Remove dirty flags from GrGpuGL state flush

Review URL: http://codereview.appspot.com/6255073/



git-svn-id: http://skia.googlecode.com/svn/trunk@4122 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 0d674ee..7233233 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -1193,6 +1193,9 @@
         programData->fTextureWidth[s] = -1;
         programData->fTextureHeight[s] = -1;
         programData->fTextureDomain[s].setEmpty();
+        // this is arbitrary, just initialize to something
+        programData->fTextureOrientation[s] =
+            GrGLTexture::kBottomUp_Orientation;
         // Must not reset fStageOverride[] here.
     }
     programData->fViewMatrix = GrMatrix::InvalidMatrix();
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index bfb1f1c..393311e 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -12,6 +12,7 @@
 #include "GrDrawState.h"
 #include "GrGLContextInfo.h"
 #include "GrGLSL.h"
+#include "GrGLTexture.h"
 #include "GrStringBuilder.h"
 #include "GrGpu.h"
 
@@ -336,6 +337,9 @@
         GrScalar                    fRadial2Radius0[GrDrawState::kNumStages];
         bool                        fRadial2PosRoot[GrDrawState::kNumStages];
         GrRect                      fTextureDomain[GrDrawState::kNumStages];
+        // The texture domain and texture matrix sent to GL depend upon the
+        // orientation.
+        GrGLTexture::Orientation    fTextureOrientation[GrDrawState::kNumStages];
 
         GrGLProgramStage*           fCustomStage[GrDrawState::kNumStages];
 
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 8817068..ec535b8 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -111,40 +111,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
-                                  GrSamplerState::SampleMode mode,
-                                  GrMatrix* matrix) {
-    GrAssert(NULL != texture);
-    GrAssert(NULL != matrix);
-    GrGLTexture::Orientation orientation = texture->orientation();
-    if (GrGLTexture::kBottomUp_Orientation == orientation) {
-        GrMatrix invY;
-        invY.setAll(GR_Scalar1, 0,           0,
-                    0,          -GR_Scalar1, GR_Scalar1,
-                    0,          0,           GrMatrix::I()[8]);
-        matrix->postConcat(invY);
-    } else {
-        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
-    }
-}
-
-bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
-                                      const GrSamplerState& sampler) {
-    GrAssert(NULL != texture);
-    if (!sampler.getMatrix().isIdentity()) {
-        return false;
-    }
-    GrGLTexture::Orientation orientation = texture->orientation();
-    if (GrGLTexture::kBottomUp_Orientation == orientation) {
-        return false;
-    } else {
-        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
-    }
-    return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 static bool gPrintStartupSpew;
 
 static bool fbo_test(const GrGLInterface* gl, int w, int h) {
@@ -203,8 +169,6 @@
         GrPrintf("------ EXTENSIONS\n %s \n", ext);
     }
 
-    this->resetDirtyFlags();
-
     this->initCaps();
 
     fProgramData = NULL;
@@ -1657,12 +1621,14 @@
             GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
         }
     #endif
-        fDirtyFlags.fRenderTargetChanged = true;
         fHWBoundRenderTarget = rt;
         const GrGLIRect& vp = rt->getViewport();
         if (fHWBounds.fViewportRect != vp) {
             vp.pushToGLViewport(this->glInterface());
             fHWBounds.fViewportRect = vp;
+            // View matrices pushed to GL depend upon the viewport. So they
+            // are now invalid.
+            fProgramCache->invalidateViewMatrices();
         }
     }
     if (NULL == bound || !bound->isEmpty()) {
@@ -2177,9 +2143,6 @@
             #endif
                 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
                 fHWBoundTextures[s] = nextTexture;
-                // The texture matrix has to compensate for texture width/height
-                // and NPOT-embedded-in-POT
-                fDirtyFlags.fTextureChangedMask |= (1 << s);
             }
 
             const GrSamplerState& sampler = drawState->getSampler(s);
