diff options
-rw-r--r-- | core/jni/android/graphics/Shader.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 61 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.cpp | 19 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.h | 16 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/tests/common/scenes/BitmapShaders.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp | 3 |
10 files changed, 116 insertions, 63 deletions
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index f04abecade20..cff772002b14 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -1,4 +1,5 @@ #include "GraphicsJNI.h" +#include "SkColorFilter.h" #include "SkGradientShader.h" #include "SkImagePriv.h" #include "SkShader.h" @@ -64,28 +65,29 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j jint tileModeX, jint tileModeY) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); sk_sp<SkImage> image; + sk_sp<SkColorFilter> colorFilter; 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. - image = android::bitmap::toBitmap(env, jbitmap).makeImage(); + image = android::bitmap::toBitmap(env, jbitmap).makeImage(&colorFilter); } if (!image.get()) { SkBitmap bitmap; image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode); } - sk_sp<SkShader> baseShader = image->makeShader( + sk_sp<SkShader> shader = image->makeShader( (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); - SkShader* shader; if (matrix) { - shader = baseShader->makeWithLocalMatrix(*matrix).release(); - } else { - shader = baseShader.release(); + shader = shader->makeWithLocalMatrix(*matrix); + } + if(colorFilter) { + shader = shader->makeWithColorFilter(colorFilter); } - ThrowIAE_IfNull(env, shader); - return reinterpret_cast<jlong>(shader); + ThrowIAE_IfNull(env, shader.get()); + return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index c19c1a11e3e2..8727a1d20dfd 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -296,6 +296,7 @@ void GlopBuilder::setFill(int color, float alphaScale, colorVector[2] = EOCF(srcColorMatrix[14] / 255.0f); colorVector[3] = srcColorMatrix[19] / 255.0f; // alpha is linear } else { + ALOGE("unsupported ColorFilter type: %s", colorFilter->getTypeName()); LOG_ALWAYS_FATAL("unsupported ColorFilter"); } } else { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 0a642b60d4c7..9683d0614e26 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -24,6 +24,8 @@ #include "pipeline/skia/AnimatedDrawables.h" #include <SkCanvasStateUtils.h> +#include <SkColorFilter.h> +// TODO remove me! #include <SkColorSpaceXformCanvas.h> #include <SkDrawable.h> #include <SkDeque.h> @@ -529,25 +531,49 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- +inline static const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint, + sk_sp<SkColorFilter> colorFilter) { + if (colorFilter) { + if (origPaint) { + *tmpPaint = *origPaint; + } + tmpPaint->setColorFilter(colorFilter); + return tmpPaint; + } else { + return origPaint; + } +} + void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { - mCanvas->drawImage(bitmap.makeImage(), left, top, paint); + SkPaint tmpPaint; + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter)); } -void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) { +void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkAutoCanvasRestore acr(mCanvas, true); mCanvas->concat(matrix); - mCanvas->drawImage(hwuiBitmap.makeImage(), 0, 0, paint); + + SkPaint tmpPaint; + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter)); } -void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop, +void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); - mCanvas->drawImageRect(hwuiBitmap.makeImage(), srcRect, dstRect, paint); + + SkPaint tmpPaint; + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter)); } -void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeight, +void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) { const int ptCount = (meshWidth + 1) * (meshHeight + 1); const int indexCount = meshWidth * meshHeight * 6; @@ -565,8 +591,8 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh // cons up texture coordinates and indices { - const SkScalar w = SkIntToScalar(hwuiBitmap.width()); - const SkScalar h = SkIntToScalar(hwuiBitmap.height()); + const SkScalar w = SkIntToScalar(bitmap.width()); + const SkScalar h = SkIntToScalar(bitmap.height()); const SkScalar dx = w / meshWidth; const SkScalar dy = h / meshHeight; @@ -627,17 +653,22 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh tmpPaint = *paint; } - sk_sp<SkImage> image = hwuiBitmap.makeImage(); - tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)); + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + sk_sp<SkShader> shader = image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); + if(colorFilter) { + shader = shader->makeWithColorFilter(colorFilter); + } + tmpPaint.setShader(shader); mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint); } -void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk, +void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { SkCanvas::Lattice lattice; - NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height()); + NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); lattice.fFlags = nullptr; int numFlags = 0; @@ -654,7 +685,11 @@ void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk, lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); - mCanvas->drawImageLattice(hwuiBitmap.makeImage().get(), lattice, dst, paint); + + SkPaint tmpPaint; + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter)); } void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) { diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 75b6d233643d..0aeb7627233a 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -31,6 +31,7 @@ #include <ui/PixelFormat.h> #include <SkCanvas.h> +#include <SkToSRGBColorFilter.h> #include <SkImagePriv.h> namespace android { @@ -208,11 +209,8 @@ Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info) buffer->incStrong(buffer); setImmutable(); // HW bitmaps are always immutable if (uirenderer::Properties::isSkiaEnabled()) { - // GraphicBuffer should be in the display color space (Bitmap::createFrom is always - // passing SRGB). The code that uploads into a GraphicBuffer should do color conversion if - // needed. mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast<AHardwareBuffer*>(buffer), - mInfo.alphaType(), nullptr); + mInfo.alphaType(), mInfo.refColorSpace()); } } @@ -319,7 +317,7 @@ GraphicBuffer* Bitmap::graphicBuffer() { return nullptr; } -sk_sp<SkImage> Bitmap::makeImage() { +sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) { sk_sp<SkImage> image = mImage; if (!image) { SkASSERT(!(isHardware() && uirenderer::Properties::isSkiaEnabled())); @@ -330,12 +328,11 @@ sk_sp<SkImage> Bitmap::makeImage() { // Note we don't cache in this case, because the raster image holds a pointer to this Bitmap // internally and ~Bitmap won't be invoked. // TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here. - if (uirenderer::Properties::isSkiaEnabled()) { - image = SkMakeImageInColorSpace(skiaBitmap, SkColorSpace::MakeSRGB(), - skiaBitmap.getGenerationID(), kNever_SkCopyPixelsMode); - } else { - image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode); - } + image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode); + } + if(uirenderer::Properties::isSkiaEnabled() && image->colorSpace() != nullptr + && !image->colorSpace()->isSRGB()) { + *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace()); } return image; } diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 634e76450c38..fc27af9fb4e7 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -16,6 +16,7 @@ #pragma once #include <SkBitmap.h> +#include <SkColorFilter.h> #include <SkColorSpace.h> #include <SkImage.h> #include <SkImageInfo.h> @@ -96,9 +97,18 @@ public: GraphicBuffer* graphicBuffer(); - // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread. - // Caching is supported only for HW Bitmaps with skia pipeline. - sk_sp<SkImage> makeImage(); + /** + * Creates or returns a cached SkImage and is safe to be invoked from either + * the UI or RenderThread. + * + * @param outputColorFilter is a required param that will be populated by + * this function if the bitmap's colorspace is not sRGB. If populated the + * filter will convert colors from the bitmaps colorspace into sRGB. It + * is the callers responsibility to use this colorFilter when drawing + * this image into any destination that is presumed to be sRGB (i.e. a + * buffer that has no colorspace defined). + */ + sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter); private: virtual ~Bitmap(); void* getStorage() const; diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index bf774460f04e..5f8ee180bd09 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -305,12 +305,6 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr return nullptr; } - auto colorSpace = info.colorSpace(); - bool convertToSRGB = false; - if (colorSpace && (!colorSpace->isSRGB())) { - isSupported = false; - convertToSRGB = true; - } SkBitmap bitmap; if (isSupported) { @@ -319,7 +313,7 @@ sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThr bitmap.allocPixels(SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(), nullptr)); bitmap.eraseColor(0); - if (info.colorType() == kRGBA_F16_SkColorType || convertToSRGB) { + if (info.colorType() == kRGBA_F16_SkColorType) { // Drawing RGBA_F16 onto ARGB_8888 is not supported skBitmap.readPixels(bitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()), bitmap.getPixels(), bitmap.rowBytes(), 0, 0); diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index d08a62c830ad..a8463ecc44d8 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -167,7 +167,8 @@ void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) { GrContext* context = thread.getGrContext(); if (context) { ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height()); - auto image = bitmap->makeImage(); + sk_sp<SkColorFilter> colorFilter; + auto image = bitmap->makeImage(&colorFilter); 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 a0cce98c8d57..6c88e93bd150 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -145,10 +145,14 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { // Recording Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- -inline static const SkPaint* nonAAPaint(const SkPaint* origPaint, SkPaint* tmpPaint) { - if (origPaint && origPaint->isAntiAlias()) { - *tmpPaint = *origPaint; +inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint, + sk_sp<SkColorFilter> colorFilter) { + if ((origPaint && origPaint->isAntiAlias()) || colorFilter) { + if (origPaint) { + *tmpPaint = *origPaint; + } tmpPaint->setAntiAlias(false); + tmpPaint->setColorFilter(colorFilter); return tmpPaint; } else { return origPaint; @@ -156,9 +160,10 @@ inline static const SkPaint* nonAAPaint(const SkPaint* origPaint, SkPaint* tmpPa } void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { - sk_sp<SkImage> image = bitmap.makeImage(); SkPaint tmpPaint; - mRecorder.drawImage(image, left, top, nonAAPaint(paint, &tmpPaint)); + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mRecorder.drawImage(image, left, top, bitmapPaint(paint, &tmpPaint, colorFilter)); // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means // it is not safe to store a raw SkImage pointer, because the image object will be destroyed // when this function ends. @@ -167,36 +172,40 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, cons } } -void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, +void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkAutoCanvasRestore acr(&mRecorder, true); concat(matrix); - sk_sp<SkImage> image = hwuiBitmap.makeImage(); + SkPaint tmpPaint; - mRecorder.drawImage(image, 0, 0, nonAAPaint(paint, &tmpPaint)); - if (!hwuiBitmap.isImmutable() && image.get() && !image->unique()) { + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mRecorder.drawImage(image, 0, 0, bitmapPaint(paint, &tmpPaint, colorFilter)); + if (!bitmap.isImmutable() && image.get() && !image->unique()) { mDisplayList->mMutableImages.push_back(image.get()); } } -void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop, +void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); - sk_sp<SkImage> image = hwuiBitmap.makeImage(); + SkPaint tmpPaint; - mRecorder.drawImageRect(image, srcRect, dstRect, nonAAPaint(paint, &tmpPaint)); - if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter)); + if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() && !dstRect.isEmpty()) { mDisplayList->mMutableImages.push_back(image.get()); } } -void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk, +void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { SkCanvas::Lattice lattice; - NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height()); + NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); lattice.fFlags = nullptr; int numFlags = 0; @@ -213,11 +222,13 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); - sk_sp<SkImage> image = hwuiBitmap.makeImage(); SkPaint tmpPaint; - mRecorder.drawImageLattice(image.get(), lattice, dst, nonAAPaint(paint, &tmpPaint)); - if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) { + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); + mRecorder.drawImageLattice(image.get(), lattice, dst, + bitmapPaint(paint, &tmpPaint, colorFilter)); + if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) { mDisplayList->mMutableImages.push_back(image.get()); } } diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp index 4797dec8e89e..0f2dc034d125 100644 --- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp +++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp @@ -46,7 +46,8 @@ public: }); SkPaint paint; - sk_sp<SkImage> image = hwuiBitmap->makeImage(); + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = hwuiBitmap->makeImage(&colorFilter); sk_sp<SkShader> repeatShader = image->makeShader( SkShader::TileMode::kRepeat_TileMode, SkShader::TileMode::kRepeat_TileMode, diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp index c246ebaddcad..960b05340063 100644 --- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp +++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp @@ -75,7 +75,8 @@ public: void doFrame(int frameNr) override { } sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) { - sk_sp<SkImage> image = bitmap.makeImage(); + sk_sp<SkColorFilter> colorFilter; + sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); return image->makeShader(SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode); } |