Merge "Fix recent apps in system UI for Skia pipeline" into oc-dev

This commit is contained in:
TreeHugger Robot
2017-05-13 01:41:53 +00:00
committed by Android (Google) Code Review
12 changed files with 192 additions and 30 deletions

View File

@@ -60,14 +60,17 @@ static void Shader_safeUnref(JNIEnv* env, jobject o, jlong shaderHandle) {
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
jint tileModeX, jint tileModeY) {
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
SkBitmap bitmap;
sk_sp<SkImage> image;
if (jbitmap) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
image = android::bitmap::toBitmap(env, jbitmap).makeImage(nullptr);
}
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
if (!image.get()) {
SkBitmap bitmap;
image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
}
sk_sp<SkShader> baseShader = image->makeShader(
(SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);

View File

@@ -16,6 +16,7 @@
#include "Bitmap.h"
#include "Caches.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"
@@ -34,11 +35,15 @@
#include <private/gui/ComposerService.h>
#include <binder/IServiceManager.h>
#include <ui/PixelFormat.h>
#include <GrTexture.h>
#include <SkCanvas.h>
#include <SkImagePriv.h>
namespace android {
Mutex Bitmap::gLock;
static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
int32_t rowBytes32 = SkToS32(rowBytes);
int64_t bigSize = (int64_t) height * rowBytes32;
@@ -317,8 +322,7 @@ sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
return nullptr;
}
SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
kRGBA_8888_SkColorType, kPremul_SkAlphaType,
SkColorSpace::MakeSRGB());
kRGBA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
}
@@ -393,6 +397,7 @@ Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info)
mPixelStorage.hardware.buffer = buffer;
buffer->incStrong(buffer);
mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
setImmutable(); // HW bitmaps are always immutable
}
Bitmap::~Bitmap() {
@@ -486,7 +491,13 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) {
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
if (isHardware()) {
outBitmap->allocPixels(info());
if (uirenderer::Properties::isSkiaEnabled()) {
// TODO: add color correctness for Skia pipeline - pass null color space for now
outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
info().colorType(), info().alphaType(), nullptr));
} else {
outBitmap->allocPixels(info());
}
uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
return;
}
@@ -512,4 +523,28 @@ GraphicBuffer* Bitmap::graphicBuffer() {
return nullptr;
}
sk_sp<SkImage> Bitmap::makeImage(const uirenderer::renderthread::RenderThread* renderThread) {
AutoMutex _lock(gLock); //TODO: implement lock free solution
auto image = mImage;
//TODO: use new API SkImage::isValid() instead of SkImage::getTexture()->getContext()
if (!image.get() || (image->getTexture() && nullptr == image->getTexture()->getContext())) {
if (isHardware() && uirenderer::RenderPipelineType::SkiaGL
== uirenderer::Properties::getRenderPipelineType()) {
//TODO: add Vulkan support
if (renderThread) {
image = uirenderer::skiapipeline::SkiaOpenGLPipeline::makeTextureImage(
*renderThread, this);
} else {
image = uirenderer::renderthread::RenderProxy::makeTextureImage(this);
}
} else {
SkBitmap skiaBitmap;
getSkBitmapForShaders(&skiaBitmap);
image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
}
mImage = image;
}
return image;
}
} // namespace android

View File

@@ -22,6 +22,8 @@
#include <SkPixelRef.h>
#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>
#include <utils/Mutex.h>
#include <SkImage.h>
namespace android {
@@ -111,6 +113,13 @@ public:
}
GraphicBuffer* graphicBuffer();
// makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
// If invoked on the render thread, then RenderThread* argument is required.
// If not invoked on the render thread, then RenderThread* must be nullptr.
// makeImage is wrapping a gralloc buffer with an EGLImage and is passing a texture to Skia.
// This is a temporary implementation until Skia can wrap the gralloc buffer in a SkImage.
sk_sp<SkImage> makeImage(const uirenderer::renderthread::RenderThread*);
protected:
virtual bool onNewLockPixels(LockRec* rec) override;
virtual void onUnlockPixels() override { };
@@ -145,6 +154,9 @@ private:
GraphicBuffer* buffer;
} hardware;
} mPixelStorage;
sk_sp<SkImage> mImage;
static Mutex gLock;
};
} //namespace android

View File

