clear stencil buffer using special purpose FBO

Review URL: https://codereview.chromium.org/941383003
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index efe1a61..df8de57 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -97,15 +97,6 @@
         return false;
     }
     if (this->createStencilBufferForRenderTarget(rt, width, height)) {
-        // Right now we're clearing the stencil buffer here after it is
-        // attached to an RT for the first time. When we start matching
-        // stencil buffers with smaller color targets this will no longer
-        // be correct because it won't be guaranteed to clear the entire
-        // sb.
-        // We used to clear down in the GL subclass using a special purpose
-        // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
-        // FBO status.
-        this->clearStencil(rt);
         GrStencilBuffer* sb = rt->renderTargetPriv().getStencilBuffer();
         sb->resourcePriv().setUniqueKey(sbKey);
         return true;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 8710931..9c0f772 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -153,6 +153,7 @@
     fHWProgramID = 0;
     fTempSrcFBOID = 0;
     fTempDstFBOID = 0;
+    fStencilClearFBOID = 0;
 
     if (this->glCaps().pathRenderingSupport()) {
         fPathRendering.reset(new GrGLPathRendering(this));
@@ -173,6 +174,9 @@
     if (0 != fTempDstFBOID) {
         GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
     }
+    if (0 != fStencilClearFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
+    }
 
     delete fProgramCache;
 }
@@ -183,6 +187,7 @@
     fHWProgramID = 0;
     fTempSrcFBOID = 0;
     fTempDstFBOID = 0;
+    fStencilClearFBOID = 0;
     if (this->glCaps().pathRenderingSupport()) {
         this->glPathRendering()->abandonGpuResources();
     }
@@ -1172,11 +1177,44 @@
             // whatever sizes GL gives us. In that case we query for the size.
             GrGLStencilBuffer::Format format = sFmt;
             get_stencil_rb_sizes(this->glInterface(), &format);
-            SkAutoTUnref<GrStencilBuffer> sb(SkNEW_ARGS(GrGLStencilBuffer,
+            SkAutoTUnref<GrGLStencilBuffer> sb(SkNEW_ARGS(GrGLStencilBuffer,
                                                   (this, sbDesc, width, height, samples, format)));
             if (this->attachStencilBufferToRenderTarget(sb, rt)) {
                 fLastSuccessfulStencilFmtIdx = sIdx;
                 rt->renderTargetPriv().didAttachStencilBuffer(sb);
+
+                // Clear the stencil buffer. We use a special purpose FBO for this so that the
+                // entire stencil buffer is cleared, even if it is attached to an FBO with a
+                // smaller color target.
+                if (0 == fStencilClearFBOID) {
+                    GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
+                }
+
+                GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID));
+                fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+                fStats.incRenderTargetBinds();
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                                GR_GL_STENCIL_ATTACHMENT,
+                                                GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+                if (sFmt.fPacked) {
+                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                                    GR_GL_DEPTH_ATTACHMENT,
+                                                    GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+                }
+
+                GL_CALL(ClearStencil(0));
+                GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
+
+                // Unbind the SB from the FBO so that we don't keep it alive.
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                                GR_GL_STENCIL_ATTACHMENT,
+                                                GR_GL_RENDERBUFFER, 0));
+                if (sFmt.fPacked) {
+                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                                    GR_GL_DEPTH_ATTACHMENT,
+                                                    GR_GL_RENDERBUFFER, 0));
+                }
+
                 return true;
             }
             // Remove the scratch key from this resource so we don't grab it from the cache ever
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 7cbca01..b93080b 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -312,6 +312,8 @@
     GrGLuint                    fTempSrcFBOID;
     GrGLuint                    fTempDstFBOID;
 
+    GrGLuint                    fStencilClearFBOID;
+
     // last scissor / viewport scissor state seen by the GL.
     struct {
         TriState    fEnabled;