@@ -2480,10 +2443,6 @@
     }
 }
 
-void GrGpuGL::resetDirtyFlags() {
-    Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
-}
-
 void GrGpuGL::setBuffers(bool indexed,
                          int* extraVertexOffset,
                          int* extraIndexOffset) {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 7cbd230..211dea8 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -76,26 +76,6 @@
         kDownOnWrite_UpOnRead_UnpremulConversion
     } fUnpremulConversion;
 
-    // The current render target and textures are bound by GrGpuGL when it
-    // flushes state to GL. After the bindings occur the variables that track
-    // the current GL state are updated to reflect the new bindings. However,
-    // the GrGpuGL subclass may have subsequent GL state manipulation it must
-    // perform whenever RT or textures change. So the GrGpuGL will set these
-    // dirty flags when it changes the RT or texture bindings. The subclass can
-    // use them to trigger its dependent state flushing. The subclass should
-    // call resetDirtyFlags to zero these out after it has consumed them.
-    //
-    // TODO: Merge GrGpuGLShaders into GrGpuGL and remove the need for these
-    // flags.
-    struct {
-        bool fRenderTargetChanged : 1;
-        int  fTextureChangedMask;
-    } fDirtyFlags;
-    GR_STATIC_ASSERT(8 * sizeof(int) >= GrDrawState::kNumStages);
-
-    // clears the dirty flags
-    void resetDirtyFlags();
-
     // last scissor / viewport scissor state seen by the GL.
     struct {
         bool        fScissorEnabled;
@@ -260,11 +240,8 @@
         const GrGLContextInfo&      fGL;
     };
 
-    // sets the texture matrix uniform for currently bound program
-    void flushTextureMatrix(int stage);
-
-    // sets the texture domain uniform for currently bound program
-    void flushTextureDomain(int stage);
+    // sets the texture matrix and domain for the currently bound program
+    void flushTextureMatrixAndDomain(int stage);
 
     // sets the color specified by GrDrawState::setColor()
     void flushColor(GrColor color);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index b8fcb1b..c349407 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -366,53 +366,61 @@
     }
 }
 
-void GrGpuGL::flushTextureDomain(int s) {
-    const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
-    const GrDrawState& drawState = this->getDrawState();
-    if (GrGLProgram::kUnusedUniform != uni) {
-        const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
+///////////////////////////////////////////////////////////////////////////////
 
-        if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
-            fProgramData->fTextureDomain[s] != texDom) {
+// helpers for texture matrices
 
-            fProgramData->fTextureDomain[s] = texDom;
-
-            float values[4] = {
-                GrScalarToFloat(texDom.left()),
-                GrScalarToFloat(texDom.top()),
-                GrScalarToFloat(texDom.right()),
-                GrScalarToFloat(texDom.bottom())
-            };
-
-            const GrGLTexture* texture =
-                static_cast<const GrGLTexture*>(drawState.getTexture(s));
-            GrGLTexture::Orientation orientation = texture->orientation();
-
-            // vertical flip if necessary
-            if (GrGLTexture::kBottomUp_Orientation == orientation) {
-                values[1] = 1.0f - values[1];
-                values[3] = 1.0f - values[3];
-                // The top and bottom were just flipped, so correct the ordering
-                // of elements so that values = (l, t, r, b).
-                SkTSwap(values[1], values[3]);
-            }
-
-            GL_CALL(Uniform4fv(uni, 1, values));
-        }
+void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
+                                  GrSamplerState::SampleMode mode,
+                                  GrMatrix* matrix) {
+    GrAssert(NULL != texture);
+    GrAssert(NULL != matrix);
+    GrGLTexture::Orientation orientation = texture->orientation();
+    if (GrGLTexture::kBottomUp_Orientation == orientation) {
+        GrMatrix invY;
+        invY.setAll(GR_Scalar1, 0,           0,
+                    0,          -GR_Scalar1, GR_Scalar1,
+                    0,          0,           GrMatrix::I()[8]);
+        matrix->postConcat(invY);
+    } else {
+        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
     }
 }
 
