Add can-ignore-rect hint to clear call

https://codereview.chromium.org/53823003/



git-svn-id: http://skia.googlecode.com/svn/trunk@12064 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkBitmapAlphaThresholdShader.cpp b/src/effects/SkBitmapAlphaThresholdShader.cpp
index 226b317..05d7ba3 100644
--- a/src/effects/SkBitmapAlphaThresholdShader.cpp
+++ b/src/effects/SkBitmapAlphaThresholdShader.cpp
@@ -241,7 +241,7 @@
     grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
     SkRegion::Iterator iter(fRegion);
     context->setRenderTarget(maskTexture->asRenderTarget());
-    context->clear(NULL, 0x0);
+    context->clear(NULL, 0x0, true);
 
     // offset to ensure border is zero on top/left
     SkMatrix matrix;
diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp
index fce5b6b..6188c49 100644
--- a/src/effects/SkGpuBlurUtils.cpp
+++ b/src/effects/SkGpuBlurUtils.cpp
@@ -197,7 +197,7 @@
             // X convolution from reading garbage.
             clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                           radiusX, srcIRect.height());
-            context->clear(&clearRect, 0x0);
+            context->clear(&clearRect, 0x0, false);
         }
         context->setRenderTarget(dstTexture->asRenderTarget());
         SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
@@ -214,7 +214,7 @@
             // convolution from reading garbage.
             clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                           srcIRect.width(), radiusY);
-            context->clear(&clearRect, 0x0);
+            context->clear(&clearRect, 0x0, false);
         }
 
         context->setRenderTarget(dstTexture->asRenderTarget());
@@ -231,10 +231,10 @@
         // upsampling.
         clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                       srcIRect.width() + 1, 1);
-        context->clear(&clearRect, 0x0);
+        context->clear(&clearRect, 0x0, false);
         clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                       1, srcIRect.height());
-        context->clear(&clearRect, 0x0);
+        context->clear(&clearRect, 0x0, false);
         SkMatrix matrix;
         matrix.setIDiv(srcTexture->width(), srcTexture->height());
         context->setRenderTarget(dstTexture->asRenderTarget());
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 152ec56..9665dcb 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -538,7 +538,7 @@
                                               dstRect.width(), radius.fHeight);
         context->clear(&clearRect, GrMorphologyEffect::kErode_MorphologyType == morphType ?
                                    SK_ColorWHITE :
-                                   SK_ColorTRANSPARENT);
+                                   SK_ColorTRANSPARENT, false);
         src.reset(ast.detach());
         srcRect = dstRect;
     }
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index e2597df..0f91566 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -461,6 +461,7 @@
     // clear the part that we care about.
     fGpu->clear(&maskSpaceIBounds,
                 kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
+                true,
                 result->asRenderTarget());
 
     // When we use the stencil in the below loop it is important to have this clip installed.
@@ -505,6 +506,7 @@
                 // clear the temp target and set blend to replace
                 fGpu->clear(&maskSpaceElementIBounds,
                             invert ? 0xffffffff : 0x00000000,
+                            true,
                             dst->asRenderTarget());
                 setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 967738a..cf3b86a 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -645,10 +645,12 @@
 
 void GrContext::clear(const SkIRect* rect,
                       const GrColor color,
+                      bool canIgnoreRect,
                       GrRenderTarget* target) {
     AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color, target);
