drawBitmapImage can batch across AA rects
authorjoshualitt <joshualitt@chromium.org>
Mon, 17 Aug 2015 17:51:22 +0000 (10:51 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 17 Aug 2015 17:51:22 +0000 (10:51 -0700)
BUG=464835

Committed: https://skia.googlesource.com/skia/+/0d4bcea0d570041434ac3de2df2bd9063138fdb5

Review URL: https://codereview.chromium.org/1293543002

src/gpu/SkGpuDevice.cpp
src/gpu/batches/GrAAFillRectBatch.cpp
src/gpu/batches/GrRectBatchFactory.h

index f8318c5..7052d25 100644 (file)
@@ -39,6 +39,7 @@
 #include "SkUtils.h"
 #include "SkVertState.h"
 #include "SkXfermode.h"
+#include "batches/GrRectBatchFactory.h"
 #include "effects/GrBicubicEffect.h"
 #include "effects/GrDashingEffect.h"
 #include "effects/GrSimpleTextureEffect.h"
@@ -918,6 +919,82 @@ static bool needs_texture_domain(const SkBitmap& bitmap,
     return needsTextureDomain;
 }
 
+static void draw_aa_bitmap(GrDrawContext* drawContext, GrContext* context,
+                           GrRenderTarget* renderTarget, const GrClip& clip,
+                           const SkMatrix& viewMatrix, const SkMatrix& srcRectToDstRect,
+                           const SkPaint& paint, const SkBitmap* bitmapPtr, const SkSize& dstSize) {
+    SkShader::TileMode tm[] = {
+        SkShader::kClamp_TileMode,
+        SkShader::kClamp_TileMode,
+    };
+
+    bool doBicubic;
+    GrTextureParams::FilterMode textureFilterMode =
+            GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix,
+                                            srcRectToDstRect,
+                                            &doBicubic);
+
+    // Setup texture to wrap bitmap
+    GrTextureParams params(tm, textureFilterMode);
+    SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, *bitmapPtr, &params));
+
+    if (!texture) {
+        SkErrorInternals::SetError(kInternalError_SkError,
+                                   "Couldn't convert bitmap to texture.");
+        return;
+    }
+
+    // Setup paint
+    GrColor paintColor = (kAlpha_8_SkColorType == bitmapPtr->colorType()) ?
+                         SkColor2GrColor(paint.getColor()) :
+                         SkColor2GrColorJustAlpha(paint.getColor());
+
+    GrPaint grPaint;
+
+    // Create and insert texture effect
+    SkAutoTUnref<const GrFragmentProcessor> fp;
+    if (doBicubic) {
+        fp.reset(GrBicubicEffect::Create(grPaint.getProcessorDataManager(), texture,
+                                         SkMatrix::I(),
+                                         tm));
+    } else {
+        fp.reset(GrSimpleTextureEffect::Create(grPaint.getProcessorDataManager(), texture,
+                                               SkMatrix::I(), params));
+    }
+
+    // The bitmap read has to be first
+    grPaint.addColorProcessor(fp);
+    if (!SkPaint2GrPaintNoShader(context, renderTarget, paint, SkColor2GrColor(paint.getColor()),
+                                 false, &grPaint)) {
+        return;
+    }
+
+    grPaint.setColor(paintColor);
+
+    // Setup dst rect and final matrix
+    SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
+
+    SkRect devRect;
+    viewMatrix.mapRect(&devRect, dstRect);
+
+    SkMatrix matrix;
+    matrix.setIDiv(bitmapPtr->width(), bitmapPtr->height());
+
+    SkMatrix dstRectToSrcRect;
+    if (!srcRectToDstRect.invert(&dstRectToSrcRect)) {
+        return;
+    }
+    matrix.preConcat(dstRectToSrcRect);
+
+    SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateFillAA(grPaint.getColor(),
+                                                                     viewMatrix,
+                                                                     matrix,
+                                                                     dstRect,
+                                                                     devRect));
+
+    drawContext->drawBatch(renderTarget, clip, grPaint, batch);
+}
+
 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
                                    const SkBitmap& bitmap,
                                    const SkRect* srcRectPtr,
@@ -987,11 +1064,11 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
         // through drawRect, which supports mask filters.
         SkBitmap        tmp;    // subset of bitmap, if necessary
         const SkBitmap* bitmapPtr = &bitmap;
