Workaround for PowerVR clear issue.

BUG=skia:

Review URL: https://codereview.chromium.org/701573002
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 8f436f2..08a62a5 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -546,6 +546,31 @@
                       dstCopy.texture() ? &dstCopy : NULL);
 }
 
+void GrDrawTarget::clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+                         GrRenderTarget* renderTarget) {
+    if (fCaps->useDrawInsteadOfClear()) {
+        // This works around a driver bug with clear by drawing a rect instead.
+        // The driver will ignore a clear if it is the only thing rendered to a
+        // target before the target is read.
+        SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
+        if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) {
+            rect = &rtRect;
+            // We first issue a discard() since that may help tilers.
+            this->discard(renderTarget);
+        }
+        AutoStateRestore asr(this, kReset_ASRInit, &SkMatrix::I());
+
+        this->drawState()->setColor(color);
+        this->drawState()->disableState(GrDrawState::kClip_StateBit);
+        this->drawState()->disableState(GrDrawState::kHWAntialias_StateBit);
+        this->drawState()->setRenderTarget(renderTarget);
+
+        this->drawSimpleRect(*rect);
+    } else {       
+        this->onClear(rect, color, canIgnoreRect, renderTarget);
+    }
+}
+
 typedef GrTraceMarkerSet::Iter TMIter;
 void GrDrawTarget::saveActiveTraceMarkers() {
     if (this->caps()->gpuTracingSupport()) {
@@ -969,6 +994,8 @@
     fGpuTracingSupport = false;
     fCompressedTexSubImageSupport = false;
 
+    fUseDrawInsteadOfClear = false;
+
     fMapBufferFlags = kNone_MapFlags;
 
     fMaxRenderTargetSize = 0;
@@ -995,6 +1022,8 @@
     fGpuTracingSupport = other.fGpuTracingSupport;
     fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport;
 
+    fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear;
+
     fMapBufferFlags = other.fMapBufferFlags;
 
     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
@@ -1030,25 +1059,29 @@
 SkString GrDrawTargetCaps::dump() const {
     SkString r;
     static const char* gNY[] = {"NO", "YES"};
-    r.appendf("MIP Map Support              : %s\n", gNY[fMipMapSupport]);
-    r.appendf("NPOT Texture Tile Support    : %s\n", gNY[fNPOTTextureTileSupport]);
-    r.appendf("Two Sided Stencil Support    : %s\n", gNY[fTwoSidedStencilSupport]);
-    r.appendf("Stencil Wrap Ops  Support    : %s\n", gNY[fStencilWrapOpsSupport]);
-    r.appendf("HW AA Lines Support          : %s\n", gNY[fHWAALineSupport]);
-    r.appendf("Shader Derivative Support    : %s\n", gNY[fShaderDerivativeSupport]);
-    r.appendf("Geometry Shader Support      : %s\n", gNY[fGeometryShaderSupport]);
-    r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
-    r.appendf("Path Rendering Support       : %s\n", gNY[fPathRenderingSupport]);
-    r.appendf("Dst Read In Shader Support   : %s\n", gNY[fDstReadInShaderSupport]);
-    r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]);
-    r.appendf("Reuse Scratch Textures       : %s\n", gNY[fReuseScratchTextures]);
-    r.appendf("Gpu Tracing Support          : %s\n", gNY[fGpuTracingSupport]);
-    r.appendf("Compressed Update Support    : %s\n", gNY[fCompressedTexSubImageSupport]);
-    r.appendf("Max Texture Size             : %d\n", fMaxTextureSize);
-    r.appendf("Max Render Target Size       : %d\n", fMaxRenderTargetSize);
-    r.appendf("Max Sample Count             : %d\n", fMaxSampleCount);
+    r.appendf("MIP Map Support                    : %s\n", gNY[fMipMapSupport]);
+    r.appendf("NPOT Texture Tile Support          : %s\n", gNY[fNPOTTextureTileSupport]);
+    r.appendf("Two Sided Stencil Support          : %s\n", gNY[fTwoSidedStencilSupport]);
+    r.appendf("Stencil Wrap Ops  Support          : %s\n", gNY[fStencilWrapOpsSupport]);
+    r.appendf("HW AA Lines Support                : %s\n", gNY[fHWAALineSupport]);
+    r.appendf("Shader Derivative Support          : %s\n", gNY[fShaderDerivativeSupport]);
+    r.appendf("Geometry Shader Support            : %s\n", gNY[fGeometryShaderSupport]);
+    r.appendf("Dual Source Blending Support       : %s\n", gNY[fDualSourceBlendingSupport]);
+    r.appendf("Path Rendering Support             : %s\n", gNY[fPathRenderingSupport]);
+    r.appendf("Dst Read In Shader Support         : %s\n", gNY[fDstReadInShaderSupport]);
+    r.appendf("Discard Render Target Support      : %s\n", gNY[fDiscardRenderTargetSupport]);
+    r.appendf("Reuse Scratch Textures             : %s\n", gNY[fReuseScratchTextures]);
+    r.appendf("Gpu Tracing Support                : %s\n", gNY[fGpuTracingSupport]);
+    r.appendf("Compressed Update Support          : %s\n", gNY[fCompressedTexSubImageSupport]);
 
-    r.appendf("Map Buffer Support           : %s\n", map_flags_to_string(fMapBufferFlags).c_str());
+    r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
+
+    r.appendf("Max Texture Size                   : %d\n", fMaxTextureSize);
+    r.appendf("Max Render Target Size             : %d\n", fMaxRenderTargetSize);
+    r.appendf("Max Sample Count                   : %d\n", fMaxSampleCount);
+
+    r.appendf("Map Buffer Support                 : %s\n",
+              map_flags_to_string(fMapBufferFlags).c_str());
 
     static const char* kConfigNames[] = {
         "Unknown",  // kUnknown_GrPixelConfig
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index b1f758a..47b439e 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -395,8 +395,8 @@
      * 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) = 0;
+    void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+               GrRenderTarget* renderTarget);
 
     /**
      * Discards the contents render target.
@@ -855,6 +855,10 @@
                              const float transforms[], PathTransformType,
                              GrPathRendering::FillType, const GrDeviceCoordTexture*) = 0;
 
+    virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+                         GrRenderTarget* renderTarget) = 0;
+
+
     virtual void didAddGpuTraceMarker() = 0;
     virtual void didRemoveGpuTraceMarker() = 0;
 
diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h
index e468bc4..f13aa53 100644
--- a/src/gpu/GrDrawTargetCaps.h
+++ b/src/gpu/GrDrawTargetCaps.h
@@ -46,6 +46,8 @@
     bool gpuTracingSupport() const { return fGpuTracingSupport; }
     bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; }
 
+    bool useDrawInsteadOfClear() const { return fUseDrawInsteadOfClear; }
+
     /**
      * Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
      * textures allows partial mappings or full mappings.
@@ -104,6 +106,9 @@
     bool fGpuTracingSupport         : 1;
     bool fCompressedTexSubImageSupport : 1;
 
+    // Driver workaround
+    bool fUseDrawInsteadOfClear     : 1;
+
     uint32_t fMapBufferFlags;
 
     int fMaxRenderTargetSize;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 8cccd35..88adb20 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -194,13 +194,13 @@
     return buffer;
 }
 
-void GrGpu::clear(const SkIRect* rect,
-                  GrColor color,
-                  bool canIgnoreRect,
-                  GrRenderTarget* renderTarget) {
+void GrGpu::onClear(const SkIRect* rect,
+                    GrColor color,
+                    bool canIgnoreRect,
+                    GrRenderTarget* renderTarget) {
     SkASSERT(renderTarget);
     this->handleDirtyContext();
-    this->onClear(renderTarget, rect, color, canIgnoreRect);
+    this->onGpuClear(renderTarget, rect, color, canIgnoreRect);
 }
 
 void GrGpu::clearStencilClip(const SkIRect& rect,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 2dcee06..d2f13b6 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -266,9 +266,6 @@
                             size_t rowBytes);
 
     // GrDrawTarget overrides
-    virtual void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
-                       GrRenderTarget* renderTarget) SK_OVERRIDE;
-
     virtual void clearStencilClip(const SkIRect& rect,
                                   bool insideClip,
                                   GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
@@ -374,7 +371,8 @@
     virtual void releaseReservedIndexSpace() SK_OVERRIDE;
     virtual void geometrySourceWillPush() SK_OVERRIDE;
     virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
-
+    virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+                         GrRenderTarget* renderTarget) SK_OVERRIDE;
 
     // called when the 3D context state is unknown. Subclass should emit any
     // assumed 3D context state and dirty any state cache.
@@ -391,11 +389,9 @@
     virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
     virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0;
 
-    // overridden by backend-specific derived class to perform the clear and
-    // 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(GrRenderTarget*, const SkIRect* rect, GrColor color,
-                         bool canIgnoreRect) = 0;
+    // overridden by backend-specific derived class to perform the clear.
+    virtual void onGpuClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
+                            bool canIgnoreRect) = 0;
 
 
     // Overridden by backend specific classes to perform a clear of the stencil clip bits.  This is
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index ec8972c..64d9cea 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -414,8 +414,8 @@
     this->recordTraceMarkersIfNecessary();
 }
 
-void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
-                                bool canIgnoreRect, GrRenderTarget* renderTarget) {
+void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
+                                  bool canIgnoreRect, GrRenderTarget* renderTarget) {
     SkIRect r;
     if (NULL == renderTarget) {
         renderTarget = this->drawState()->getRenderTarget();
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 714d822..3d7d526 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -86,11 +86,6 @@
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) SK_OVERRIDE;
 
-    virtual void clear(const SkIRect* rect,
-                       GrColor color,
-                       bool canIgnoreRect,
-                       GrRenderTarget* renderTarget) SK_OVERRIDE;
-
     virtual void clearStencilClip(const SkIRect& rect,
                                   bool insideClip,
                                   GrRenderTarget* renderTarget) SK_OVERRIDE;
@@ -274,6 +269,10 @@
                              const uint32_t indices[], int count,
                              const float transforms[], PathTransformType,
                              GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
+    virtual void onClear(const SkIRect* rect,
+                         GrColor color,
+                         bool canIgnoreRect,
+                         GrRenderTarget* renderTarget) SK_OVERRIDE;
 
     virtual bool onReserveVertexSpace(size_t vertexSize,
                                       int vertexCount,
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index ee87a39..6272aba 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -380,6 +380,11 @@
         GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount);
     }
 
+    if (kPowerVR54x_GrGLRenderer == ctxInfo.renderer() ||
+        kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) {
+        fUseDrawInsteadOfClear = true;
+    }
+
     this->initConfigTexturableTable(ctxInfo, gli);
     this->initConfigRenderableTable(ctxInfo);
 
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 96e26c7..9f7b05a 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -191,7 +191,7 @@
             return kQualcomm_GrGLVendor;
         }
         if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
-                return kNVIDIA_GrGLVendor;
+            return kNVIDIA_GrGLVendor;
         }
     }
     return kOther_GrGLVendor;
@@ -204,6 +204,16 @@
         } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
             return kTegra2_GrGLRenderer;
         }
+        int lastDigit;
+        int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
+        if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
+            return kPowerVR54x_GrGLRenderer;
+        }
+        static const char kPowerVRRogueStr[] = "PowerVR Rogue";
+        if (0 == strncmp(rendererString, kPowerVRRogueStr,
+                         SK_ARRAY_COUNT(kPowerVRRogueStr)-1)) {
+            return kPowerVRRogue_GrGLRenderer;
+        }
     }
     return kOther_GrGLRenderer;
 }
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 5025db3..bc6fdf1 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -43,7 +43,8 @@
 enum GrGLRenderer {
     kTegra2_GrGLRenderer,
     kTegra3_GrGLRenderer,
-
+    kPowerVR54x_GrGLRenderer,
+    kPowerVRRogue_GrGLRenderer,
     kOther_GrGLRenderer
 };
 
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 1a5048a..73dd9bb 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1356,8 +1356,8 @@
     }
 }
 
-void GrGpuGL::onClear(GrRenderTarget* target, const SkIRect* rect, GrColor color,
-                      bool canIgnoreRect) {
+void GrGpuGL::onGpuClear(GrRenderTarget* target, const SkIRect* rect, GrColor color,
+                         bool canIgnoreRect) {
     // parent class should never let us get here with no RT
     SkASSERT(target);
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 63fcea6..a8851b8 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -134,8 +134,8 @@
         GrStencilBuffer* sb,
         GrRenderTarget* rt) SK_OVERRIDE;
 
-    virtual void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
-                         bool canIgnoreRect) SK_OVERRIDE;
+    virtual void onGpuClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
+                            bool canIgnoreRect) SK_OVERRIDE;
 
     virtual void onClearStencilClip(GrRenderTarget*,
                                     const SkIRect& rect,