Reduce GrGLProgram::ProgramDesc from 88B to 24B.
http://codereview.appspot.com/4561058.



git-svn-id: http://skia.googlecode.com/svn/trunk@1480 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index af83801..ecb4753 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -86,14 +86,14 @@
 }
 
 static inline const char* all_ones_vec(int count) {
-    static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)", 
+    static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
                                     "vec3(1,1,1)", "vec4(1,1,1,1)"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
     return ONESVEC[count];
 }
 
 static inline const char* all_zeros_vec(int count) {
-    static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)", 
+    static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
                                     "vec3(0,0,0)", "vec4(0,0,0,0)"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
     return ZEROSVEC[count];
@@ -337,7 +337,9 @@
     // The rest of transfer mode color filters have not been implemented
     if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
         GR_DEBUGCODE(bool success =)
-            SkXfermode::ModeAsCoeff(fProgramDesc.fColorFilterXfermode, &uniformCoeff, &colorCoeff);
+            SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
+                                    (fProgramDesc.fColorFilterXfermode),
+                                    &uniformCoeff, &colorCoeff);
         GR_DEBUGASSERT(success);
     } else {
         colorCoeff = SkXfermode::kOne_Coeff;
@@ -423,7 +425,7 @@
     if (needComputedColor) {
         GrStringBuilder outColor;
         for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) {
-            if (fProgramDesc.fStages[s].fEnabled) {
+            if (fProgramDesc.fStages[s].isEnabled()) {
                 // create var to hold stage result
                 outColor = "color";
                 outColor.appendS32(s);
@@ -456,12 +458,12 @@
 
     // if have all ones for the "dst" input to the color filter then we can make
     // additional optimizations.
-    if (needColorFilterUniform && !inColor.size() && 
+    if (needColorFilterUniform && !inColor.size() &&
         (SkXfermode::kIDC_Coeff == uniformCoeff ||
          SkXfermode::kIDA_Coeff == uniformCoeff)) {
           uniformCoeff = SkXfermode::kZero_Coeff;
           bool bogus;
-          needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, 
+          needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff,
                           &needColorFilterUniform, &bogus);
     }
     if (needColorFilterUniform) {
@@ -470,16 +472,16 @@
     }
 
     bool wroteFragColorZero = false;
-    if (SkXfermode::kZero_Coeff == uniformCoeff && 
+    if (SkXfermode::kZero_Coeff == uniformCoeff &&
         SkXfermode::kZero_Coeff == colorCoeff) {
-        segments.fFSCode.appendf("\t%s = %s;\n", 
+        segments.fFSCode.appendf("\t%s = %s;\n",
                                  fsColorOutput,
                                  all_zeros_vec(4));
         wroteFragColorZero = true;
     } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) {
         segments.fFSCode.appendf("\tvec4 filteredColor;\n");
         const char* color = inColor.size() ? inColor.c_str() : all_ones_vec(4);
-        addColorFilter(&segments.fFSCode, "filteredColor", uniformCoeff, 
+        addColorFilter(&segments.fFSCode, "filteredColor", uniformCoeff,
                        colorCoeff, color);
         inColor = "filteredColor";
     }
@@ -529,8 +531,7 @@
         GrStringBuilder outCoverage;
         const int& startStage = fProgramDesc.fFirstCoverageStage;
         for (int s = startStage; s < GrDrawTarget::kNumStages; ++s) {
-            if (fProgramDesc.fStages[s].fEnabled) {
-
+            if (fProgramDesc.fStages[s].isEnabled()) {
                 // create var to hold stage output
                 outCoverage = "coverage";
                 outCoverage.appendS32(s);
@@ -559,16 +560,16 @@
             }
         }
         if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
-            segments.fFSOutputs.appendf("out vec4 %s;\n", 
+            segments.fFSOutputs.appendf("out vec4 %s;\n",
                                         dual_source_output_name());
             bool outputIsZero = false;
             GrStringBuilder coeff;
-            if (ProgramDesc::kCoverage_DualSrcOutput != 
+            if (ProgramDesc::kCoverage_DualSrcOutput !=
                 fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
                 if (!inColor.size()) {
                     outputIsZero = true;
                 } else {
-                    if (fProgramDesc.fDualSrcOutput == 
+                    if (fProgramDesc.fDualSrcOutput ==
                         ProgramDesc::kCoverageISA_DualSrcOutput) {
                         coeff.printf("(1 - %s.a)", inColor.c_str());
                     } else {
@@ -577,7 +578,7 @@
                 }
             }
             if (outputIsZero) {
-                segments.fFSCode.appendf("\t%s = %s;\n", 
+                segments.fFSCode.appendf("\t%s = %s;\n",
                                          dual_source_output_name(),
                                          all_zeros_vec(4));
             } else {
@@ -768,7 +769,7 @@
 bool GrGLProgram::bindOutputsAttribsAndLinkProgram(
                                         GrStringBuilder texCoordAttrNames[],
                                         bool bindColorOut,
-                                        bool bindDualSrcOut, 
+                                        bool bindDualSrcOut,
                                         CachedData* programData) const {
     programData->fProgramID = GR_GL(CreateProgram());
     if (!programData->fProgramID) {
@@ -780,7 +781,7 @@
     GR_GL(AttachShader(progID, programData->fFShaderID));
 
     if (bindColorOut) {
-        GR_GL(BindFragDataLocationIndexed(programData->fProgramID, 
+        GR_GL(BindFragDataLocationIndexed(programData->fProgramID,
                                           0, 0, declared_color_output_name()));
     }
     if (bindDualSrcOut) {
@@ -849,18 +850,18 @@
         GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
     }
     if (kUseUniform == programData->fUniLocations.fColorUni) {
-        programData->fUniLocations.fColorUni = 
+        programData->fUniLocations.fColorUni =
                                 GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
         GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
     }
     if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
-        programData->fUniLocations.fColorFilterUni = 
+        programData->fUniLocations.fColorFilterUni =
                         GR_GL(GetUniformLocation(progID, COL_FILTER_UNI_NAME));
         GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
     }
 
     if (kUseUniform == programData->fUniLocations.fEdgesUni) {
-        programData->fUniLocations.fEdgesUni = 
+        programData->fUniLocations.fEdgesUni =
             GR_GL(GetUniformLocation(progID, EDGES_UNI_NAME));
         GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni);
     } else {
@@ -869,7 +870,7 @@
 
     for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
         StageUniLocations& locations = programData->fUniLocations.fStages[s];
-        if (fProgramDesc.fStages[s].fEnabled) {
+        if (fProgramDesc.fStages[s].isEnabled()) {
             if (kUseUniform == locations.fTextureMatrixUni) {
                 GrStringBuilder texMName;
                 tex_matrix_name(s, &texMName);
@@ -891,7 +892,7 @@
             if (kUseUniform == locations.fNormalizedTexelSizeUni) {
                 GrStringBuilder texelSizeName;
                 normalized_texel_size_name(s, &texelSizeName);
-                locations.fNormalizedTexelSizeUni = 
+                locations.fNormalizedTexelSizeUni =
                    GR_GL(GetUniformLocation(progID, texelSizeName.c_str()));
                 GrAssert(kUnusedUniform != locations.fNormalizedTexelSizeUni);
             }
@@ -989,7 +990,7 @@
         segments->fFSUnis.appendf("uniform vec2 %s;\n", texelSizeName.c_str());
     }
 
-    segments->fVaryings.appendf("varying %s %s;\n", 
+    segments->fVaryings.appendf("varying %s %s;\n",
                                 float_vector_type(varyingDims), varyingName.c_str());
 
     if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
@@ -1011,9 +1012,9 @@
 
     if (ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
 
-        segments->fVSUnis.appendf("uniform %s float %s[6];\n", 
+        segments->fVSUnis.appendf("uniform %s float %s[6];\n",
                                   GrPrecision(), radial2ParamsName.c_str());
-        segments->fFSUnis.appendf("uniform float %s[6];\n", 
+        segments->fFSUnis.appendf("uniform float %s[6];\n",
                                   radial2ParamsName.c_str());
         locations->fRadial2Uni = kUseUniform;
 
@@ -1132,11 +1133,11 @@
         modulate.printf(" * %s", fsInColor);
     }
 
-    if (desc.fOptFlags & 
+    if (desc.fOptFlags &
         ProgramDesc::StageDesc::kCustomTextureDomain_OptFlagBit) {
         GrStringBuilder texDomainName;
         tex_domain_name(stageNum, &texDomainName);
-        segments->fFSUnis.appendf("uniform %s %s;\n", 
+        segments->fFSUnis.appendf("uniform %s %s;\n",
                                   float_vector_type(4),
                                   texDomainName.c_str());
         GrStringBuilder coordVar("clampCoord");
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index f6258ab..473bcb6 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -78,16 +78,18 @@
     static int PositionAttributeIdx() { return 0; }
     static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
     static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; }
-    static int ViewMatrixAttributeIdx() { 
-        return 2 + GrDrawTarget::kMaxTexCoords; 
+    static int ViewMatrixAttributeIdx() {
+        return 2 + GrDrawTarget::kMaxTexCoords;
     }
-    static int TextureMatrixAttributeIdx(int stage) { 
-        return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage; 
+    static int TextureMatrixAttributeIdx(int stage) {
+        return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage;
     }
 
 private:
 
-    //Parameters that affect code generation
+    // Parameters that affect code generation
+    // These structs should be kept compact; they are the input to an
+    // expensive hash key generator.
     struct ProgramDesc {
         ProgramDesc() {
             // since we use this as part of a key we can't have any unitialized
@@ -95,16 +97,51 @@
             memset(this, 0, sizeof(ProgramDesc));
         }
 
-        // stripped of bits that don't affect prog generation
-        GrVertexLayout fVertexLayout;
+        struct StageDesc {
+            enum OptFlagBits {
+                kNoPerspective_OptFlagBit       = 1 << 0,
+                kIdentityMatrix_OptFlagBit      = 1 << 1,
+                kCustomTextureDomain_OptFlagBit = 1 << 2,
+                kIsEnabled_OptFlagBit           = 1 << 7
+            };
+            enum Modulation {
+                kColor_Modulation,
+                kAlpha_Modulation
+            };
+            enum FetchMode {
+                kSingle_FetchMode,
+                k2x2_FetchMode
+            };
+            enum CoordMapping {
+                kIdentity_CoordMapping,
+                kRadialGradient_CoordMapping,
+                kSweepGradient_CoordMapping,
+                kRadial2Gradient_CoordMapping
+            };
 
-        enum {
+            uint8_t fOptFlags;
+            uint8_t fModulation;  // casts to enum Modulation
+            uint8_t fFetchMode;  // casts to enum FetchMode
+            uint8_t fCoordMapping;  // casts to enum CoordMapping
+
+            inline bool isEnabled() const {
+                return fOptFlags & kIsEnabled_OptFlagBit;
+            }
+            inline void setEnabled(bool newValue) {
+                if (newValue) {
+                    fOptFlags |= kIsEnabled_OptFlagBit;
+                } else {
+                    fOptFlags &= ~kIsEnabled_OptFlagBit;
+                }
+            }
+        };
+
+        enum ColorType {
             kNone_ColorType         = 0,
             kAttribute_ColorType    = 1,
             kUniform_ColorType      = 2,
-        } fColorType;
-
-        // Dual-src blending makes use of a secondary output color that can be 
+        };
+        // Dual-src blending makes use of a secondary output color that can be
         // used as a per-pixel blend coeffecient. This controls whether a
         // secondary source is output and what value it holds.
         enum DualSrcOutput {
@@ -113,41 +150,23 @@
             kCoverageISA_DualSrcOutput,
             kCoverageISC_DualSrcOutput,
             kDualSrcOutputCnt
-        } fDualSrcOutput;
+        };
 
-        int  fFirstCoverageStage;
-        bool fEmitsPointSize;
-        int fEdgeAANumEdges;
+        // stripped of bits that don't affect prog generation
+        GrVertexLayout fVertexLayout;
 
-        SkXfermode::Mode fColorFilterXfermode;
+        StageDesc fStages[GrDrawTarget::kNumStages];
 
-        struct StageDesc {
-            enum OptFlagBits {
-                kNoPerspective_OptFlagBit       = 1 << 0,
-                kIdentityMatrix_OptFlagBit      = 1 << 1,
-                kCustomTextureDomain_OptFlagBit = 1 << 2
-            };
+        uint8_t fColorType;  // casts to enum ColorType
+        uint8_t fDualSrcOutput;  // casts to enum DualSrcOutput
+        int8_t fFirstCoverageStage;
+        SkBool8 fEmitsPointSize;
 
-            unsigned fOptFlags;
-            bool fEnabled;
+        int8_t fEdgeAANumEdges;
+        uint8_t fColorFilterXfermode;  // casts to enum SkXfermode::Mode
 
-            enum Modulation {
-                kColor_Modulation,
-                kAlpha_Modulation
-            } fModulation;
+        uint8_t fPadTo32bLengthMultiple [2];
 
-            enum FetchMode {
-                kSingle_FetchMode,
-                k2x2_FetchMode
-            } fFetchMode;
-
-            enum CoordMapping {
-                kIdentity_CoordMapping,
-                kRadialGradient_CoordMapping,
-                kSweepGradient_CoordMapping,
-                kRadial2Gradient_CoordMapping
-            } fCoordMapping;
-        } fStages[GrDrawTarget::kNumStages];
     } fProgramDesc;
 
     const ProgramDesc& getDesc() { return fProgramDesc; }
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 6d4b4b1..bd57291 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -196,11 +196,11 @@
         pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1));
 
         if (fDualSourceBlendingSupport) {
-            pdesc.fDualSrcOutput = 
+            pdesc.fDualSrcOutput =
                (GrGLProgram::ProgramDesc::DualSrcOutput)
                (int)(random.nextF() * GrGLProgram::ProgramDesc::kDualSrcOutputCnt);
         } else {
-            pdesc.fDualSrcOutput = 
+            pdesc.fDualSrcOutput =
                                 GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
         }
 
@@ -219,7 +219,6 @@
             if (random.nextF() > .5f) {
                 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
             }
-            pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
             idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
             pdesc.fStages[s].fOptFlags = STAGE_OPTS[idx];
             idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
@@ -228,6 +227,7 @@
             pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[idx];
             idx = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES));
             pdesc.fStages[s].fFetchMode = FETCH_MODES[idx];
+            pdesc.fStages[s].setEnabled(VertexUsesStage(s, pdesc.fVertexLayout));
         }
         GrGLProgram::CachedData cachedData;
         program.genProgram(&cachedData);
@@ -730,20 +730,19 @@
     for (int s = 0; s < kNumStages; ++s) {
         GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
 
-        stage.fEnabled = this->isStageEnabled(s);
+        stage.fOptFlags = 0;
+        stage.setEnabled(this->isStageEnabled(s));
 
-        if (stage.fEnabled) {
+        if (stage.isEnabled()) {
             lastEnabledStage = s;
             GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
             GrAssert(NULL != texture);
             // we matrix to invert when orientation is TopDown, so make sure
             // we aren't in that case before flagging as identity.
             if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
-                stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit;
+                stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit;
             } else if (!getSamplerMatrix(s).hasPerspective()) {
-                stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit;
-            } else {
-                stage.fOptFlags = 0;
+                stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit;
             }
             switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
                 case GrSamplerState::kNormal_SampleMode:
@@ -779,11 +778,11 @@
             }
 
             if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
-                GrAssert(GrSamplerState::kClamp_WrapMode == 
-                    fCurrDrawState.fSamplerStates[s].getWrapX() && 
+                GrAssert(GrSamplerState::kClamp_WrapMode ==
+                    fCurrDrawState.fSamplerStates[s].getWrapX() &&
                     GrSamplerState::kClamp_WrapMode ==
                     fCurrDrawState.fSamplerStates[s].getWrapY());
-                stage.fOptFlags |= 
+                stage.fOptFlags |=
                     GrGLProgram::ProgramDesc::StageDesc::
                     kCustomTextureDomain_OptFlagBit;
             }
@@ -837,5 +836,3 @@
         }
     }
 }
-
-