diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 6419aa43dd4e2..adfc98ec2f840 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -52,7 +52,7 @@ public: } bool valid() { - return !!mBitmap; + return mBitmap; } Bitmap& bitmap() { diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index 9c3505490d277..d79325a464168 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -407,8 +407,7 @@ static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject j jlong matrixHandle, jlong paintHandle) { const SkMatrix* matrix = reinterpret_cast(matrixHandle); const Paint* paint = reinterpret_cast(paintHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); } @@ -419,8 +418,7 @@ static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbi Canvas* canvas = get_canvas(canvasHandle); const Paint* paint = reinterpret_cast(paintHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); if (screenDensity != 0 && screenDensity != bitmapDensity) { Paint filteredPaint; if (paint) { diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index f35d6052da058..f2ae847b1952e 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -631,13 +631,15 @@ void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) { } void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) { - const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty(); + SkBitmap bitmap; + op.vectorDrawable->getBitmapUpdateIfDirty().getSkBitmap(&bitmap); + SkBitmap* localBitmap = mAllocator.create(bitmap); SkPaint* paint = op.vectorDrawable->getPaint(); const BitmapRectOp* resolvedOp = mAllocator.create_trivial(op.unmappedBounds, op.localMatrix, op.localClip, paint, - &bitmap, + localBitmap, Rect(bitmap.width(), bitmap.height())); deferBitmapRectOp(*resolvedOp); } diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 2730ed9abec58..d25202690c19e 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -478,8 +478,10 @@ void RecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Sk restore(); } -void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, +void RecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) { + SkBitmap bitmap; + hwuiBitmap.getSkBitmap(&bitmap); if (matrix.isIdentity()) { drawBitmap(&bitmap, paint); } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) @@ -490,7 +492,7 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, SkRect dst; bitmap.getBounds(&src); matrix.mapRect(&dst, src); - drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, + drawBitmap(hwuiBitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint); } else { save(SaveFlags::Matrix); @@ -500,9 +502,11 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, } } -void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, +void RecordingCanvas::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); if (srcLeft == 0 && srcTop == 0 && srcRight == bitmap.width() && srcBottom == bitmap.height() diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index c5ed61c1c65f7..cdb8dfc2002dc 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -177,9 +177,8 @@ public: // Bitmap-based virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override; - virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, - const SkPaint* paint) override; - virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, + virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override; + virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) override; virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index c99219f37c2d8..ab899f9f831c6 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -497,15 +497,19 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint mCanvas->drawBitmap(skBitmap, left, top, paint); } -void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { +void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) { + SkBitmap bitmap; + hwuiBitmap.getSkBitmap(&bitmap); SkAutoCanvasRestore acr(mCanvas.get(), true); mCanvas->concat(matrix); mCanvas->drawBitmap(bitmap, 0, 0, paint); } -void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, +void SkiaCanvas::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); mCanvas->drawBitmapRect(bitmap, srcRect, dstRect, paint); diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 9c4d7c42c647d..49aea8e5e35ad 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -125,9 +125,8 @@ public: const uint16_t* indices, int indexCount, const SkPaint& paint) override; virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override; - virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, - const SkPaint* paint) override; - virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, + virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override; + virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) override; virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index 6620458cefb64..863146e36d291 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -107,16 +107,12 @@ void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) { void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) { - SkPixelRef* pxRef = bitmap.pixelRef(); - + sk_sp hwuiBitmap = Bitmap::createFrom(bitmap.info(), *bitmap.pixelRef()); // HWUI doesn't support extractSubset(), so convert any subsetted bitmap into // a drawBitmapRect(); pass through an un-subsetted bitmap. - if (pxRef && bitmap.dimensions() != pxRef->info().dimensions()) { - SkBitmap fullBitmap; - fullBitmap.setInfo(pxRef->info()); - fullBitmap.setPixelRef(pxRef, 0, 0); + if (hwuiBitmap && bitmap.dimensions() != hwuiBitmap->info().dimensions()) { SkIPoint origin = bitmap.pixelRefOrigin(); - mCanvas->drawBitmap(fullBitmap, origin.fX, origin.fY, + mCanvas->drawBitmap(*hwuiBitmap, origin.fX, origin.fY, origin.fX + bitmap.dimensions().width(), origin.fY + bitmap.dimensions().height(), left, top, @@ -124,16 +120,16 @@ void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScal top + bitmap.dimensions().height(), paint); } else { - auto hwuiBitmap= Bitmap::createFrom(bitmap.info(), *pxRef); mCanvas->drawBitmap(*hwuiBitmap, left, top, paint); } } -void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* srcPtr, +void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr, const SkRect& dst, const SkPaint* paint, SrcRectConstraint) { - SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(bitmap.width(), bitmap.height()); + SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height()); // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src? - mCanvas->drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, + Bitmap* bitmap = reinterpret_cast(skBitmap.pixelRef()); + mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint); } diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 715681d5fca6d..b50647adc0beb 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -502,18 +502,18 @@ int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, } void Tree::drawStaging(Canvas* outCanvas) { - bool redrawNeeded = allocateBitmapIfNeeded(&mStagingCache.bitmap, + bool redrawNeeded = allocateBitmapIfNeeded(mStagingCache, mStagingProperties.getScaledWidth(), mStagingProperties.getScaledHeight()); // draw bitmap cache if (redrawNeeded || mStagingCache.dirty) { - updateBitmapCache(&mStagingCache.bitmap, true); + updateBitmapCache(*mStagingCache.bitmap, true); mStagingCache.dirty = false; } SkPaint tmpPaint; SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties); - outCanvas->drawBitmap(mStagingCache.bitmap, 0, 0, - mStagingCache.bitmap.width(), mStagingCache.bitmap.height(), + outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0, + mStagingCache.bitmap->width(), mStagingCache.bitmap->height(), mStagingProperties.getBounds().left(), mStagingProperties.getBounds().top(), mStagingProperties.getBounds().right(), mStagingProperties.getBounds().bottom(), paint); } @@ -535,46 +535,46 @@ SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) { } } -const SkBitmap& Tree::getBitmapUpdateIfDirty() { - bool redrawNeeded = allocateBitmapIfNeeded(&mCache.bitmap, mProperties.getScaledWidth(), +Bitmap& Tree::getBitmapUpdateIfDirty() { + bool redrawNeeded = allocateBitmapIfNeeded(mCache, mProperties.getScaledWidth(), mProperties.getScaledHeight()); if (redrawNeeded || mCache.dirty) { - updateBitmapCache(&mCache.bitmap, false); + updateBitmapCache(*mCache.bitmap, false); mCache.dirty = false; } - return mCache.bitmap; + return *mCache.bitmap; } -void Tree::updateBitmapCache(SkBitmap* outCache, bool useStagingData) { - outCache->eraseColor(SK_ColorTRANSPARENT); - SkCanvas outCanvas(*outCache); +void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) { + SkBitmap outCache; + bitmap.getSkBitmap(&outCache); + outCache.eraseColor(SK_ColorTRANSPARENT); + SkCanvas outCanvas(outCache); float viewportWidth = useStagingData ? mStagingProperties.getViewportWidth() : mProperties.getViewportWidth(); float viewportHeight = useStagingData ? mStagingProperties.getViewportHeight() : mProperties.getViewportHeight(); - float scaleX = outCache->width() / viewportWidth; - float scaleY = outCache->height() / viewportHeight; + float scaleX = outCache.width() / viewportWidth; + float scaleY = outCache.height() / viewportHeight; mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY, useStagingData); } -bool Tree::allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height) { - if (!canReuseBitmap(*outCache, width, height)) { +bool Tree::allocateBitmapIfNeeded(Cache& cache, int width, int height) { + if (!canReuseBitmap(cache.bitmap.get(), width, height)) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING sk_sp colorSpace = nullptr; #else sk_sp colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); #endif SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace); - outCache->setInfo(info); - // TODO: Count the bitmap cache against app's java heap - outCache->allocPixels(info); + cache.bitmap = Bitmap::allocateHeapBitmap(info); return true; } return false; } -bool Tree::canReuseBitmap(const SkBitmap& bitmap, int width, int height) { - return width == bitmap.width() && height == bitmap.height(); +bool Tree::canReuseBitmap(Bitmap* bitmap, int width, int height) { + return bitmap && width == bitmap->width() && height == bitmap->height(); } void Tree::onPropertyChanged(TreeProperties* prop) { diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index e68fbf4c62432..e9a9c719975a4 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -18,6 +18,7 @@ #define ANDROID_HWUI_VPATH_H #include "hwui/Canvas.h" +#include "hwui/Bitmap.h" #include "DisplayList.h" #include @@ -561,7 +562,7 @@ public: const SkRect& bounds, bool needsMirroring, bool canReuseCache); void drawStaging(Canvas* canvas); - const SkBitmap& getBitmapUpdateIfDirty(); + Bitmap& getBitmapUpdateIfDirty(); void setAllowCaching(bool allowCaching) { mAllowCaching = allowCaching; } @@ -691,11 +692,15 @@ public: void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; } private: + struct Cache { + sk_sp bitmap; + bool dirty = true; + }; SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop); - bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height); - bool canReuseBitmap(const SkBitmap&, int width, int height); - void updateBitmapCache(SkBitmap* outCache, bool useStagingData); + bool allocateBitmapIfNeeded(Cache& cache, int width, int height); + bool canReuseBitmap(Bitmap*, int width, int height); + void updateBitmapCache(Bitmap& outCache, bool useStagingData); // Cap the bitmap size, such that it won't hurt the performance too much // and it won't crash due to a very large scale. // The drawable will look blurry above this size. @@ -708,10 +713,6 @@ private: TreeProperties mStagingProperties = TreeProperties(this); SkPaint mPaint; - struct Cache { - SkBitmap bitmap; - bool dirty = true; - }; Cache mStagingCache; Cache mCache; diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 341ece3478c1b..d9534f2c4fec8 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -23,9 +23,9 @@ namespace android { -static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) { - int32_t rowBytes32 = SkToS32(bitmap.rowBytes()); - int64_t bigSize = (int64_t)bitmap.height() * rowBytes32; +static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) { + int32_t rowBytes32 = SkToS32(rowBytes); + int64_t bigSize = (int64_t) height * rowBytes32; if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) { return false; // allocation will be too large } @@ -45,13 +45,14 @@ static sk_sp allocateBitmap(SkBitmap* bitmap, SkColorTable* ctable, Allo } size_t size; - if (!computeAllocationSize(*bitmap, &size)) { - return nullptr; - } // we must respect the rowBytes value already set on the bitmap instead of // attempting to compute our own. const size_t rowBytes = bitmap->rowBytes(); + if (!computeAllocationSize(rowBytes, bitmap->height(), &size)) { + return nullptr; + } + auto wrapper = alloc(size, info, rowBytes, ctable); if (wrapper) { wrapper->getSkBitmap(bitmap); @@ -62,15 +63,11 @@ static sk_sp allocateBitmap(SkBitmap* bitmap, SkColorTable* ctable, Allo return wrapper; } -sk_sp Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) { - return allocateBitmap(bitmap, ctable, &Bitmap::allocateHeapBitmap); -} - sk_sp Bitmap::allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable) { return allocateBitmap(bitmap, ctable, &Bitmap::allocateAshmemBitmap); } -sk_sp Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes, +static sk_sp allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) { void* addr = calloc(size, 1); if (!addr) { @@ -79,6 +76,19 @@ sk_sp Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, s return sk_sp(new Bitmap(addr, size, info, rowBytes, ctable)); } +sk_sp Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) { + return allocateBitmap(bitmap, ctable, &android::allocateHeapBitmap); +} + +sk_sp Bitmap::allocateHeapBitmap(const SkImageInfo& info) { + size_t size; + if (!computeAllocationSize(info.minRowBytes(), info.height(), &size)) { + LOG_ALWAYS_FATAL("trying to allocate too large bitmap"); + return nullptr; + } + return android::allocateHeapBitmap(size, info, info.minRowBytes(), nullptr); +} + sk_sp Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) { // Create new ashmem region with read/write priv diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 2a5d00b9860ac..029d80d6279fc 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -34,8 +34,7 @@ typedef void (*FreeFunc)(void* addr, void* context); class ANDROID_API Bitmap : public SkPixelRef { public: static sk_sp allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable); - static sk_sp allocateHeapBitmap(size_t allocSize, const SkImageInfo& info, - size_t rowBytes, SkColorTable* ctable); + static sk_sp allocateHeapBitmap(const SkImageInfo& info); static sk_sp allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable); static sk_sp allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info, diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 8d0860823e1d2..baee8fdabf904 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -220,9 +220,9 @@ public: // Bitmap-based virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) = 0; - virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, + virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) = 0; - virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, + virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) = 0; virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index cdfa2f474233d..b8dfb011ff137 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -125,8 +125,7 @@ public: static sk_sp createBitmap(int width, int height, SkColorType colorType = kN32_SkColorType) { SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType); - size_t size = height * info.minRowBytes(); - return Bitmap::allocateHeapBitmap(size, info, info.minRowBytes(), nullptr); + return Bitmap::allocateHeapBitmap(info); } static sk_sp createBitmap(int width, int height, SkBitmap* outBitmap) { diff --git a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp index 584f6841d4ad2..825602466f92a 100644 --- a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp +++ b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp @@ -45,12 +45,14 @@ public: int x = dp(32); for (int i = 0; i < 4; i++) { int y = (height / 4) * i; - SkBitmap thumb = TestUtils::createSkBitmap(thumbnailSize, thumbnailSize); - thumb.eraseColor(COLORS[i]); - sp card = createCard(x, y, cardsize, cardsize, thumb); + SkBitmap bitmap; + sk_sp thumb(TestUtils::createBitmap(thumbnailSize, thumbnailSize, &bitmap)); + + bitmap.eraseColor(COLORS[i]); + sp card = createCard(x, y, cardsize, cardsize, *thumb); card->mutateStagingProperties().setElevation(i * dp(8)); renderer.drawRenderNode(card.get()); - mThumbnail = thumb; + mThumbnail = bitmap; mCards.push_back(card); } @@ -68,8 +70,7 @@ public: } private: - sp createCard(int x, int y, int width, int height, - const SkBitmap& thumb) { + sp createCard(int x, int y, int width, int height, Bitmap& thumb) { return TestUtils::createNode(x, y, x + width, y + height, [&thumb, width, height](RenderProperties& props, Canvas& canvas) { props.setElevation(dp(16));