Index: src/gpu/SkGr.cpp |
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp |
index e0892d8ab974e88db4034b429cba09727ab8cb93..a26cdb8b8aa9e48c13d1abbf6fdcfc9cad2689f8 100644 |
--- a/src/gpu/SkGr.cpp |
+++ b/src/gpu/SkGr.cpp |
@@ -503,31 +503,6 @@ static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const Stretch& stretch) { |
return stretched; |
} |
-static GrTexture* create_bitmap_texture(GrContext* ctx, |
- const SkBitmap& bmp, |
- const Stretch& stretch, |
- const GrUniqueKey& unstretchedKey, |
- const GrUniqueKey& stretchedKey) { |
- if (Stretch::kNone_Type != stretch.fType) { |
- SkAutoTUnref<GrTexture> unstretched; |
- // Check if we have the unstretched version in the cache, if not create it. |
- if (unstretchedKey.isValid()) { |
- unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey)); |
- } |
- if (!unstretched) { |
- unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey)); |
- if (!unstretched) { |
- // We might not have been able to create a unstrecthed texture because it is smaller |
- // than the min texture size. In that case do cpu stretching. |
- SkBitmap stretchedBmp = stretch_on_cpu(bmp, stretch); |
- return create_unstretched_bitmap_texture(ctx, stretchedBmp, stretchedKey); |
- } |
- } |
- return stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKey); |
- } |
- return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey); |
-} |
- |
bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& subset, |
GrTexture* nativeTexture, const GrTextureParams* params) { |
Stretch stretch; |
@@ -562,57 +537,159 @@ bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, |
params); |
} |
-GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, |
- const SkBitmap& bitmap, |
- const GrTextureParams* params) { |
+class GrTextureMaker { |
+public: |
+ GrTextureMaker(int width, int height) : fWidth(width), fHeight(height) {} |
+ |
+ int width() const { return fWidth; } |
+ int height() const { return fHeight; } |
+ |
+ GrTexture* refCachedTexture(GrContext*, const GrTextureParams*); |
+ |
+protected: |
+ /** |
+ * Return the maker's "original" unstretched texture. It is the responsibility of the maker |
+ * to make this efficient ... if the texture is being generated, the maker must handle |
+ * caching it. |
+ */ |
+ virtual GrTexture* onRefUnstretchedTexture(GrContext*) = 0; |
+ |
+ /** |
+ * If we need to stretch the maker's original texture, the maker is asked to return a key |
+ * that identifies its origianl + the stretch parameter. If the maker does not want to cache |
+ * the stretched version (e.g. the maker is volatile), this should ignore the key parameter |
+ * and return false. |
+ */ |
+ virtual bool onMakeStretchedKey(const Stretch&, GrUniqueKey* stretchedKey) = 0; |
+ |
+ /** |
+ * Return a new (uncached) texture that is the stretch of the maker's original. |
+ * |
+ * The base-class handles general logic for this, and only needs access to the following |
+ * methods: |
+ * - onRefUnstretchedTexture() |
+ * - onGetROBitmkap() |
bsalomon
2015/09/29 19:23:29
ROBitmap
reed1
2015/09/29 19:38:13
Done.
|
+ * |
+ * Subclass may override this if they can handle stretching more efficiently. |
+ */ |
+ virtual GrTexture* onGenerateStretchedTexture(GrContext*, const Stretch&); |
+ |
+ /** |
+ * If a stretched version of the texture is generated, it may be cached (assuming that |
+ * onMakeStretchedKey() returns true). In that case, the maker is notified in case it |
+ * wants to note that for when the maker is destroyed. |
+ */ |
+ virtual void onNotifyStretchCached(const GrUniqueKey& stretchedKey) = 0; |
+ |
+ /** |
+ * Some GPUs are unreliable w/ very small texture sizes. If we run into that case, this |
+ * method will be called (in service of onGenerateStretchedTexture) to return a raster version |
+ * of the original texture. |
+ */ |
+ virtual bool onGetROBitmap(SkBitmap*) = 0; |
- Stretch stretch; |
- get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch); |
+private: |
+ const int fWidth; |
+ const int fHeight; |
+}; |
- GrTexture* result = bitmap.getTexture(); |
- if (result) { |
- if (Stretch::kNone_Type == stretch.fType) { |
- return SkRef(result); |
+GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const Stretch& stretch) { |
+ if (this->width() < ctx->caps()->minTextureSize() || |
+ this->height() < ctx->caps()->minTextureSize()) |
+ { |
+ // we can't trust our ability to use HW to perform the stretch, so we request |
+ // a raster instead, and perform the stretch on the CPU. |
+ SkBitmap bitmap; |
+ if (!this->onGetROBitmap(&bitmap)) { |
+ return nullptr; |
} |
- GrUniqueKey stretchedKey; |
- // Don't create a key for the resized version if the bmp is volatile. |
- if (!bitmap.isVolatile()) { |
- const GrUniqueKey& key = result->getUniqueKey(); |
- if (key.isValid()) { |
- make_stretched_key(key, stretch, &stretchedKey); |
- GrTexture* stretched = |
- ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey); |
- if (stretched) { |
- return stretched; |
- } |
- } |
+ SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); |
+ return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey()); |
+ } else { |
+ SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); |
+ if (!unstretched) { |
+ return nullptr; |
} |
- return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey); |
+ return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); |
} |
+} |
bsalomon
2015/09/29 19:23:29
extra \n
reed1
2015/09/29 19:38:13
Done.
|
- GrUniqueKey key, resizedKey; |
- if (!bitmap.isVolatile()) { |
- // If the bitmap isn't changing try to find a cached copy first. |
- make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, &key, &resizedKey); |
+GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams* params) { |
+ Stretch stretch; |
+ get_stretch(ctx, this->width(), this->height(), params, &stretch); |
- result = ctx->textureProvider()->findAndRefTextureByUniqueKey( |
- resizedKey.isValid() ? resizedKey : key); |
+ if (Stretch::kNone_Type == stretch.fType) { |
+ return this->onRefUnstretchedTexture(ctx); |
+ } |
+ |
+ GrUniqueKey stretchedKey; |
+ if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
+ GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey); |
if (result) { |
return result; |
} |
} |
- result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey); |
- if (result) { |
- return result; |
+ GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch); |
+ if (!result) { |
+ return nullptr; |
} |
- SkErrorInternals::SetError( kInternalError_SkError, |
- "---- failed to create texture for cache [%d %d]\n", |
- bitmap.width(), bitmap.height()); |
+ if (stretchedKey.isValid()) { |
+ ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result); |
+ this->onNotifyStretchCached(stretchedKey); |
+ } |
+ return result; |
+} |
+ |
+class Bitmap_GrTextureMaker : public GrTextureMaker { |
+public: |
+ Bitmap_GrTextureMaker(const SkBitmap& bitmap) |
+ : INHERITED(bitmap.width(), bitmap.height()) |
+ , fBitmap(bitmap) |
+ {} |
+ |
+protected: |
+ GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { |
+ GrTexture* tex = fBitmap.getTexture(); |
+ if (tex) { |
+ return SkRef(tex); |
+ } |
+ |
+ GrUniqueKey unstretchedKey; |
+ make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset()); |
+ return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey); |
+ } |
+ |
+ bool onMakeStretchedKey(const Stretch& stretch, GrUniqueKey* stretchedKey) override { |
+ if (fBitmap.isVolatile()) { |
+ return false; |
+ } |
- return nullptr; |
+ GrUniqueKey unstretchedKey; |
+ make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset()); |
+ return make_stretched_key(unstretchedKey, stretch, stretchedKey); |
+ } |
+ |
+ void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { |
+ fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretchedKey)); |
+ } |
+ |
+ bool onGetROBitmap(SkBitmap* bitmap) override { |
+ *bitmap = fBitmap; |
+ return true; |
+ } |
+ |
+private: |
+ const SkBitmap fBitmap; |
+ |
+ typedef GrTextureMaker INHERITED; |
+}; |
+ |
+GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, |
+ const GrTextureParams* params) { |
+ return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); |
} |
// TODO: make this be the canonical signature, and turn the version that takes GrTextureParams* |