Add GrMakeCachedBitmapProxy
authorRobert Phillips <robertphillips@google.com>
Wed, 15 Feb 2017 18:18:21 +0000 (13:18 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Wed, 15 Feb 2017 19:15:20 +0000 (19:15 +0000)
This is split out of https://skia-review.googlesource.com/c/7889/ (Remove SkSpecialImage's GrTexture-based ctors) to allow focusing on the caching/subsetting changes.

Change-Id: Ic2af7a0d03e88941ab5b6cdfcecbbdefe3578eda
Reviewed-on: https://skia-review.googlesource.com/8456
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>

include/gpu/SkGr.h
src/core/SkSpecialImage.cpp
src/gpu/SkGpuDevice.cpp
src/gpu/SkGr.cpp
src/gpu/SkGrPriv.h

index 3f72fa1..f7ca0c8 100644 (file)
@@ -86,9 +86,6 @@ static inline GrColor SkPMColorToGrColor(SkPMColor c) {
 GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&,
                                     const GrSamplerParams&, SkScalar scaleAdjust[2]);
 
-sk_sp<GrTexture> GrMakeCachedBitmapTexture(GrContext*, const SkBitmap&,
-                                           const GrSamplerParams&, SkScalar scaleAdjust[2]);
-
 // TODO: Move SkImageInfo2GrPixelConfig to SkGrPriv.h (requires cleanup to SkWindow its subclasses).
 GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps);
 
index 0ec5459..f44d011 100644 (file)
@@ -103,16 +103,24 @@ sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrContext* context) {
         return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
     }
 
-    sk_sp<GrTexture> resultTex(
-        GrRefCachedBitmapTexture(context, bmp, GrSamplerParams::ClampNoFilter(), nullptr));
-    if (!resultTex) {
+    // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
+    // semantics). Since this is cached though we would have to bake the fit into the cache key.
+    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(context, bmp);
+    if (!proxy) {
         return nullptr;
     }
 
-    return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
-                                       this->uniqueID(),
-                                       resultTex, sk_ref_sp(this->getColorSpace()), &this->props(),
-                                       this->alphaType());
+    const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height());
+
+    // GrMakeCachedBitmapProxy has uploaded only the specified subset of 'bmp' so we need not
+    // bother with SkBitmap::getSubset
+    return SkSpecialImage::MakeDeferredFromGpu(context,
+                                               rect,
+                                               this->uniqueID(),
+                                               std::move(proxy),
+                                               sk_ref_sp(this->getColorSpace()),
+                                               &this->props(),
+                                               this->alphaType());
 #else
     return nullptr;
 #endif
index f30057d..4314b45 100644 (file)
@@ -1021,14 +1021,13 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
             if (bitmap.extractSubset(&tmpB, iTileR)) {
                 // now offset it to make it "local" to our tmp bitmap
                 tileR.offset(-offset.fX, -offset.fY);
-                GrSamplerParams paramsTemp = params;
                 // de-optimized this determination
                 bool needsTextureDomain = true;
                 this->drawBitmapTile(tmpB,
                                      viewMatrix,
                                      rectToDraw,
                                      tileR,
-                                     paramsTemp,
+                                     params,
                                      *paint,
                                      constraint,
                                      bicubic,
@@ -1054,9 +1053,11 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
     SkASSERT(bitmap.width() <= fContext->caps()->maxTileSize() &&
              bitmap.height() <= fContext->caps()->maxTileSize());
 
-    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
+    SkASSERT(SkShader::kClamp_TileMode == params.getTileModeX() &&
+             SkShader::kClamp_TileMode == params.getTileModeY());
+
     sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap,
-                                                         params, scaleAdjust);
+                                                         params, nullptr);
     if (nullptr == texture) {
         return;
     }
@@ -1064,8 +1065,8 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
         GrColorSpaceXform::Make(bitmap.colorSpace(), fRenderTargetContext->getColorSpace());
 
     // Compute a matrix that maps the rect we will draw to the src rect.
-    SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
-    texMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
+    const SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect,
+                                                        SkMatrix::kFill_ScaleToFit);
 
     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
     // the rest from the SkPaint.
@@ -1125,32 +1126,11 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
         return;
     }
 