@@ -28,6 +28,8 @@
#include <cutils/properties.h>
#include <strings.h>
#include <SkImagePriv.h>
#include <gl/GrGLTypes.h>
using namespace android::uirenderer::renderthread;
@@ -197,6 +199,87 @@ void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* func
}
}
static void deleteImageTexture(void* context) {
EGLImageKHR EGLimage = reinterpret_cast<EGLImageKHR>(context);
if (EGLimage != EGL_NO_IMAGE_KHR) {
EGLDisplay display = eglGetCurrentDisplay();
if (EGL_NO_DISPLAY == display) {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
eglDestroyImageKHR(display, EGLimage);
}
}
sk_sp<SkImage> SkiaOpenGLPipeline::makeTextureImage(
const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap) {
renderThread.eglManager().initialize();
GraphicBuffer* buffer = bitmap->graphicBuffer();
EGLDisplay display = eglGetCurrentDisplay();
if (EGL_NO_DISPLAY == display) {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
LOG_ALWAYS_FATAL_IF(!bitmap->isHardware(),
"Texture image requires a HW bitmap.");
// We use an EGLImage to access the content of the GraphicBuffer
// The EGL image is later bound to a 2D texture
EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
EGLImageKHR EGLimage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
clientBuffer, imageAttrs);
if (EGLimage == EGL_NO_IMAGE_KHR) {
ALOGW("Could not create EGL image, err =%s",
uirenderer::renderthread::EglManager::eglErrorString());
return nullptr;
}
GLuint textureId = 0;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, EGLimage);
GLenum status = GL_NO_ERROR;
while ((status = glGetError()) != GL_NO_ERROR) {
ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
eglDestroyImageKHR(display, EGLimage);
return nullptr;
}
sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
grContext->resetContext();
GrGLTextureInfo textureInfo;
textureInfo.fTarget = GL_TEXTURE_EXTERNAL_OES;
textureInfo.fID = textureId;
GrBackendTextureDesc textureDescription;
textureDescription.fWidth = bitmap->info().width();
textureDescription.fHeight = bitmap->info().height();
textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&textureInfo);
PixelFormat format = buffer->getPixelFormat();
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
break;
case PIXEL_FORMAT_RGBA_FP16:
textureDescription.fConfig = kRGBA_half_GrPixelConfig;
break;
default:
eglDestroyImageKHR(display, EGLimage);
return nullptr;
}
// TODO: add color correctness - pass null color space for now
sk_sp<SkImage> image = SkImage::MakeFromTexture(grContext.get(), textureDescription,
bitmap->info().alphaType(), nullptr, deleteImageTexture, EGLimage);
if (!image.get()) {
eglDestroyImageKHR(display, EGLimage);
return nullptr;
}
return image;
}
} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */

View File

@@ -46,6 +46,8 @@ public:
bool isContextReady() override;
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
static sk_sp<SkImage> makeTextureImage(
const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap);
private:
renderthread::EglManager& mEglManager;

View File

@@ -61,6 +61,7 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4
textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
CopyResult copyResult = CopyResult::UnknownError;
// TODO: add color correctness - pass null color space for now
sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription));
if (image) {
SkAutoLockPixels alp(*bitmap);

View File

@@ -155,11 +155,11 @@ void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
GrContext* context = thread.getGrContext();
if (context) {
ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
SkBitmap skiaBitmap;
bitmap->getSkBitmap(&skiaBitmap);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
SkImage_pinAsTexture(image.get(), context);
SkImage_unpinAsTexture(image.get(), context);
auto image = bitmap->makeImage(&thread);
if (image.get() && !bitmap->isHardware()) {
SkImage_pinAsTexture(image.get(), context);
SkImage_unpinAsTexture(image.get(), context);
}
}
}

View File

@@ -168,11 +168,8 @@ inline static const SkPaint* nonAAPaint(const SkPaint* origPaint, SkPaint* tmpPa
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
SkBitmap skBitmap;
bitmap.getSkBitmap(&skBitmap);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
if (!skBitmap.isImmutable()) {
sk_sp<SkImage> image = bitmap.makeImage(nullptr);
if (!bitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -181,12 +178,10 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, cons
void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
SkAutoCanvasRestore acr(&mRecorder, true);
concat(matrix);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
if (!bitmap.isImmutable()) {
sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
if (!hwuiBitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -196,12 +191,10 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
float dstBottom, const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
if (!bitmap.isImmutable()) {
sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
if (!hwuiBitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -210,11 +203,8 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float sr
void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
SkCanvas::Lattice lattice;
NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
lattice.fFlags = nullptr;
int numFlags = 0;
@@ -231,8 +221,8 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
if (!bitmap.isImmutable()) {
sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
if (!hwuiBitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}

View File

@@ -693,6 +693,18 @@ int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap)
}
}
CREATE_BRIDGE2(makeTextureImage, RenderThread* thread, Bitmap* bitmap) {
return args->thread->makeTextureImage(args->bitmap).release();
}
sk_sp<SkImage> RenderProxy::makeTextureImage(Bitmap* bitmap) {
SETUP_TASK(makeTextureImage);
args->bitmap = bitmap;
args->thread = &RenderThread::getInstance();
sk_sp<SkImage> hardwareImage(reinterpret_cast<SkImage*>(staticPostAndWait(task)));
return hardwareImage;
}
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}

View File

@@ -135,6 +135,8 @@ public:
static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
static sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
private:
RenderThread& mRenderThread;
CanvasContext* mContext;

View File

@@ -17,6 +17,7 @@
#include "RenderThread.h"
#include "../renderstate/RenderState.h"
#include "../pipeline/skia/SkiaOpenGLPipeline.h"
#include "../pipeline/skia/SkiaOpenGLReadback.h"
#include "CanvasContext.h"
#include "EglManager.h"
@@ -433,6 +434,24 @@ RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
return next;
}
sk_sp<SkImage> RenderThread::makeTextureImage(Bitmap* bitmap) {
auto renderType = Properties::getRenderPipelineType();
sk_sp<SkImage> hardwareImage;
switch (renderType) {
case RenderPipelineType::SkiaGL:
hardwareImage = skiapipeline::SkiaOpenGLPipeline::makeTextureImage(*this, bitmap);
break;
case RenderPipelineType::SkiaVulkan:
//TODO: add Vulkan support
break;
default:
LOG_ALWAYS_FATAL("makeTextureImage: canvas context type %d not supported",
(int32_t) renderType);
break;
}
return hardwareImage;
}
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */

View File

@@ -33,6 +33,7 @@
namespace android {
class Bitmap;
class DisplayEventReceiver;
namespace uirenderer {
@@ -104,6 +105,8 @@ public:
VulkanManager& vulkanManager() { return *mVkManager; }
sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
protected:
virtual bool threadLoop() override;