-        SkMatrix localM;
+        SkMatrix srcRectToDstRect;
         if (srcRectPtr) {
-            localM.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
-            localM.postScale(dstSize.fWidth / srcRectPtr->width(),
-                             dstSize.fHeight / srcRectPtr->height());
+            srcRectToDstRect.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
+            srcRectToDstRect.postScale(dstSize.fWidth / srcRectPtr->width(),
+                                       dstSize.fHeight / srcRectPtr->height());
             // In bleed mode we position and trim the bitmap based on the src rect which is
             // already accounted for in 'm' and 'srcRect'. In clamp mode we need to chop out
             // the desired portion of the bitmap and then update 'm' and 'srcRect' to
@@ -1010,17 +1087,25 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
                 srcRect.offset(-offset.fX, -offset.fY);
 
                 // The source rect has changed so update the matrix
-                localM.preTranslate(offset.fX, offset.fY);
+                srcRectToDstRect.preTranslate(offset.fX, offset.fY);
             }
         } else {
-            localM.reset();
+            srcRectToDstRect.reset();
         }
 
-        SkPaint paintWithShader(paint);
-        paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
-            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref();
-        SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
-        this->drawRect(draw, dstRect, paintWithShader);
+        // If we have a maskfilter then we can't batch, so we take a slow path.  However, we fast
+        // path the case where we are drawing an AA rect so we can batch many drawImageRect calls
+        if (paint.getMaskFilter()) {
+            SkPaint paintWithShader(paint);
+            paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
+                                      SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
+                                      &srcRectToDstRect))->unref();
+            SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
+            this->drawRect(draw, dstRect, paintWithShader);
+        } else {
+            draw_aa_bitmap(fDrawContext, fContext, fRenderTarget, fClip, *draw.fMatrix,
+                           srcRectToDstRect, paint, bitmapPtr, dstSize);
+        }
 
         return;
     }
index 94cc5ce..d8ef3d3 100644 (file)
@@ -250,12 +250,15 @@ private:
         // Make verts point to vertex color and then set all the color and coverage vertex attrs
         // values.
         verts += sizeof(SkPoint);
+
+        // The coverage offset is always the last vertex attribute
+        intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint);
         for (int i = 0; i < 4; ++i) {
             if (tweakAlphaForCoverage) {
                 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
             } else {
                 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
-                *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0;
+                *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0;
             }
         }
 
@@ -278,7 +281,7 @@ private:
             } else {
                 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
                 *reinterpret_cast<float*>(verts + i * vertexStride +
-                                          sizeof(GrColor)) = innerCoverage;
+                                          coverageOffset) = innerCoverage;
             }
         }
     }
@@ -392,7 +395,7 @@ public:
         }
         SkMatrix localCoordMatrix;
         localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix);
-        SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + vertexStride - sizeof(SkPoint));
+        SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + sizeof(SkPoint) + sizeof(GrColor));
         localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
     }
 };
index 7eaec79..5a43a34 100644 (file)
@@ -23,10 +23,10 @@ class SkStrokeRec;
 namespace GrRectBatchFactory {
 
 inline GrDrawBatch* CreateFillBW(GrColor color,
-                             const SkMatrix& viewMatrix,
-                             const SkRect& rect,
-                             const SkRect* localRect,
-                             const SkMatrix* localMatrix) {
+                                 const SkMatrix& viewMatrix,
+                                 const SkRect& rect,
+                                 const SkRect* localRect,
+                                 const SkMatrix* localMatrix) {
     return GrBWFillRectBatch::Create(color, viewMatrix, rect, localRect, localMatrix);
 }
 
@@ -37,6 +37,14 @@ inline GrDrawBatch* CreateFillAA(GrColor color,
     return GrAAFillRectBatch::Create(color, viewMatrix, rect, devRect);
 }
 
+inline GrDrawBatch* CreateFillAA(GrColor color,
+                                 const SkMatrix& viewMatrix,
+                                 const SkMatrix& localMatrix,
+                                 const SkRect& rect,
+                                 const SkRect& devRect) {
+    return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRect);
+}
+
 GrDrawBatch* CreateStrokeBW(GrColor color,
                             const SkMatrix& viewMatrix,
                             const SkRect& rect,