Use Bitmap in DisplayList & RecordedOps instead of SkBitmap
Test: refactoring cl.
bug:32216791

Change-Id: I1d8a9a6e772e2176b6c2409409a910478b45f8db
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 840c79d..6079d5d 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -46,7 +46,7 @@
         const MergedBakedOpList& opList) {
 
     const BakedOpState& firstState = *(opList.states[0]);
-    const SkBitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;
+    Bitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;
 
     Texture* texture = renderer.caches().textureCache.get(bitmap);
     if (!texture) return;
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index ac7a600..e8972aa 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -181,7 +181,7 @@
     if (!mRenderTarget.frameBufferId) mHasDrawn = true;
 }
 
-Texture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) {
+Texture* BakedOpRenderer::getTexture(Bitmap* bitmap) {
     return mCaches.textureCache.get(bitmap);
 }
 
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 62bc564..4d76a3d 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -74,7 +74,7 @@
     void endLayer();
     WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
 
-    Texture* getTexture(const SkBitmap* bitmap);
+    Texture* getTexture(Bitmap* bitmap);
     const LightInfo& getLightInfo() const { return mLightInfo; }
 
     void renderGlop(const BakedOpState& state, const Glop& glop) {
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 6e7d11f..5213d48 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -106,9 +106,9 @@
 bool DisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
         std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
     TextureCache& cache = Caches::getInstance().textureCache;
-    for (auto&& bitmapResource : bitmapResources) {
+    for (auto& bitmapResource : bitmapResources) {
         void* ownerToken = &info.canvasContext;
-        info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource);
+        info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource.get());
     }
     for (auto&& op : children) {
         RenderNode* childNode = op->renderNode;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 06b0891..cab092f 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -38,6 +38,7 @@
 #include "Matrix.h"
 #include "RenderProperties.h"
 #include "TreeInfo.h"
+#include "hwui/Bitmap.h"
 
 #include <vector>
 
@@ -101,7 +102,7 @@
 
     const LsaVector<NodeOpType*>& getChildren() const { return children; }
 
-    const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
+    const LsaVector<sk_sp<Bitmap>>& getBitmapResources() const { return bitmapResources; }
 
     size_t addChild(NodeOpType* childOp);
 
@@ -140,7 +141,7 @@
     LsaVector<NodeOpType*> children;
 
     // Resources - Skia objects + 9 patches referred to by this DisplayList
-    LsaVector<const SkBitmap*> bitmapResources;
+    LsaVector<sk_sp<Bitmap>> bitmapResources;
     LsaVector<const SkPath*> pathResources;
     LsaVector<const Res_png_9patch*> patchResources;
     LsaVector<std::unique_ptr<const SkPaint>> paints;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index f2ae847..245db1d 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -631,15 +631,13 @@
 }
 
 void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
-    SkBitmap bitmap;
-    op.vectorDrawable->getBitmapUpdateIfDirty().getSkBitmap(&bitmap);
-    SkBitmap* localBitmap = mAllocator.create<SkBitmap>(bitmap);
+    Bitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
     SkPaint* paint = op.vectorDrawable->getPaint();
     const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(op.unmappedBounds,
             op.localMatrix,
             op.localClip,
             paint,
-            localBitmap,
+            &bitmap,
             Rect(bitmap.width(), bitmap.height()));
     deferBitmapRectOp(*resolvedOp);
 }
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 3b1caa5..f9a7c36f2 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -211,14 +211,14 @@
 };
 
 struct BitmapOp : RecordedOp {
-    BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
+    BitmapOp(BASE_PARAMS, Bitmap* bitmap)
             : SUPER(BitmapOp)
             , bitmap(bitmap) {}
-    const SkBitmap* bitmap;
+    Bitmap* bitmap;
 };
 
 struct BitmapMeshOp : RecordedOp {
-    BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight,
+    BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight,
             const float* vertices, const int* colors)
             : SUPER(BitmapMeshOp)
             , bitmap(bitmap)
@@ -226,7 +226,7 @@
             , meshHeight(meshHeight)
             , vertices(vertices)
             , colors(colors) {}
