diff options
author | Derek Sollenberger <djsollen@google.com> | 2014-12-04 15:20:29 -0500 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2015-01-09 13:56:56 -0500 |
commit | 3d4eed7f1aa99401dabe2e45b82f98fb4fc2d754 (patch) | |
tree | e727b03577a823f638cab2f76a8a1161b73662eb /libs | |
parent | 83eb4443a9d24f2ae4a1e516354748850c10d06b (diff) | |
download | frameworks_base-3d4eed7f1aa99401dabe2e45b82f98fb4fc2d754.zip frameworks_base-3d4eed7f1aa99401dabe2e45b82f98fb4fc2d754.tar.gz frameworks_base-3d4eed7f1aa99401dabe2e45b82f98fb4fc2d754.tar.bz2 |
Update HWUI to store its own SkBitmap objects
This enables us to...
1) simplify the lifecycle/ownership between Java and HWUI
2) remove DisplayListRenderer::drawBitmapData and associated logic
3) track pixel lifecycle using standard SkPixelRef refcounting
4) Remove uncessary calls to ref/unref the bitmap's pixels and colorTable
Change-Id: I3c95078da20995444f6388a029414280fd654318
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/DisplayList.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 1 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 21 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 14 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.cpp | 18 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 1 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/Renderer.h | 1 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.cpp | 161 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 53 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/TextureCache.h | 4 |
13 files changed, 113 insertions, 186 deletions
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 249ada0..9832e60 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -46,12 +46,6 @@ void DisplayListData::cleanupResources() { resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i)); } - for (size_t i = 0; i < ownedBitmapResources.size(); i++) { - const SkBitmap* bitmap = ownedBitmapResources.itemAt(i); - resourceCache.decrementRefcountLocked(bitmap); - resourceCache.destructorLocked(bitmap); - } - for (size_t i = 0; i < patchResources.size(); i++) { resourceCache.decrementRefcountLocked(patchResources.itemAt(i)); } @@ -63,7 +57,6 @@ void DisplayListData::cleanupResources() { resourceCache.unlock(); bitmapResources.clear(); - ownedBitmapResources.clear(); patchResources.clear(); sourcePaths.clear(); paints.clear(); diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index cfd60ad..011b509 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -134,7 +134,6 @@ public: int projectionReceiveIndex; Vector<const SkBitmap*> bitmapResources; - Vector<const SkBitmap*> ownedBitmapResources; Vector<const Res_png_9patch*> patchResources; std::vector<std::unique_ptr<const SkPaint>> paints; diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 1b5af49..36c14c4 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -734,27 +734,6 @@ private: Rect mSrc; }; -class DrawBitmapDataOp : public DrawBitmapOp { -public: - DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint) - : DrawBitmapOp(bitmap, paint) {} - - virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override { - renderer.drawBitmapData(mBitmap, mPaint); - } - - virtual void output(int level, uint32_t logFlags) const override { - OP_LOG("Draw bitmap %p", mBitmap); - } - - virtual const char* name() override { return "DrawBitmapData"; } - - virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, - const DeferredDisplayState& state) override { - deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; - } -}; - class DrawBitmapMeshOp : public DrawBoundedOp { public: DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight, diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index ca21e4e..c7de03a 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -266,13 +266,6 @@ void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, floa } } -void DisplayListRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) { - bitmap = refBitmapData(bitmap); - paint = refPaint(paint); - - addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, paint)); -} - void DisplayListRenderer::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) { int vertexCount = (meshWidth + 1) * (meshHeight + 1); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 01fcdd3..8f8d24c 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -101,8 +101,6 @@ public: // Bitmap-based void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint); - // TODO: move drawBitmapData() to Canvas.h - void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint); // TODO: move drawPatch() to Canvas.h void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch, float left, float top, float right, float bottom, const SkPaint* paint); @@ -367,15 +365,9 @@ private: // 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. - mDisplayListData->bitmapResources.add(bitmap); - mResourceCache.incrementRefcount(bitmap); - return bitmap; - } - - inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) { - mDisplayListData->ownedBitmapResources.add(bitmap); - mResourceCache.incrementRefcount(bitmap); - return bitmap; + const SkBitmap* cachedBitmap = mResourceCache.insert(bitmap); + mDisplayListData->bitmapResources.add(cachedBitmap); + return cachedBitmap; } inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 3c8fb8b..d1e51e1 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2006,24 +2006,6 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { mDirty = true; } -void OpenGLRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) { - if (quickRejectSetupScissor(0, 0, bitmap->width(), bitmap->height())) { - return; - } - - mCaches.activeTexture(0); - Texture* texture = mCaches.textureCache.getTransient(bitmap); - const AutoTexture autoCleanup(texture); - - if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) { - drawAlphaBitmap(texture, 0, 0, paint); - } else { - drawTextureRect(0, 0, bitmap->width(), bitmap->height(), texture, paint); - } - - mDirty = true; -} - void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) { if (!vertices || mState.currentlyIgnored()) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 9d9b3d2..75e79d6 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -162,7 +162,6 @@ public: virtual void drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) override; - virtual void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) override; virtual void drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) override; void drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry, diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 5a7ea40..23462cc 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -338,11 +338,6 @@ void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { if (subtree) { TextureCache& cache = Caches::getInstance().textureCache; info.out.hasFunctors |= subtree->functors.size(); - // TODO: Fix ownedBitmapResources to not require disabling prepareTextures - // and thus falling out of async drawing path. - if (subtree->ownedBitmapResources.size()) { - info.prepareTextures = false; - } for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) { info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]); } diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h index 3240bbc..48d83b9 100644 --- a/libs/hwui/Renderer.h +++ b/libs/hwui/Renderer.h @@ -155,7 +155,6 @@ public: virtual void drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) = 0; - virtual void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) = 0; virtual void drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) = 0; virtual void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch, diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 45c27c2..2d1adc5 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -16,7 +16,6 @@ #define LOG_TAG "OpenGLRenderer" -#include <SkPixelRef.h> #include "ResourceCache.h" #include "Caches.h" @@ -37,8 +36,8 @@ void ResourceCache::logCache() { ResourceReference* ref = mCache->valueAt(i); ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", i, mCache->keyAt(i), mCache->valueAt(i)); - ALOGD(" ResourceCache: mCache(%zu): refCount, recycled, destroyed, type = %d, %d, %d, %d", - i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType); + ALOGD(" ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", + i, ref->refCount, ref->destroyed, ref->resourceType); } } @@ -60,13 +59,24 @@ void ResourceCache::unlock() { mLock.unlock(); } -void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { +const SkBitmap* ResourceCache::insert(const SkBitmap* bitmapResource) { Mutex::Autolock _l(mLock); - incrementRefcountLocked(resource, resourceType); + + BitmapKey bitmapKey(bitmapResource); + ssize_t index = mBitmapCache.indexOfKey(bitmapKey); + if (index == NAME_NOT_FOUND) { + SkBitmap* cachedBitmap = new SkBitmap(*bitmapResource); + index = mBitmapCache.add(bitmapKey, cachedBitmap); + return cachedBitmap; + } + + mBitmapCache.keyAt(index).mRefCount++; + return mBitmapCache.valueAt(index); } -void ResourceCache::incrementRefcount(const SkBitmap* bitmapResource) { - incrementRefcount((void*) bitmapResource, kBitmap); +void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { + Mutex::Autolock _l(mLock); + incrementRefcountLocked(resource, resourceType); } void ResourceCache::incrementRefcount(const SkPath* pathResource) { @@ -87,25 +97,14 @@ void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourc ref->refCount++; } -void ResourceCache::incrementRefcountLocked(const SkBitmap* bitmapResource) { - incrementRefcountLocked((void*) bitmapResource, kBitmap); -} - -void ResourceCache::incrementRefcountLocked(const SkPath* pathResource) { - incrementRefcountLocked((void*) pathResource, kPath); -} - -void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) { - incrementRefcountLocked((void*) patchResource, kNinePatch); -} - void ResourceCache::decrementRefcount(void* resource) { Mutex::Autolock _l(mLock); decrementRefcountLocked(resource); } void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) { - decrementRefcount((void*) bitmapResource); + Mutex::Autolock _l(mLock); + decrementRefcountLocked(bitmapResource); } void ResourceCache::decrementRefcount(const SkPath* pathResource) { @@ -130,7 +129,20 @@ void ResourceCache::decrementRefcountLocked(void* resource) { } void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) { - decrementRefcountLocked((void*) bitmapResource); + BitmapKey bitmapKey(bitmapResource); + ssize_t index = mBitmapCache.indexOfKey(bitmapKey); + + LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND, + "Decrementing the reference of an untracked Bitmap"); + + const BitmapKey& cacheEntry = mBitmapCache.keyAt(index); + if (cacheEntry.mRefCount == 1) { + // delete the bitmap and remove it from the cache + delete mBitmapCache.valueAt(index); + mBitmapCache.removeItemsAt(index); + } else { + cacheEntry.mRefCount--; + } } void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) { @@ -164,28 +176,6 @@ void ResourceCache::destructorLocked(SkPath* resource) { } } -void ResourceCache::destructor(const SkBitmap* resource) { - Mutex::Autolock _l(mLock); - destructorLocked(resource); -} - -void ResourceCache::destructorLocked(const SkBitmap* resource) { - ssize_t index = mCache->indexOfKey(resource); - ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; - if (ref == nullptr) { - // If we're not tracking this resource, just delete it - if (Caches::hasInstance()) { - Caches::getInstance().textureCache.releaseTexture(resource); - } - delete resource; - return; - } - ref->destroyed = true; - if (ref->refCount == 0) { - deleteResourceReferenceLocked(resource, ref); - } -} - void ResourceCache::destructor(Res_png_9patch* resource) { Mutex::Autolock _l(mLock); destructorLocked(resource); @@ -212,64 +202,12 @@ void ResourceCache::destructorLocked(Res_png_9patch* resource) { } /** - * Return value indicates whether resource was actually recycled, which happens when RefCnt - * reaches 0. - */ -bool ResourceCache::recycle(SkBitmap* resource) { - Mutex::Autolock _l(mLock); - return recycleLocked(resource); -} - -/** - * Return value indicates whether resource was actually recycled, which happens when RefCnt - * reaches 0. - */ -bool ResourceCache::recycleLocked(SkBitmap* resource) { - ssize_t index = mCache->indexOfKey(resource); - if (index < 0) { - if (Caches::hasInstance()) { - Caches::getInstance().textureCache.releaseTexture(resource); - } - // not tracking this resource; just recycle the pixel data - resource->setPixels(nullptr, nullptr); - return true; - } - ResourceReference* ref = mCache->valueAt(index); - if (ref == nullptr) { - // Should not get here - shouldn't get a call to recycle if we're not yet tracking it - return true; - } - ref->recycled = true; - if (ref->refCount == 0) { - deleteResourceReferenceLocked(resource, ref); - return true; - } - // Still referring to resource, don't recycle yet - return false; -} - -/** * This method should only be called while the mLock mutex is held (that mutex is grabbed * by the various destructor() and recycle() methods which call this method). */ void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) { - if (ref->recycled && ref->resourceType == kBitmap) { - SkBitmap* bitmap = (SkBitmap*) resource; - if (Caches::hasInstance()) { - Caches::getInstance().textureCache.releaseTexture(bitmap); - } - bitmap->setPixels(nullptr, nullptr); - } if (ref->destroyed) { switch (ref->resourceType) { - case kBitmap: { - SkBitmap* bitmap = (SkBitmap*) resource; - if (Caches::hasInstance()) { - Caches::getInstance().textureCache.releaseTexture(bitmap); - } - delete bitmap; - } - break; case kPath: { SkPath* path = (SkPath*) resource; if (Caches::hasInstance()) { @@ -296,5 +234,38 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource delete ref; } +/////////////////////////////////////////////////////////////////////////////// +// Bitmap Key +/////////////////////////////////////////////////////////////////////////////// + +void BitmapKey::operator=(const BitmapKey& other) { + this->mRefCount = other.mRefCount; + this->mBitmapDimensions = other.mBitmapDimensions; + this->mPixelRefOrigin = other.mPixelRefOrigin; + this->mPixelRefStableID = other.mPixelRefStableID; +} + +bool BitmapKey::operator==(const BitmapKey& other) const { + return mPixelRefStableID == other.mPixelRefStableID && + mPixelRefOrigin == other.mPixelRefOrigin && + mBitmapDimensions == other.mBitmapDimensions; +} + +bool BitmapKey::operator<(const BitmapKey& other) const { + if (mPixelRefStableID != other.mPixelRefStableID) { + return mPixelRefStableID < other.mPixelRefStableID; + } + if (mPixelRefOrigin.x() != other.mPixelRefOrigin.x()) { + return mPixelRefOrigin.x() < other.mPixelRefOrigin.x(); + } + if (mPixelRefOrigin.y() != other.mPixelRefOrigin.y()) { + return mPixelRefOrigin.y() < other.mPixelRefOrigin.y(); + } + if (mBitmapDimensions.width() != other.mBitmapDimensions.width()) { + return mBitmapDimensions.width() < other.mBitmapDimensions.width(); + } + return mBitmapDimensions.height() < other.mBitmapDimensions.height(); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index a252f6c..c6483ac 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -21,6 +21,7 @@ #include <SkBitmap.h> #include <SkPath.h> +#include <SkPixelRef.h> #include <utils/KeyedVector.h> #include <utils/Singleton.h> @@ -36,7 +37,6 @@ class Layer; * Type of Resource being cached */ enum ResourceType { - kBitmap, kNinePatch, kPath }; @@ -45,15 +45,45 @@ class ResourceReference { public: ResourceReference(ResourceType type) { - refCount = 0; recycled = false; destroyed = false; resourceType = type; + refCount = 0; destroyed = false; resourceType = type; } int refCount; - bool recycled; bool destroyed; ResourceType resourceType; }; +class BitmapKey { +public: + BitmapKey(const SkBitmap* bitmap) + : mRefCount(1) + , mBitmapDimensions(bitmap->dimensions()) + , mPixelRefOrigin(bitmap->pixelRefOrigin()) + , mPixelRefStableID(bitmap->pixelRef()->getStableID()) { } + + void operator=(const BitmapKey& other); + bool operator==(const BitmapKey& other) const; + bool operator<(const BitmapKey& other) const; + +private: + // This constructor is only used by the KeyedVector implementation + BitmapKey() + : mRefCount(-1) + , mBitmapDimensions(SkISize::Make(0,0)) + , mPixelRefOrigin(SkIPoint::Make(0,0)) + , mPixelRefStableID(0) { } + + // reference count of all HWUI object using this bitmap + mutable int mRefCount; + + SkISize mBitmapDimensions; + SkIPoint mPixelRefOrigin; + uint32_t mPixelRefStableID; + + friend class ResourceCache; + friend class android::key_value_pair_t<BitmapKey, SkBitmap*>; +}; + class ANDROID_API ResourceCache: public Singleton<ResourceCache> { ResourceCache(); ~ResourceCache(); @@ -69,14 +99,15 @@ public: void lock(); void unlock(); + /** + * The cache stores a copy of the provided resource or refs an existing resource + * if the bitmap has previously been inserted and returns the cached copy. + */ + const SkBitmap* insert(const SkBitmap* resource); + void incrementRefcount(const SkPath* resource); - void incrementRefcount(const SkBitmap* resource); void incrementRefcount(const Res_png_9patch* resource); - void incrementRefcountLocked(const SkPath* resource); - void incrementRefcountLocked(const SkBitmap* resource); - void incrementRefcountLocked(const Res_png_9patch* resource); - void decrementRefcount(const SkBitmap* resource); void decrementRefcount(const SkPath* resource); void decrementRefcount(const Res_png_9patch* resource); @@ -86,16 +117,11 @@ public: void decrementRefcountLocked(const Res_png_9patch* resource); void destructor(SkPath* resource); - void destructor(const SkBitmap* resource); void destructor(Res_png_9patch* resource); void destructorLocked(SkPath* resource); - void destructorLocked(const SkBitmap* resource); void destructorLocked(Res_png_9patch* resource); - bool recycle(SkBitmap* resource); - bool recycleLocked(SkBitmap* resource); - private: void deleteResourceReferenceLocked(const void* resource, ResourceReference* ref); @@ -115,6 +141,7 @@ private: mutable Mutex mLock; KeyedVector<const void*, ResourceReference*>* mCache; + KeyedVector<BitmapKey, SkBitmap*> mBitmapCache; }; }; // namespace uirenderer diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 7dc2480..b4d3708 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -233,11 +233,9 @@ Texture* TextureCache::getTransient(const SkBitmap* bitmap) { return texture; } -void TextureCache::releaseTexture(const SkBitmap* bitmap) { - if (!bitmap || !bitmap->pixelRef()) return; - +void TextureCache::releaseTexture(uint32_t pixelRefStableID) { Mutex::Autolock _l(mLock); - mGarbage.push(bitmap->pixelRef()->getStableID()); + mGarbage.push(pixelRefStableID); } void TextureCache::clearGarbage() { diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 0e33e4c..b97d92d 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -88,10 +88,10 @@ public: Texture* getTransient(const SkBitmap* bitmap); /** - * Removes the texture associated with the specified bitmap. This is meant + * Removes the texture associated with the specified pixelRef. This is meant * to be called from threads that are not the EGL context thread. */ - void releaseTexture(const SkBitmap* bitmap); + ANDROID_API void releaseTexture(uint32_t pixelRefStableID); /** * Process deferred removals. */ |