+    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color, 
+                                                                canIgnoreRect, target);
 }
 
 void GrContext::drawPaint(const GrPaint& origPaint) {
@@ -833,7 +835,7 @@
                 // Will it blend?
                 GrColor clearColor;
                 if (paint.isOpaqueAndConstantColor(&clearColor)) {
-                    target->clear(NULL, clearColor);
+                    target->clear(NULL, clearColor, true);
                     return;
                 }
             }
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 6a1cc02..266dc07 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -405,10 +405,12 @@
     /**
      * Clear the current render target if one isn't passed in. Ignores the
      * clip and all other draw state (blend mode, stages, etc). Clears the
-     * whole thing if rect is NULL, otherwise just the rect.
+     * whole thing if rect is NULL, otherwise just the rect. If canIgnoreRect
+     * is set then the entire render target can be optionally cleared.
      */
     virtual void clear(const SkIRect* rect,
                        GrColor color,
+                       bool canIgnoreRect,
                        GrRenderTarget* renderTarget = NULL) = 0;
 
     /**
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index cd217f4..af7037a 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -205,6 +205,7 @@
 
 void GrGpu::clear(const SkIRect* rect,
                   GrColor color,
+                  bool canIgnoreRect,
                   GrRenderTarget* renderTarget) {
     GrDrawState::AutoRenderTargetRestore art;
     if (NULL != renderTarget) {
@@ -215,7 +216,7 @@
         return;
     }
     this->handleDirtyContext();
-    this->onClear(rect, color);
+    this->onClear(rect, color, canIgnoreRect);
 }
 
 void GrGpu::forceRenderTargetFlush() {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index c0a4b8f..f9028b9 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -265,6 +265,7 @@
     // GrDrawTarget overrides
     virtual void clear(const SkIRect* rect,
                        GrColor color,
+                       bool canIgnoreRect,
                        GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
 
     virtual void purgeResources() SK_OVERRIDE {
@@ -426,8 +427,9 @@
     virtual GrPath* onCreatePath(const SkPath& path, const SkStrokeRec&) = 0;
 
     // overridden by backend-specific derived class to perform the clear and
-    // clearRect. NULL rect means clear whole target.
-    virtual void onClear(const SkIRect* rect, GrColor color) = 0;
+    // clearRect. NULL rect means clear whole target. If canIgnoreRect is
+    // true, it is okay to perform a full clear instead of a partial clear
+    virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) = 0;
 
     // overridden by backend-specific derived class to perform the draw call.
     virtual void onGpuDraw(const DrawInfo&) = 0;
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index a299512..ccbfe59 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -419,7 +419,8 @@
     }
 }
 
-void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color, GrRenderTarget* renderTarget) {
+void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color, 
+                                bool canIgnoreRect, GrRenderTarget* renderTarget) {
     SkIRect r;
     if (NULL == renderTarget) {
         renderTarget = this->drawState()->getRenderTarget();
@@ -435,6 +436,7 @@
     Clear* clr = this->recordClear();
     clr->fColor = color;
     clr->fRect = *rect;
+    clr->fCanIgnoreRect = canIgnoreRect;
     clr->fRenderTarget = renderTarget;
     renderTarget->ref();
 }
@@ -540,6 +542,7 @@
             case kClear_Cmd:
                 fDstGpu->clear(&fClears[currClear].fRect,
                                fClears[currClear].fColor,
+                               fClears[currClear].fCanIgnoreRect,
                                fClears[currClear].fRenderTarget);
                 ++currClear;
                 break;
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 275d7e0..6b680b2 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -71,6 +71,7 @@
                                int* indexCount) const SK_OVERRIDE;
     virtual void clear(const SkIRect* rect,
                        GrColor color,
+                       bool canIgnoreRect,
                        GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
 
     virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
@@ -117,6 +118,7 @@
 
         SkIRect         fRect;
         GrColor         fColor;
+        bool            fCanIgnoreRect;
         GrRenderTarget* fRenderTarget;
     };
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index f47a91b..4041c41 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -548,7 +548,7 @@
 
 void SkGpuDevice::clear(SkColor color) {
     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
-    fContext->clear(&rect, SkColor2GrColor(color), fRenderTarget);
+    fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget);
     fNeedClear = false;
 }
 
@@ -822,7 +822,7 @@
     GrContext::AutoRenderTarget art(context, maskTexture->asRenderTarget());
     GrContext::AutoClip ac(context, clipRect);
 
-    context->clear(NULL, 0x0);
+    context->clear(NULL, 0x0, true);
 
     GrPaint tempPaint;
     if (doAA) {
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 8e6c3e2..60c0dfa 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -48,6 +48,7 @@
     fIsCoreProfile = false;
     fFixedFunctionSupport = false;
     fDiscardFBSupport = false;
+    fFullClearIsFree = false;
 }
 
 GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
@@ -84,6 +85,7 @@
     fIsCoreProfile = caps.fIsCoreProfile;
     fFixedFunctionSupport = caps.fFixedFunctionSupport;
     fDiscardFBSupport = caps.fDiscardFBSupport;
+    fFullClearIsFree = caps.fFullClearIsFree;
 
     return *this;
 }
@@ -224,6 +226,10 @@
 
     fDiscardFBSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer");
 
+    if (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor()) {
+        fFullClearIsFree = true;
+    }
+
     if (kDesktop_GrGLBinding == binding) {
         fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) ||
                                     ctxInfo.hasExtension("GL_ARB_vertex_array_object");
@@ -648,4 +654,5 @@
     GrPrintf("Use non-VBO for dynamic data: %s\n",
              (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
     GrPrintf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO"));
+    GrPrintf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
 }
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 81391ec..c126a76 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -248,6 +248,8 @@
     /// Is there support for discarding the frame buffer
     bool discardFBSupport() const { return fDiscardFBSupport; }
 
+    bool fullClearIsFree() const { return fFullClearIsFree; }
+
 private:
     /**
      * Maintains a bit per GrPixelConfig. It is used to avoid redundantly
@@ -329,6 +331,7 @@
     bool fIsCoreProfile : 1;
     bool fFixedFunctionSupport : 1;
     bool fDiscardFBSupport : 1;
+    bool fFullClearIsFree : 1;
 
     typedef GrDrawTargetCaps INHERITED;
 };
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index adbfc35..92e496c 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1255,12 +1255,16 @@
     }
 }
 
-void GrGpuGL::onClear(const SkIRect* rect, GrColor color) {
+void GrGpuGL::onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) {
     const GrDrawState& drawState = this->getDrawState();
     const GrRenderTarget* rt = drawState.getRenderTarget();
     // parent class should never let us get here with no RT
     SkASSERT(NULL != rt);
 
+    if (canIgnoreRect && this->glCaps().fullClearIsFree()) {
+        rect = NULL;
+    }
+
     SkIRect clippedRect;
     if (NULL != rect) {
         // flushScissor expects rect to be clipped to the target.
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 677e48c..7c97080 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -135,7 +135,7 @@
         GrStencilBuffer* sb,
         GrRenderTarget* rt) SK_OVERRIDE;
 
-    virtual void onClear(const SkIRect* rect, GrColor color) SK_OVERRIDE;
+    virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) SK_OVERRIDE;
 
     virtual void onForceRenderTargetFlush() SK_OVERRIDE;