diff options
| -rw-r--r-- | core/jni/android/graphics/Shader.cpp | 9 | ||||
| -rw-r--r-- | libs/hwui/hwui/Bitmap.cpp | 41 | ||||
| -rw-r--r-- | libs/hwui/hwui/Bitmap.h | 12 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp | 83 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h | 2 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp | 1 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 28 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 12 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 2 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.cpp | 19 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.h | 3 |
12 files changed, 192 insertions, 30 deletions
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 214d97c213e4..b529e3745647 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -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); diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index d765584a7530..b0e486d874ca 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -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 diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index da45f7697f56..621e43979969 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -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
\ No newline at end of file diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index ae1313101f3c..4885873e232d 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -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 */ diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h index 36685ddb17a7..f3ce189df574 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h @@ -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; diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp index a18d26471a29..1a6e70949992 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp @@ -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); diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 10c1865ac50c..349d4ccfa04d 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -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); + } } } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 559d268b71f7..5d7bbfa11c7d 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -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()); } diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index a1f1717e6b96..5c2ec0ea3c88 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -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); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index a60ed55c70d2..97ad796b6065 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -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; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 1450ec98dabf..d62b55633e2d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -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 */ diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 9bc5985e5b16..34542c6021ec 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -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; |