-    const SkBitmap* bitmap;
+    Bitmap* bitmap;
     const int meshWidth;
     const int meshHeight;
     const float* vertices;
@@ -234,11 +234,11 @@
 };
 
 struct BitmapRectOp : RecordedOp {
-    BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src)
+    BitmapRectOp(BASE_PARAMS, Bitmap* bitmap, const Rect& src)
             : SUPER(BitmapRectOp)
             , bitmap(bitmap)
             , src(src) {}
-    const SkBitmap* bitmap;
+    Bitmap* bitmap;
     const Rect src;
 };
 
@@ -288,11 +288,11 @@
 };
 
 struct PatchOp : RecordedOp {
-    PatchOp(BASE_PARAMS, const SkBitmap* bitmap, const Res_png_9patch* patch)
+    PatchOp(BASE_PARAMS, Bitmap* bitmap, const Res_png_9patch* patch)
             : SUPER(PatchOp)
             , bitmap(bitmap)
             , patch(patch) {}
-    const SkBitmap* bitmap;
+    Bitmap* bitmap;
     const Res_png_9patch* patch;
 };
 
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 77be38d..f5bcba2 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -21,7 +21,6 @@
 #include "RenderNode.h"
 #include "VectorDrawable.h"
 #include "hwui/MinikinUtils.h"
-#include "hwui/Bitmap.h"
 
 namespace android {
 namespace uirenderer {
@@ -470,20 +469,16 @@
 
 // Bitmap-based
 void RecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    SkBitmap skBitmap;
-    bitmap.getSkBitmap(&skBitmap);
     save(SaveFlags::Matrix);
     translate(left, top);
-    drawBitmap(&skBitmap, paint);
+    drawBitmap(bitmap, paint);
     restore();
 }
 
-void RecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
+void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
                             const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
     if (matrix.isIdentity()) {
-        drawBitmap(&bitmap, paint);
+        drawBitmap(bitmap, paint);
     } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
             && MathUtils::isPositive(matrix.getScaleX())
             && MathUtils::isPositive(matrix.getScaleY())) {
@@ -492,21 +487,19 @@
         SkRect dst;
         bitmap.getBounds(&src);
         matrix.mapRect(&dst, src);
-        drawBitmap(hwuiBitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
                    dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
     } else {
         save(SaveFlags::Matrix);
         concat(matrix);
-        drawBitmap(&bitmap, paint);
+        drawBitmap(bitmap, paint);
         restore();
     }
 }
 
-void RecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
+void RecordingCanvas::drawBitmap(Bitmap& bitmap, 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()
@@ -515,7 +508,7 @@
         // transform simple rect to rect drawing case into position bitmap ops, since they merge
         save(SaveFlags::Matrix);
         translate(dstLeft, dstTop);
-        drawBitmap(&bitmap, paint);
+        drawBitmap(bitmap, paint);
         restore();
     } else {
         addOp(alloc().create_trivial<BitmapRectOp>(
@@ -527,10 +520,8 @@
     }
 }
 
-void RecordingCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeight,
+void RecordingCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
             const float* vertices, const int* colors, const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
     int vertexCount = (meshWidth + 1) * (meshHeight + 1);
     addOp(alloc().create_trivial<BitmapMeshOp>(
             calcBoundsOfPoints(vertices, vertexCount * 2),
@@ -541,11 +532,9 @@
             refBuffer<int>(colors, vertexCount))); // 1 color per vertex
 }
 
-void RecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const android::Res_png_9patch& patch,
+void RecordingCanvas::drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& patch,
             float dstLeft, float dstTop, float dstRight, float dstBottom,
             const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
     addOp(alloc().create_trivial<PatchOp>(
             Rect(dstLeft, dstTop, dstRight, dstBottom),
             *(mState.currentSnapshot()->transform),
@@ -586,12 +575,12 @@
     }
 }
 
-void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
+void RecordingCanvas::drawBitmap(Bitmap& bitmap, const SkPaint* paint) {
     addOp(alloc().create_trivial<BitmapOp>(
-            Rect(bitmap->width(), bitmap->height()),
+            Rect(bitmap.width(), bitmap.height()),
             *(mState.currentSnapshot()->transform),
             getRecordedClip(),
-            refPaint(paint), refBitmap(*bitmap)));
+            refPaint(paint), refBitmap(bitmap)));
 }
 
 void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