-    sk_sp<GrTexture> texture;
-    {
-        SkAutoLockPixels alp(bitmap, true);
-        if (!bitmap.readyToDraw()) {
-            return;
-        }
-
-        // draw sprite neither filters nor tiles.
-        texture.reset(GrRefCachedBitmapTexture(fContext.get(), bitmap,
-                                               GrSamplerParams::ClampNoFilter(), nullptr));
-        if (!texture) {
-            return;
-        }
+    sk_sp<SkSpecialImage> srcImg = this->makeSpecial(bitmap);
+    if (!srcImg) {
+        return;
     }
 
-    SkIRect srcRect = SkIRect::MakeXYWH(bitmap.pixelRefOrigin().fX,
-                                        bitmap.pixelRefOrigin().fY,
-                                        bitmap.width(),
-                                        bitmap.height());
-
-    sk_sp<SkSpecialImage> srcImg(SkSpecialImage::MakeFromGpu(srcRect,
-                                                             bitmap.getGenerationID(),
-                                                             std::move(texture),
-                                                             bitmap.refColorSpace(),
-                                                             &this->surfaceProps()));
-
     this->drawSpecial(draw, srcImg.get(), left, top, paint);
 }
 
@@ -1294,22 +1274,23 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
 }
 
 sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) {
-    SkAutoLockPixels alp(bitmap, true);
-    if (!bitmap.readyToDraw()) {
+    // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
+    // semantics). Since this is cached we would have to bake the fit into the cache key though.
+    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(fContext.get(), bitmap);
+    if (!proxy) {
         return nullptr;
     }
 
-    sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap,
-                                                         GrSamplerParams::ClampNoFilter(), nullptr);
-    if (!texture) {
-        return nullptr;
-    }
+    const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height());
 
-    return SkSpecialImage::MakeFromGpu(bitmap.bounds(),
-                                       bitmap.getGenerationID(),
-                                       texture,
-                                       bitmap.refColorSpace(),
-                                       &this->surfaceProps());
+    // GrMakeCachedBitmapProxy creates a tight copy of 'bitmap' so we don't have to subset
+    // the special image
+    return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
+                                               rect,
+                                               bitmap.getGenerationID(),
+                                               std::move(proxy),
+                                               bitmap.refColorSpace(),
+                                               &this->surfaceProps());
 }
 
 sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
index bf04927..45f6e6e 100644 (file)
@@ -269,6 +269,42 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
                                                                  nullptr, scaleAdjust);
 }
 
+// For better or for worse, this method currently sidesteps the issue of caching an uninstantiated
+// proxy via a key.
+sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrContext* context, const SkBitmap& bitmap) {
+    GrUniqueKey originalKey;
+
+    if (!bitmap.isVolatile()) {
+        SkIPoint origin = bitmap.pixelRefOrigin();
+        SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height());
+        GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset);
+    }
+
+    sk_sp<GrTexture> tex;
+
+    if (originalKey.isValid()) {
+        tex.reset(context->textureProvider()->findAndRefTextureByUniqueKey(originalKey));
+    }
+    if (!tex) {
+        tex.reset(GrUploadBitmapToTexture(context, bitmap));
+        if (tex && originalKey.isValid()) {
+            tex->resourcePriv().setUniqueKey(originalKey);
+            GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
+        }
+    }
+
+    if (!tex) {
+        return nullptr;
+    }
+
+    sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex));
+    if (!proxy) {
+        return nullptr;
+    }
+
+    return sk_ref_sp(proxy->asTextureProxy());
+}
+
 sk_sp<GrTexture> GrMakeCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
                                            const GrSamplerParams& params, SkScalar scaleAdjust[2]) {
     // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
index 5437d4a..7f52ee8 100644 (file)
@@ -9,6 +9,7 @@
 #define SkGrPriv_DEFINED
 
 #include "GrBlend.h"
+#include "GrSamplerParams.h"
 #include "GrTypes.h"
 #include "SkCanvas.h"
 #include "SkImageInfo.h"
@@ -22,6 +23,7 @@ class GrRenderTargetContext;
 class GrFragmentProcessor;
 class GrPaint;
 class GrTexture;
+class GrTextureProxy;
 class GrUniqueKey;
 class SkBitmap;
 class SkData;
@@ -178,6 +180,22 @@ GrTexture* GrUploadPixmapToTexture(GrContext*, const SkPixmap&, SkBudgeted budge
 GrTexture* GrUploadMipMapToTexture(GrContext*, const SkImageInfo&, const GrMipLevel* texels,
                                    int mipLevelCount);
 
+sk_sp<GrTexture> GrMakeCachedBitmapTexture(GrContext*, const SkBitmap&,
+                                           const GrSamplerParams&, SkScalar scaleAdjust[2]);
+
+// This is intended to replace:
+//    SkAutoLockPixels alp(bitmap, true);
+//    if (!bitmap.readyToDraw()) {
+//        return nullptr;
+//    }
+//    sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap,
+//                                                         GrSamplerParams::ClampNoFilter(),
+//                                                         nullptr);
+//    if (!texture) {
+//        return nullptr;
+//    }
+sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrContext* context, const SkBitmap& bitmap);
+
 //////////////////////////////////////////////////////////////////////////////
 
 GR_STATIC_ASSERT((int)kZero_GrBlendCoeff == (int)SkXfermode::kZero_Coeff);