Add flag bits for partial GrContext reset

BUG=248728
R=bsalomon@google.com

Committed: https://code.google.com/p/skia/source/detail?r=9802

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9814 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index c94c1a9..fe8f4fd 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -204,8 +204,8 @@
     fGpu->markContextDirty();
 }
 
-void GrContext::resetContext() {
-    fGpu->markContextDirty();
+void GrContext::resetContext(uint32_t state) {
+    fGpu->markContextDirty(state);
 }
 
 void GrContext::freeGpuResources() {
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index ae98b54..5d6c62f 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -30,12 +30,12 @@
 GrGpu::GrGpu(GrContext* context)
     : GrDrawTarget(context)
     , fResetTimestamp(kExpiredTimestamp+1)
+    , fResetBits(kAll_GrBackendState)
     , fVertexPool(NULL)
     , fIndexPool(NULL)
     , fVertexPoolUseCnt(0)
     , fIndexPoolUseCnt(0)
-    , fQuadIndexBuffer(NULL)
-    , fContextIsDirty(true) {
+    , fQuadIndexBuffer(NULL) {
 
     fClipMaskManager.setGpu(this);
 
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 3acfac2..85e3988 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -66,7 +66,9 @@
      * the GrGpu that the state was modified and it shouldn't make assumptions
      * about the state.
      */
-    void markContextDirty() { fContextIsDirty = true; }
+    void markContextDirty(uint32_t state = kAll_GrBackendState) {
+        fResetBits |= state;
+    }
 
     void unimpl(const char[]);
 
@@ -426,7 +428,7 @@
 
     // called when the 3D context state is unknown. Subclass should emit any
     // assumed 3D context state and dirty any state cache.
-    virtual void onResetContext() = 0;
+    virtual void onResetContext(uint32_t resetBits) = 0;
 
     // overridden by backend-specific derived class to create objects.
     virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
@@ -507,14 +509,14 @@
         // stencil buffer. Perhaps we should detect whether it is a
         // internally created stencil buffer and if so skip the invalidate.
         fClipMaskManager.invalidateStencilMask();
-        this->onResetContext();
+        this->onResetContext(fResetBits);
+        fResetBits = 0;
         ++fResetTimestamp;
     }
 
     void handleDirtyContext() {
-        if (fContextIsDirty) {
+        if (fResetBits) {
             this->resetContext();
-            fContextIsDirty = false;
         }
     }
 
@@ -524,6 +526,7 @@
     typedef SkTInternalLList<GrResource> ResourceList;
     SkSTArray<kPreallocGeomPoolStateStackCnt, GeometryPoolState, true>  fGeomPoolStateStack;
     ResetTimestamp                                                      fResetTimestamp;
+    uint32_t                                                            fResetBits;
     GrVertexBufferAllocPool*                                            fVertexPool;
     GrIndexBufferAllocPool*                                             fIndexPool;
     // counts number of uses of vertex/index pool in the geometry stack
@@ -531,7 +534,6 @@
     int                                                                 fIndexPoolUseCnt;
     // these are mutable so they can be created on-demand
     mutable GrIndexBuffer*                                              fQuadIndexBuffer;
-    bool                                                                fContextIsDirty;
     // Used to abandon/release all resources created by this GrGpu. TODO: Move this
     // functionality to GrResourceCache.
     ResourceList                                                        fResourceList;
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index d96ea39..0ffcc27 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -153,6 +153,7 @@
     GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt);
 
     fLastSuccessfulStencilFmtIdx = 0;
+    fHWProgramID = 0;
 }
 
 GrGpuGL::~GrGpuGL() {
@@ -282,88 +283,109 @@
     return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL);
 }
 
-void GrGpuGL::onResetContext() {
-
+void GrGpuGL::onResetContext(uint32_t resetBits) {
     // we don't use the zb at all
-    GL_CALL(Disable(GR_GL_DEPTH_TEST));
-    GL_CALL(DepthMask(GR_GL_FALSE));
+    if (resetBits & kMisc_GrGLBackendState) {
+        GL_CALL(Disable(GR_GL_DEPTH_TEST));
+        GL_CALL(DepthMask(GR_GL_FALSE));
 
-    fHWDrawFace = GrDrawState::kInvalid_DrawFace;
-    fHWDitherEnabled = kUnknown_TriState;
+        fHWDrawFace = GrDrawState::kInvalid_DrawFace;
+        fHWDitherEnabled = kUnknown_TriState;
 
-    if (kDesktop_GrGLBinding == this->glBinding()) {
-        // Desktop-only state that we never change
-        if (!this->glCaps().isCoreProfile()) {
-            GL_CALL(Disable(GR_GL_POINT_SMOOTH));
-            GL_CALL(Disable(GR_GL_LINE_SMOOTH));
-            GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
-            GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
-            GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
-            GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
+        if (kDesktop_GrGLBinding == this->glBinding()) {
+            // Desktop-only state that we never change
+            if (!this->glCaps().isCoreProfile()) {
+                GL_CALL(Disable(GR_GL_POINT_SMOOTH));
+                GL_CALL(Disable(GR_GL_LINE_SMOOTH));
+                GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
+                GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
+                GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
+                GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
+            }
+            // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a
+            // core profile. This seems like a bug since the core spec removes any mention of
+            // GL_ARB_imaging.
+            if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
+                GL_CALL(Disable(GR_GL_COLOR_TABLE));
+            }
+            GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
+            // Since ES doesn't support glPointSize at all we always use the VS to
+            // set the point size
+            GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
+
+            // We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
+            // currently part of our gl interface. There are probably others as
+            // well.
         }
-        // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a core
-        // profile. This seems like a bug since the core spec removes any mention of GL_ARB_imaging.
-        if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
-            GL_CALL(Disable(GR_GL_COLOR_TABLE));
-        }
-        GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
-        // Since ES doesn't support glPointSize at all we always use the VS to
-        // set the point size
-        GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
-
-        // We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
-        // currently part of our gl interface. There are probably others as
-        // well.
+        fHWWriteToColor = kUnknown_TriState;
+        // we only ever use lines in hairline mode
+        GL_CALL(LineWidth(1));
     }
-    fHWAAState.invalidate();
-    fHWWriteToColor = kUnknown_TriState;
 
-    // we only ever use lines in hairline mode
-    GL_CALL(LineWidth(1));
+    if (resetBits & kAA_GrGLBackendState) {
+        fHWAAState.invalidate();
+    }
 
     // invalid
-    fHWActiveTextureUnitIdx = -1;
-
-    fHWBlendState.invalidate();
-
-    for (int s = 0; s < fHWBoundTextures.count(); ++s) {
-        fHWBoundTextures[s] = NULL;
+    if (resetBits & kTextureBinding_GrGLBackendState) {
+        fHWActiveTextureUnitIdx = -1;
+        for (int s = 0; s < fHWBoundTextures.count(); ++s) {
+            fHWBoundTextures[s] = NULL;
+        }
     }
 
-    fHWScissorSettings.invalidate();
+    if (resetBits & kBlend_GrGLBackendState) {
+        fHWBlendState.invalidate();
+    }
 
-    fHWViewport.invalidate();
+    if (resetBits & kView_GrGLBackendState) {
+        fHWScissorSettings.invalidate();
+        fHWViewport.invalidate();
+    }
 
-    fHWStencilSettings.invalidate();
-    fHWStencilTestEnabled = kUnknown_TriState;
+    if (resetBits & kStencil_GrGLBackendState) {
+        fHWStencilSettings.invalidate();
+        fHWStencilTestEnabled = kUnknown_TriState;
+    }
 
-    fHWGeometryState.invalidate();
+    // Vertex
+    if (resetBits & kVertex_GrGLBackendState) {
+        fHWGeometryState.invalidate();
+    }
 
-    fHWBoundRenderTarget = NULL;
+    if (resetBits & kRenderTarget_GrGLBackendState) {
+        fHWBoundRenderTarget = NULL;
+    }
 
-    fHWPathStencilMatrixState.invalidate();
-    if (this->caps()->pathStencilingSupport()) {
-        // we don't use the model view matrix.
-        GL_CALL(MatrixMode(GR_GL_MODELVIEW));
-        GL_CALL(LoadIdentity());
+    if (resetBits & kPathStencil_GrGLBackendState) {
+        fHWPathStencilMatrixState.invalidate();
+        if (this->caps()->pathStencilingSupport()) {
+            // we don't use the model view matrix.
+            GL_CALL(MatrixMode(GR_GL_MODELVIEW));
+            GL_CALL(LoadIdentity());
+        }
     }
 
     // we assume these values
-    if (this->glCaps().unpackRowLengthSupport()) {
-        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
-    }
-    if (this->glCaps().packRowLengthSupport()) {
-        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
-    }
-    if (this->glCaps().unpackFlipYSupport()) {
-        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
-    }
-    if (this->glCaps().packFlipYSupport()) {
-        GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
+    if (resetBits & kPixelStore_GrGLBackendState) {
+        if (this->glCaps().unpackRowLengthSupport()) {
+            GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
+        }
+        if (this->glCaps().packRowLengthSupport()) {
+            GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
+        }
+        if (this->glCaps().unpackFlipYSupport()) {
+            GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
+        }
+        if (this->glCaps().packFlipYSupport()) {
+            GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
+        }
     }
 
-    fHWProgramID = 0;
-    fSharedGLProgramState.invalidate();
+    if (resetBits & kProgram_GrGLBackendState) {
+        fHWProgramID = 0;
+        fSharedGLProgramState.invalidate();
+    }
 }
 
 namespace {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index c644fbb..38e5842 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -102,7 +102,7 @@
 
 private:
     // GrGpu overrides
-    virtual void onResetContext() SK_OVERRIDE;
+    virtual void onResetContext(uint32_t resetBits) SK_OVERRIDE;
 
     virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
                                        const void* srcData,