@@ -677,7 +666,9 @@
     SkBitmap bitmap;
     SkShader::TileMode xy[2];
     if (shader->isABitmap(&bitmap, nullptr, xy)) {
-        refBitmap(bitmap);
+        // TODO: create  hwui-owned BitmapShader.
+        Bitmap* hwuiBitmap = static_cast<Bitmap*>(bitmap.pixelRef());
+        refBitmap(*hwuiBitmap);
         return;
     }
     SkShader::ComposeRec rec;
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 6a46bfa..a8fcfeb 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -22,6 +22,7 @@
 #include "ResourceCache.h"
 #include "SkiaCanvasProxy.h"
 #include "Snapshot.h"
+#include "hwui/Bitmap.h"
 #include "hwui/Canvas.h"
 #include "utils/LinearAllocator.h"
 #include "utils/Macros.h"
@@ -203,7 +204,7 @@
         return mState.writableSnapshot()->mutateClipArea().serializeClip(alloc());
     }
 
-    void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
+    void drawBitmap(Bitmap& bitmap, const SkPaint* paint);
     void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
 
 
@@ -285,14 +286,17 @@
         return cachedRegion;
     }
 
-    inline const SkBitmap* refBitmap(const SkBitmap& bitmap) {
+    inline Bitmap* refBitmap(Bitmap& bitmap) {
         // Note that this assumes the bitmap is immutable. There are cases this won't handle
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
         // contents, and drawing again. The only fix would be to always copy it the first time,
         // which doesn't seem worth the extra cycles for this unlikely case.
-        SkBitmap* localBitmap = alloc().create<SkBitmap>(bitmap);
-        mDisplayList->bitmapResources.push_back(localBitmap);
-        return localBitmap;
+
+        // this is required because sk_sp's ctor adopts the pointer,
+        // but does not increment the refcount,
+        bitmap.ref();
+        mDisplayList->bitmapResources.emplace_back(&bitmap);
+        return &bitmap;
     }
 
     inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 5d9e5c0..489a306 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -21,6 +21,7 @@
 #include "Layer.h"
 #include "Matrix.h"
 #include "Texture.h"
+#include "hwui/Bitmap.h"
 
 #include <SkMatrix.h>
 #include <utils/Log.h>
@@ -206,7 +207,9 @@
         return false;
     }
 
-    outData->bitmapTexture = caches.textureCache.get(&bitmap);
+    // TODO: create  hwui-owned BitmapShader.
+    Bitmap* hwuiBitmap = static_cast<Bitmap*>(bitmap.pixelRef());
+    outData->bitmapTexture = caches.textureCache.get(hwuiBitmap);
     if (!outData->bitmapTexture) return false;
 
     outData->bitmapSampler = (*textureUnit)++;
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 5ccdbda..08641b7 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -23,6 +23,7 @@
 #include "TextureCache.h"
 #include "Properties.h"
 #include "utils/TraceUtils.h"
+#include "hwui/Bitmap.h"
 
 namespace android {
 namespace uirenderer {
@@ -91,7 +92,7 @@
     }
 }
 
-bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
+bool TextureCache::canMakeTextureFromBitmap(Bitmap* bitmap) {
     if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
         ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
                 bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
@@ -102,8 +103,8 @@
 
 // Returns a prepared Texture* that either is already in the cache or can fit
 // in the cache (and is thus added to the cache)
-Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
-    Texture* texture = mCache.get(bitmap->pixelRef()->getStableID());
+Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
+    Texture* texture = mCache.get(bitmap->getStableID());
 
     if (!texture) {
         if (!canMakeTextureFromBitmap(bitmap)) {
@@ -126,7 +127,9 @@
             texture = new Texture(Caches::getInstance());
             texture->bitmapSize = size;
             texture->generation = bitmap->getGenerationID();
-            texture->upload(*bitmap);
+            SkBitmap skBitmap;
+            bitmap->getSkBitmap(&skBitmap);
+            texture->upload(skBitmap);
 
             mSize += size;
             TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
@@ -134,19 +137,21 @@
             if (mDebugEnabled) {
                 ALOGD("Texture created, size = %d", size);
             }
-            mCache.put(bitmap->pixelRef()->getStableID(), texture);
+            mCache.put(bitmap->getStableID(), texture);
         }
     } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
         // Texture was in the cache but is dirty, re-upload
         // TODO: Re-adjust the cache size if the bitmap's dimensions have changed
-        texture->upload(*bitmap);
+        SkBitmap skBitmap;
+        bitmap->getSkBitmap(&skBitmap);
+        texture->upload(skBitmap);
         texture->generation = bitmap->getGenerationID();
     }
 
     return texture;
 }
 