-void GrGpuGL::flushTextureMatrix(int s) {
-    const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
+bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
+                                      const GrSamplerState& sampler) {
+    GrAssert(NULL != texture);
+    if (!sampler.getMatrix().isIdentity()) {
+        return false;
+    }
+    GrGLTexture::Orientation orientation = texture->orientation();
+    if (GrGLTexture::kBottomUp_Orientation == orientation) {
+        return false;
+    } else {
+        GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
+    }
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrGpuGL::flushTextureMatrixAndDomain(int s) {
     const GrDrawState& drawState = this->getDrawState();
     const GrGLTexture* texture =
         static_cast<const GrGLTexture*>(drawState.getTexture(s));
     if (NULL != texture) {
+
+        bool orientationChange = fProgramData->fTextureOrientation[s] !=
+                                 texture->orientation();
+
+        const GrGLint& matrixUni =
+            fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
+
         const GrMatrix& hwMatrix = fProgramData->fTextureMatrices[s];
         const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
-        if (GrGLProgram::kUnusedUniform != uni &&
-            (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
-            !hwMatrix.cheapEqualTo(samplerMatrix))) {
+
+        if (GrGLProgram::kUnusedUniform != matrixUni &&
+            (orientationChange || !hwMatrix.cheapEqualTo(samplerMatrix))) {
 
             GrMatrix m = samplerMatrix;
             GrSamplerState::SampleMode mode =
@@ -433,9 +441,36 @@
                 GrScalarToFloat(m[GrMatrix::kMPersp2])
             };
 
-            GL_CALL(UniformMatrix3fv(uni, 1, false, mt));
+            GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt));
             fProgramData->fTextureMatrices[s] = samplerMatrix;
         }
+
+        const GrGLint& domUni = 
+            fProgramData->fUniLocations.fStages[s].fTexDomUni;
+        const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
+        if (GrGLProgram::kUnusedUniform != domUni &&
+            (orientationChange ||fProgramData->fTextureDomain[s] != texDom)) {
+
+            fProgramData->fTextureDomain[s] = texDom;
+
+            float values[4] = {
+                GrScalarToFloat(texDom.left()),
+                GrScalarToFloat(texDom.top()),
+                GrScalarToFloat(texDom.right()),
+                GrScalarToFloat(texDom.bottom())
+            };
+
+            // vertical flip if necessary
+            if (GrGLTexture::kBottomUp_Orientation == texture->orientation()) {
+                values[1] = 1.0f - values[1];
+                values[3] = 1.0f - values[3];
+                // The top and bottom were just flipped, so correct the ordering
+                // of elements so that values = (l, t, r, b).
+                SkTSwap(values[1], values[3]);
+            }
+            GL_CALL(Uniform4fv(domUni, 1, values));
+        }
+        fProgramData->fTextureOrientation[s] = texture->orientation();
     }
 }
 
@@ -619,11 +654,6 @@
 
     const GrDrawState& drawState = this->getDrawState();
 
-    if (fDirtyFlags.fRenderTargetChanged) {
-        // we assume all shader matrices may be wrong after viewport changes
-        fProgramCache->invalidateViewMatrices();
-    }
-
     GrBlendCoeff srcCoeff;
     GrBlendCoeff dstCoeff;
     BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
@@ -666,14 +696,12 @@
 
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         if (this->isStageEnabled(s)) {
-            this->flushTextureMatrix(s);
+            this->flushTextureMatrixAndDomain(s);
 
             this->flushRadial2(s);
 
             this->flushTexelSize(s);
 
-            this->flushTextureDomain(s);
-
             if (NULL != fProgramData->fCustomStage[s]) {
                 const GrSamplerState& sampler =
                     this->getDrawState().getSampler(s);
@@ -687,7 +715,6 @@
         }
     }
     this->flushColorMatrix();
-    resetDirtyFlags();
     return true;
 }