-bool TextureCache::prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap) {
+bool TextureCache::prefetchAndMarkInUse(void* ownerToken, Bitmap* bitmap) {
     Texture* texture = getCachedTexture(bitmap);
     if (texture) {
         texture->isInUse = ownerToken;
@@ -154,11 +159,11 @@
     return texture;
 }
 
-bool TextureCache::prefetch(const SkBitmap* bitmap) {
+bool TextureCache::prefetch(Bitmap* bitmap) {
     return getCachedTexture(bitmap);
 }
 
-Texture* TextureCache::get(const SkBitmap* bitmap) {
+Texture* TextureCache::get(Bitmap* bitmap) {
     Texture* texture = getCachedTexture(bitmap);
 
     if (!texture) {
@@ -169,7 +174,9 @@
         const uint32_t size = bitmap->rowBytes() * bitmap->height();
         texture = new Texture(Caches::getInstance());
         texture->bitmapSize = size;
-        texture->upload(*bitmap);
+        SkBitmap skBitmap;
+        bitmap->getSkBitmap(&skBitmap);
+        texture->upload(skBitmap);
         texture->generation = bitmap->getGenerationID();
         texture->cleanup = true;
     }
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 88ef771..68a548b 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -28,6 +28,9 @@
 #include <unordered_map>
 
 namespace android {
+
+class Bitmap;
+
 namespace uirenderer {
 
 class Texture;
@@ -73,20 +76,20 @@
      * acquired for the bitmap, false otherwise. If a Texture was acquired it is
      * marked as in use.
      */
-    bool prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap);
+    bool prefetchAndMarkInUse(void* ownerToken, Bitmap* bitmap);
 
     /**
      * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
      * acquired for the bitmap, false otherwise. Does not mark the Texture
      * as in use and won't update currently in-use Textures.
      */
-    bool prefetch(const SkBitmap* bitmap);
+    bool prefetch(Bitmap* bitmap);
 
     /**
      * Returns the texture associated with the specified bitmap from within the cache.
      * If the texture cannot be found in the cache, a new texture is generated.
      */
-    Texture* get(const SkBitmap* bitmap);
+    Texture* get(Bitmap* bitmap);
 
     /**
      * Removes the texture associated with the specified pixelRef. This is meant
@@ -119,9 +122,9 @@
     void flush();
 
 private:
-    bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
+    bool canMakeTextureFromBitmap(Bitmap* bitmap);
 
-    Texture* getCachedTexture(const SkBitmap* bitmap);
+    Texture* getCachedTexture(Bitmap* bitmap);
 
     LruCache<uint32_t, Texture*> mCache;
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index d9534f2..31fbe68 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -269,4 +269,9 @@
     outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
 }
 
+void Bitmap::getBounds(SkRect* bounds) const {
+    SkASSERT(bounds);
+    bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));
+}
+
 } // namespace android
\ No newline at end of file
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 029d80d..e86ac11 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -69,6 +69,10 @@
     void setHasHardwareMipMap(bool hasMipMap);
     bool hasHardwareMipMap() const;
 
+    bool isOpaque() const {return info().isOpaque(); }
+    SkColorType colorType() const { return info().colorType(); }
+    void getBounds(SkRect* bounds) const;
+
 protected:
     virtual bool onNewLockPixels(LockRec* rec) override;
     virtual void onUnlockPixels() override { };
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c2ed864..42da293 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -617,17 +617,17 @@
             reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
 }
 
-CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, SkBitmap* bitmap) {
+CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) {
     if (Caches::hasInstance() && args->thread->eglManager().hasEglContext()) {
         ATRACE_NAME("Bitmap#prepareToDraw task");
         Caches::getInstance().textureCache.prefetch(args->bitmap);
     }
-    delete args->bitmap;
+    args->bitmap->unref();
     args->bitmap = nullptr;
     return nullptr;
 }
 
-void RenderProxy::prepareToDraw(const SkBitmap& bitmap) {
+void RenderProxy::prepareToDraw(Bitmap& bitmap) {
     // If we haven't spun up a hardware accelerated window yet, there's no
     // point in precaching these bitmaps as it can't impact jank.
     // We also don't know if we even will spin up a hardware-accelerated
@@ -636,7 +636,8 @@
     RenderThread* renderThread = &RenderThread::getInstance();
     SETUP_TASK(prepareToDraw);
     args->thread = renderThread;
-    args->bitmap = new SkBitmap(bitmap);
+    bitmap.ref();
+    args->bitmap = &bitmap;
     nsecs_t lastVsync = renderThread->timeLord().latestVsync();
     nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
     nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 50a6f64..ae9330d 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -128,7 +128,7 @@
 
     ANDROID_API static int copySurfaceInto(sp<Surface>& surface,
             int left, int top, int right, int bottom, SkBitmap* bitmap);
-    ANDROID_API static void prepareToDraw(const SkBitmap& bitmap);
+    ANDROID_API static void prepareToDraw(Bitmap& bitmap);
 
 private:
     RenderThread& mRenderThread;
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index b8dfb01..cdaa705 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -134,17 +134,6 @@
         return Bitmap::allocateHeapBitmap(outBitmap, nullptr);
     }
 
-    static SkBitmap createSkBitmap(int width, int height,
-            SkColorType colorType = kN32_SkColorType) {
-        SkBitmap bitmap;
-        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
-        SkImageInfo info = SkImageInfo::Make(width, height,
-                colorType, kPremul_SkAlphaType, colorSpace);
-        bitmap.setInfo(info);
-        Bitmap::allocateHeapBitmap(&bitmap, nullptr);
-        return bitmap;
-    }
-
     static sp<DeferredLayerUpdater> createTextureLayerUpdater(
             renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
             const SkMatrix& transform);
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index fb6067d..01046e1 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -403,10 +403,10 @@
         void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
             switch(mIndex++) {
             case 0:
-                EXPECT_EQ(opaqueBitmap.get(), op.bitmap->pixelRef());
+                EXPECT_EQ(opaqueBitmap.get(), op.bitmap);
                 break;
             case 1:
-                EXPECT_EQ(transpBitmap.get(), op.bitmap->pixelRef());
+                EXPECT_EQ(transpBitmap.get(), op.bitmap);
                 break;
             default:
                 ADD_FAILURE() << "Only two ops expected.";
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 3bfbf12..134497c 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -736,10 +736,12 @@
 }
 
 TEST(RecordingCanvas, refBitmapInShader_bitmapShader) {
-    SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
+    sk_sp<Bitmap> bitmap = TestUtils::createBitmap(100, 100);
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
         SkPaint paint;
-        sk_sp<SkShader> shader = SkMakeBitmapShader(bitmap,
+        SkBitmap skBitmap;
+        bitmap->getSkBitmap(&skBitmap);
+        sk_sp<SkShader> shader = SkMakeBitmapShader(skBitmap,
                 SkShader::TileMode::kClamp_TileMode,
                 SkShader::TileMode::kClamp_TileMode,
                 nullptr,
@@ -753,10 +755,12 @@
 }
 
 TEST(RecordingCanvas, refBitmapInShader_composeShader) {
-    SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
+    sk_sp<Bitmap> bitmap = TestUtils::createBitmap(100, 100);
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
         SkPaint paint;
-        sk_sp<SkShader> shader1 = SkMakeBitmapShader(bitmap,
+        SkBitmap skBitmap;
+        bitmap->getSkBitmap(&skBitmap);
+        sk_sp<SkShader> shader1 = SkMakeBitmapShader(skBitmap,
                 SkShader::TileMode::kClamp_TileMode,
                 SkShader::TileMode::kClamp_TileMode,
                 nullptr,