Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2011 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 #include "GrBinHashKey.h"
     18 #include "GrGLProgram.h"
     19 #include "GrGpuGLShaders.h"
     20 #include "GrGpuVertex.h"
     21 #include "GrMemory.h"
     22 #include "GrNoncopyable.h"
     23 #include "GrStringBuilder.h"
     24 #include "GrRandom.h"
     25 
     26 #define SKIP_CACHE_CHECK    true
     27 #define GR_UINT32_MAX   static_cast<uint32_t>(-1)
     28 
     29 #include "GrTHashCache.h"
     30 
     31 class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable {
     32 private:
     33     class Entry;
     34 
     35 #if GR_DEBUG
     36     typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug
     37 #else
     38     typedef GrBinHashKey<Entry, 64> ProgramHashKey;
     39 #endif
     40 
     41     class Entry : public ::GrNoncopyable {
     42     public:
     43         Entry() {}
     44         void copyAndTakeOwnership(Entry& entry) {
     45             fProgramData.copyAndTakeOwnership(entry.fProgramData);
     46             fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer
     47             fLRUStamp = entry.fLRUStamp;
     48         }
     49 
     50     public:
     51         int compare(const ProgramHashKey& key) const { return fKey.compare(key); }
     52 
     53     public:
     54         GrGLProgram::CachedData fProgramData;
     55         ProgramHashKey          fKey;
     56         unsigned int            fLRUStamp;
     57     };
     58 
     59     GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
     60 
     61     // We may have kMaxEntries+1 shaders in the GL context because
     62     // we create a new shader before evicting from the cache.
     63     enum {
     64         kMaxEntries = 32
     65     };
     66     Entry        fEntries[kMaxEntries];
     67     int          fCount;
     68     unsigned int fCurrLRUStamp;
     69 
     70 public:
     71     ProgramCache()
     72         : fCount(0)
     73         , fCurrLRUStamp(0) {
     74     }
     75 
     76     ~ProgramCache() {
     77         for (int i = 0; i < fCount; ++i) {
     78             GrGpuGLShaders::DeleteProgram(&fEntries[i].fProgramData);
     79         }
     80     }
     81 
     82     void abandon() {
     83         fCount = 0;
     84     }
     85 
     86     void invalidateViewMatrices() {
     87         for (int i = 0; i < fCount; ++i) {
     88             // set to illegal matrix
     89             fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix();
     90         }
     91     }
     92 
     93     GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) {
     94         Entry newEntry;
     95         while (newEntry.fKey.doPass()) {
     96             desc.buildKey(newEntry.fKey);
     97         }
     98         Entry* entry = fHashCache.find(newEntry.fKey);
     99         if (NULL == entry) {
    100             if (!desc.genProgram(&newEntry.fProgramData)) {
    101                 return NULL;
    102             }
    103             if (fCount < kMaxEntries) {
    104                 entry = fEntries + fCount;
    105                 ++fCount;
    106             } else {
    107                 GrAssert(kMaxEntries == fCount);
    108                 entry = fEntries;
    109                 for (int i = 1; i < kMaxEntries; ++i) {
    110                     if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
    111                         entry = fEntries + i;
    112                     }
    113                 }
    114                 fHashCache.remove(entry->fKey, entry);
    115                 GrGpuGLShaders::DeleteProgram(&entry->fProgramData);
    116             }
    117             entry->copyAndTakeOwnership(newEntry);
    118             fHashCache.insert(entry->fKey, entry);
    119         }
    120 
    121         entry->fLRUStamp = fCurrLRUStamp;
    122         if (GR_UINT32_MAX == fCurrLRUStamp) {
    123             // wrap around! just trash our LRU, one time hit.
    124             for (int i = 0; i < fCount; ++i) {
    125                 fEntries[i].fLRUStamp = 0;
    126             }
    127         }
    128         ++fCurrLRUStamp;
    129         return &entry->fProgramData;
    130     }
    131 };
    132 
    133 void GrGpuGLShaders::abandonResources(){
    134     INHERITED::abandonResources();
    135     fProgramCache->abandon();
    136 }
    137 
    138 void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) {
    139     GR_GL(DeleteShader(programData->fVShaderID));
    140     GR_GL(DeleteShader(programData->fFShaderID));
    141     GR_GL(DeleteProgram(programData->fProgramID));
    142     GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));)
    143 }
    144 
    145 void GrGpuGLShaders::ProgramUnitTest() {
    146 
    147     static const int STAGE_OPTS[] = {
    148         0,
    149         GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit,
    150         GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping
    151     };
    152     static const GrGLProgram::ProgramDesc::StageDesc::Modulation STAGE_MODULATES[] = {
    153         GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation,
    154         GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation
    155     };
    156     static const GrGLProgram::ProgramDesc::StageDesc::CoordMapping STAGE_COORD_MAPPINGS[] = {
    157         GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping,
    158         GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping,
    159         GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping,
    160         GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping
    161     };
    162     static const GrGLProgram::ProgramDesc::StageDesc::FetchMode FETCH_MODES[] = {
    163         GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode,
    164         GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode,
    165     };
    166     GrGLProgram program;
    167     GrGLProgram::ProgramDesc& pdesc = program.fProgramDesc;
    168 
    169     static const int NUM_TESTS = 512;
    170 
    171     // GrRandoms nextU() values have patterns in the low bits
    172     // So using nextU() % array_count might never take some values.
    173     GrRandom random;
    174     for (int t = 0; t < NUM_TESTS; ++t) {
    175 
    176 #if 0
    177         GrPrintf("\nTest Program %d\n-------------\n", t);
    178         static const int stop = -1;
    179         if (t == stop) {
    180             int breakpointhere = 9;
    181         }
    182 #endif
    183 
    184         pdesc.fVertexLayout = 0;
    185         pdesc.fEmitsPointSize = random.nextF() > .5f;
    186         float colorType = random.nextF();
    187         if (colorType < 1.f / 3.f) {
    188             pdesc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
    189         } else if (colorType < 2.f / 3.f) {
    190             pdesc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
    191         } else {
    192             pdesc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
    193         }
    194 
    195         int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt));
    196         pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx;
    197 
    198         idx = (int)(random.nextF() * (kNumStages+1));
    199         pdesc.fFirstCoverageStage = idx;
    200 
    201         pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1));
    202 
    203         if (fDualSourceBlendingSupport) {
    204             pdesc.fDualSrcOutput =
    205                (GrGLProgram::ProgramDesc::DualSrcOutput)
    206                (int)(random.nextF() * GrGLProgram::ProgramDesc::kDualSrcOutputCnt);
    207         } else {
    208             pdesc.fDualSrcOutput =
    209                                 GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
    210         }
    211 
    212         for (int s = 0; s < kNumStages; ++s) {
    213             // enable the stage?
    214             if (random.nextF() > .5f) {
    215                 // use separate tex coords?
    216                 if (random.nextF() > .5f) {
    217                     int t = (int)(random.nextF() * kMaxTexCoords);
    218                     pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
    219                 } else {
    220                     pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
    221                 }
    222             }
    223             // use text-formatted verts?
    224             if (random.nextF() > .5f) {
    225                 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
    226             }
    227             idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
    228             pdesc.fStages[s].fOptFlags = STAGE_OPTS[idx];
    229             idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
    230             pdesc.fStages[s].fModulation = STAGE_MODULATES[idx];
    231             idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
    232             pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[idx];
    233             idx = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES));
    234             pdesc.fStages[s].fFetchMode = FETCH_MODES[idx];
    235             pdesc.fStages[s].setEnabled(VertexUsesStage(s, pdesc.fVertexLayout));
    236         }
    237         GrGLProgram::CachedData cachedData;
    238         program.genProgram(&cachedData);
    239         DeleteProgram(&cachedData);
    240         bool again = false;
    241         if (again) {
    242             program.genProgram(&cachedData);
    243             DeleteProgram(&cachedData);
    244         }
    245     }
    246 }
    247 
    248 GrGpuGLShaders::GrGpuGLShaders() {
    249 
    250     resetContext();
    251     int major, minor;
    252     gl_version(&major, &minor);
    253 
    254     f4X4DownsampleFilterSupport = true;
    255     if (GR_GL_SUPPORT_DESKTOP) {
    256         fDualSourceBlendingSupport =
    257             major > 3 ||(3 == major && 3 <= minor) ||
    258             has_gl_extension("GL_ARB_blend_func_extended");
    259     } else {
    260         fDualSourceBlendingSupport = false;
    261     }
    262 
    263     fProgramData = NULL;
    264     fProgramCache = new ProgramCache();
    265 
    266 #if 0
    267     ProgramUnitTest();
    268 #endif
    269 }
    270 
    271 GrGpuGLShaders::~GrGpuGLShaders() {
    272     delete fProgramCache;
    273 }
    274 
    275 const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
    276     GrAssert(fProgramData);
    277 
    278     if (GrGLProgram::kSetAsAttribute ==
    279         fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
    280         return fHWDrawState.fSamplerStates[stage].getMatrix();
    281     } else {
    282         return fProgramData->fTextureMatrices[stage];
    283     }
    284 }
    285 
    286 void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
    287     GrAssert(fProgramData);
    288     if (GrGLProgram::kSetAsAttribute ==
    289         fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
    290         fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
    291     } else {
    292         fProgramData->fTextureMatrices[stage] = matrix;
    293     }
    294 }
    295 
    296 void GrGpuGLShaders::resetContext() {
    297     INHERITED::resetContext();
    298 
    299     fHWGeometryState.fVertexLayout = 0;
    300     fHWGeometryState.fVertexOffset = ~0;
    301     GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
    302     for (int t = 0; t < kMaxTexCoords; ++t) {
    303         GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
    304     }
    305     GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
    306 
    307     fHWProgramID = 0;
    308 }
    309 
    310 void GrGpuGLShaders::flushViewMatrix() {
    311     GrAssert(NULL != fCurrDrawState.fRenderTarget);
    312     GrMatrix m;
    313     m.setAll(
    314         GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
    315         0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
    316         0, 0, GrMatrix::I()[8]);
    317     m.setConcat(m, fCurrDrawState.fViewMatrix);
    318 
    319     // ES doesn't allow you to pass true to the transpose param,
    320     // so do our own transpose
    321     GrGLfloat mt[]  = {
    322         GrScalarToFloat(m[GrMatrix::kMScaleX]),
    323         GrScalarToFloat(m[GrMatrix::kMSkewY]),
    324         GrScalarToFloat(m[GrMatrix::kMPersp0]),
    325         GrScalarToFloat(m[GrMatrix::kMSkewX]),
    326         GrScalarToFloat(m[GrMatrix::kMScaleY]),
    327         GrScalarToFloat(m[GrMatrix::kMPersp1]),
    328         GrScalarToFloat(m[GrMatrix::kMTransX]),
    329         GrScalarToFloat(m[GrMatrix::kMTransY]),
    330         GrScalarToFloat(m[GrMatrix::kMPersp2])
    331     };
    332 
    333     if (GrGLProgram::kSetAsAttribute ==
    334         fProgramData->fUniLocations.fViewMatrixUni) {
    335         int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
    336         GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
    337         GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
    338         GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
    339     } else {
    340         GrAssert(GrGLProgram::kUnusedUniform !=
    341                  fProgramData->fUniLocations.fViewMatrixUni);
    342         GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
    343                                1, false, mt));
    344     }
    345 }
    346 
    347 void GrGpuGLShaders::flushTextureDomain(int s) {
    348     const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
    349     if (GrGLProgram::kUnusedUniform != uni) {
    350         const GrRect &texDom =
    351             fCurrDrawState.fSamplerStates[s].getTextureDomain();
    352 
    353         if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
    354             fProgramData->fTextureDomain[s] != texDom) {
    355 
    356             fProgramData->fTextureDomain[s] = texDom;
    357 
    358             float values[4] = {
    359                 GrScalarToFloat(texDom.left()),
    360                 GrScalarToFloat(texDom.top()),
    361                 GrScalarToFloat(texDom.right()),
    362                 GrScalarToFloat(texDom.bottom())
    363             };
    364 
    365             GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
    366             GrGLTexture::Orientation orientation = texture->orientation();
    367 
    368             // vertical flip if necessary
    369             if (GrGLTexture::kBottomUp_Orientation == orientation) {
    370                 values[1] = 1.0f - values[1];
    371                 values[3] = 1.0f - values[3];
    372                 // The top and bottom were just flipped, so correct the ordering
    373                 // of elements so that values = (l, t, r, b).
    374                 SkTSwap(values[1], values[3]);
    375             }
    376 
    377             values[0] *= SkScalarToFloat(texture->contentScaleX());
    378             values[2] *= SkScalarToFloat(texture->contentScaleX());
    379             values[1] *= SkScalarToFloat(texture->contentScaleY());
    380             values[3] *= SkScalarToFloat(texture->contentScaleY());
    381 
    382             GR_GL(Uniform4fv(uni, 1, values));
    383         }
    384     }
    385 }
    386 
    387 void GrGpuGLShaders::flushTextureMatrix(int s) {
    388     const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
    389     GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
    390     if (NULL != texture) {
    391         if (GrGLProgram::kUnusedUniform != uni &&
    392             (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
    393             getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
    394 
    395             GrAssert(NULL != fCurrDrawState.fTextures[s]);
    396 
    397             GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
    398 
    399             GrMatrix m = getSamplerMatrix(s);
    400             GrSamplerState::SampleMode mode =
    401                 fCurrDrawState.fSamplerStates[s].getSampleMode();
    402             AdjustTextureMatrix(texture, mode, &m);
    403 
    404             // ES doesn't allow you to pass true to the transpose param,
    405             // so do our own transpose
    406             GrGLfloat mt[]  = {
    407                 GrScalarToFloat(m[GrMatrix::kMScaleX]),
    408                 GrScalarToFloat(m[GrMatrix::kMSkewY]),
    409                 GrScalarToFloat(m[GrMatrix::kMPersp0]),
    410                 GrScalarToFloat(m[GrMatrix::kMSkewX]),
    411                 GrScalarToFloat(m[GrMatrix::kMScaleY]),
    412                 GrScalarToFloat(m[GrMatrix::kMPersp1]),
    413                 GrScalarToFloat(m[GrMatrix::kMTransX]),
    414                 GrScalarToFloat(m[GrMatrix::kMTransY]),
    415                 GrScalarToFloat(m[GrMatrix::kMPersp2])
    416             };
    417 
    418             if (GrGLProgram::kSetAsAttribute ==
    419                 fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
    420                 int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s);
    421                 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
    422                 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
    423                 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
    424             } else {
    425                 GR_GL(UniformMatrix3fv(uni, 1, false, mt));
    426             }
    427             recordHWSamplerMatrix(s, getSamplerMatrix(s));
    428         }
    429     }
    430 }
    431 
    432 void GrGpuGLShaders::flushRadial2(int s) {
    433 
    434     const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
    435     const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
    436     if (GrGLProgram::kUnusedUniform != uni &&
    437         (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
    438          fProgramData->fRadial2Radius0[s]  != sampler.getRadial2Radius0()  ||
    439          fProgramData->fRadial2PosRoot[s]  != sampler.isRadial2PosRoot())) {
    440 
    441         GrScalar centerX1 = sampler.getRadial2CenterX1();
    442         GrScalar radius0 = sampler.getRadial2Radius0();
    443 
    444         GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
    445 
    446         float values[6] = {
    447             GrScalarToFloat(a),
    448             1 / (2.f * values[0]),
    449             GrScalarToFloat(centerX1),
    450             GrScalarToFloat(radius0),
    451             GrScalarToFloat(GrMul(radius0, radius0)),
    452             sampler.isRadial2PosRoot() ? 1.f : -1.f
    453         };
    454         GR_GL(Uniform1fv(uni, 6, values));
    455         fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
    456         fProgramData->fRadial2Radius0[s]  = sampler.getRadial2Radius0();
    457         fProgramData->fRadial2PosRoot[s]  = sampler.isRadial2PosRoot();
    458     }
    459 }
    460 
    461 void GrGpuGLShaders::flushTexelSize(int s) {
    462     const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
    463     if (GrGLProgram::kUnusedUniform != uni) {
    464         GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
    465         if (texture->allocWidth() != fProgramData->fTextureWidth[s] ||
    466             texture->allocHeight() != fProgramData->fTextureWidth[s]) {
    467 
    468             float texelSize[] = {1.f / texture->allocWidth(),
    469                                  1.f / texture->allocHeight()};
    470             GR_GL(Uniform2fv(uni, 1, texelSize));
    471         }
    472     }
    473 }
    474 
    475 void GrGpuGLShaders::flushEdgeAAData() {
    476     const int& uni = fProgramData->fUniLocations.fEdgesUni;
    477     if (GrGLProgram::kUnusedUniform != uni) {
    478         int count = fCurrDrawState.fEdgeAANumEdges;
    479         Edge edges[kMaxEdges];
    480         // Flip the edges in Y
    481         float height = fCurrDrawState.fRenderTarget->height();
    482         for (int i = 0; i < count; ++i) {
    483             edges[i] = fCurrDrawState.fEdgeAAEdges[i];
    484             float b = edges[i].fY;
    485             edges[i].fY = -b;
    486             edges[i].fZ += b * height;
    487         }
    488         GR_GL(Uniform3fv(uni, count, &edges[0].fX));
    489     }
    490 }
    491 
    492 static const float ONE_OVER_255 = 1.f / 255.f;
    493 
    494 #define GR_COLOR_TO_VEC4(color) {\
    495     GrColorUnpackR(color) * ONE_OVER_255,\
    496     GrColorUnpackG(color) * ONE_OVER_255,\
    497     GrColorUnpackB(color) * ONE_OVER_255,\
    498     GrColorUnpackA(color) * ONE_OVER_255 \
    499 }
    500 
    501 void GrGpuGLShaders::flushColor() {
    502     const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc();
    503     if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
    504         // color will be specified per-vertex as an attribute
    505         // invalidate the const vertex attrib color
    506         fHWDrawState.fColor = GrColor_ILLEGAL;
    507     } else {
    508         switch (desc.fColorType) {
    509             case GrGLProgram::ProgramDesc::kAttribute_ColorType:
    510                 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
    511                     // OpenGL ES only supports the float varities of glVertexAttrib
    512                     float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
    513                     GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
    514                     fHWDrawState.fColor = fCurrDrawState.fColor;
    515                 }
    516                 break;
    517             case GrGLProgram::ProgramDesc::kUniform_ColorType:
    518                 if (fProgramData->fColor != fCurrDrawState.fColor) {
    519                     // OpenGL ES only supports the float varities of glVertexAttrib
    520                     float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
    521                     GrAssert(GrGLProgram::kUnusedUniform !=
    522                              fProgramData->fUniLocations.fColorUni);
    523                     GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
    524                     fProgramData->fColor = fCurrDrawState.fColor;
    525                 }
    526                 break;
    527             case GrGLProgram::ProgramDesc::kNone_ColorType:
    528                 GrAssert(0xffffffff == fCurrDrawState.fColor);
    529                 break;
    530             default:
    531                 GrCrash("Unknown color type.");
    532         }
    533     }
    534     if (fProgramData->fUniLocations.fColorFilterUni
    535                 != GrGLProgram::kUnusedUniform
    536             && fProgramData->fColorFilterColor
    537                 != fCurrDrawState.fColorFilterColor) {
    538         float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
    539         GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
    540         fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
    541     }
    542 }
    543 
    544 
    545 bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
    546     if (!flushGLStateCommon(type)) {
    547         return false;
    548     }
    549 
    550     if (fDirtyFlags.fRenderTargetChanged) {
    551         // our coords are in pixel space and the GL matrices map to NDC
    552         // so if the viewport changed, our matrix is now wrong.
    553         fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
    554         // we assume all shader matrices may be wrong after viewport changes
    555         fProgramCache->invalidateViewMatrices();
    556     }
    557 
    558     buildProgram(type);
    559     fProgramData = fProgramCache->getProgramData(fCurrentProgram);
    560     if (NULL == fProgramData) {
    561         GrAssert(!"Failed to create program!");
    562         return false;
    563     }
    564 
    565     if (fHWProgramID != fProgramData->fProgramID) {
    566         GR_GL(UseProgram(fProgramData->fProgramID));
    567         fHWProgramID = fProgramData->fProgramID;
    568     }
    569     GrBlendCoeff srcCoeff = fCurrDrawState.fSrcBlend;
    570     GrBlendCoeff dstCoeff = fCurrDrawState.fDstBlend;
    571 
    572     fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
    573     this->flushBlend(type, srcCoeff, dstCoeff);
    574 
    575     this->flushColor();
    576 
    577     GrMatrix* currViewMatrix;
    578     if (GrGLProgram::kSetAsAttribute ==
    579         fProgramData->fUniLocations.fViewMatrixUni) {
    580         currViewMatrix = &fHWDrawState.fViewMatrix;
    581     } else {
    582         currViewMatrix = &fProgramData->fViewMatrix;
    583     }
    584 
    585     if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
    586         flushViewMatrix();
    587         *currViewMatrix = fCurrDrawState.fViewMatrix;
    588     }
    589 
    590     for (int s = 0; s < kNumStages; ++s) {
    591         this->flushTextureMatrix(s);
    592 
    593         this->flushRadial2(s);
    594 
    595         this->flushTexelSize(s);
    596 
    597         this->flushTextureDomain(s);
    598     }
    599     this->flushEdgeAAData();
    600     resetDirtyFlags();
    601     return true;
    602 }
    603 
    604 void GrGpuGLShaders::postDraw() {
    605 }
    606 
    607 void GrGpuGLShaders::setupGeometry(int* startVertex,
    608                                     int* startIndex,
    609                                     int vertexCount,
    610                                     int indexCount) {
    611 
    612     int newColorOffset;
    613     int newTexCoordOffsets[kMaxTexCoords];
    614 
    615     GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
    616                                                   newTexCoordOffsets,
    617                                                   &newColorOffset);
    618     int oldColorOffset;
    619     int oldTexCoordOffsets[kMaxTexCoords];
    620     GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
    621                                                   oldTexCoordOffsets,
    622                                                   &oldColorOffset);
    623     bool indexed = NULL != startIndex;
    624 
    625     int extraVertexOffset;
    626     int extraIndexOffset;
    627     setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
    628 
    629     GrGLenum scalarType;
    630     bool texCoordNorm;
    631     if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
    632         scalarType = GrGLTextType;
    633         texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
    634     } else {
    635         scalarType = GrGLType;
    636         texCoordNorm = false;
    637     }
    638 
    639     size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
    640     *startVertex = 0;
    641     if (indexed) {
    642         *startIndex += extraIndexOffset;
    643     }
    644 
    645     // all the Pointers must be set if any of these are true
    646     bool allOffsetsChange =  fHWGeometryState.fArrayPtrsDirty ||
    647                              vertexOffset != fHWGeometryState.fVertexOffset ||
    648                              newStride != oldStride;
    649 
    650     // position and tex coord offsets change if above conditions are true
    651     // or the type/normalization changed based on text vs nontext type coords.
    652     bool posAndTexChange = allOffsetsChange ||
    653                            (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
    654                                 (kTextFormat_VertexLayoutBit &
    655                                   (fHWGeometryState.fVertexLayout ^
    656                                    fGeometrySrc.fVertexLayout)));
    657 
    658     if (posAndTexChange) {
    659         int idx = GrGLProgram::PositionAttributeIdx();
    660         GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
    661                                   (GrGLvoid*)vertexOffset));
    662         fHWGeometryState.fVertexOffset = vertexOffset;
    663     }
    664 
    665     for (int t = 0; t < kMaxTexCoords; ++t) {
    666         if (newTexCoordOffsets[t] > 0) {
    667             GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
    668             int idx = GrGLProgram::TexCoordAttributeIdx(t);
    669             if (oldTexCoordOffsets[t] <= 0) {
    670                 GR_GL(EnableVertexAttribArray(idx));
    671                 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
    672                                           newStride, texCoordOffset));
    673             } else if (posAndTexChange ||
    674                        newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
    675                 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
    676                                           newStride, texCoordOffset));
    677             }
    678         } else if (oldTexCoordOffsets[t] > 0) {
    679             GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
    680         }
    681     }
    682 
    683     if (newColorOffset > 0) {
    684         GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
    685         int idx = GrGLProgram::ColorAttributeIdx();
    686         if (oldColorOffset <= 0) {
    687             GR_GL(EnableVertexAttribArray(idx));
    688             GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    689                                       true, newStride, colorOffset));
    690         } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
    691             GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    692                                       true, newStride, colorOffset));
    693         }
    694     } else if (oldColorOffset > 0) {
    695         GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
    696     }
    697 
    698     fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
    699     fHWGeometryState.fArrayPtrsDirty = false;
    700 }
    701 
    702 void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
    703     GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc;
    704 
    705     // Must initialize all fields or cache will have false negatives!
    706     desc.fVertexLayout = fGeometrySrc.fVertexLayout;
    707 
    708     desc.fEmitsPointSize = kPoints_PrimitiveType == type;
    709 
    710     bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
    711     // fColorType records how colors are specified for the program. Strip
    712     // the bit from the layout to avoid false negatives when searching for an
    713     // existing program in the cache.
    714     desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
    715 
    716     desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
    717 
    718 #if GR_AGGRESSIVE_SHADER_OPTS
    719     if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
    720         desc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
    721     } else
    722 #endif
    723 #if GR_GL_NO_CONSTANT_ATTRIBUTES
    724     if (!requiresAttributeColors) {
    725         desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
    726     } else
    727 #endif
    728     {
    729         if (requiresAttributeColors) {} // suppress unused var warning
    730         desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
    731     }
    732 
    733     desc.fEdgeAANumEdges = fCurrDrawState.fEdgeAANumEdges;
    734 
    735     int lastEnabledStage = -1;
    736 
    737     for (int s = 0; s < kNumStages; ++s) {
    738         GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
    739 
    740         stage.fOptFlags = 0;
    741         stage.setEnabled(this->isStageEnabled(s));
    742 
    743         if (stage.isEnabled()) {
    744             lastEnabledStage = s;
    745             GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
    746             GrAssert(NULL != texture);
    747             // we matrix to invert when orientation is TopDown, so make sure
    748             // we aren't in that case before flagging as identity.
    749             if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
    750                 stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit;
    751             } else if (!getSamplerMatrix(s).hasPerspective()) {
    752                 stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit;
    753             }
    754             switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
    755                 case GrSamplerState::kNormal_SampleMode:
    756                     stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping;
    757                     break;
    758                 case GrSamplerState::kRadial_SampleMode:
    759                     stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping;
    760                     break;
    761                 case GrSamplerState::kRadial2_SampleMode:
    762                     stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping;
    763                     break;
    764                 case GrSamplerState::kSweep_SampleMode:
    765                     stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping;
    766                     break;
    767                 default:
    768                     GrCrash("Unexpected sample mode!");
    769                     break;
    770             }
    771 
    772             switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
    773                 // these both can use a regular texture2D()
    774                 case GrSamplerState::kNearest_Filter:
    775                 case GrSamplerState::kBilinear_Filter:
    776                     stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode;
    777                     break;
    778                 // performs 4 texture2D()s
    779                 case GrSamplerState::k4x4Downsample_Filter:
    780                     stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode;
    781                     break;
    782                 default:
    783                     GrCrash("Unexpected filter!");
    784                     break;
    785             }
    786 
    787             if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
    788                 GrAssert(GrSamplerState::kClamp_WrapMode ==
    789                     fCurrDrawState.fSamplerStates[s].getWrapX() &&
    790                     GrSamplerState::kClamp_WrapMode ==
    791                     fCurrDrawState.fSamplerStates[s].getWrapY());
    792                 stage.fOptFlags |=
    793                     GrGLProgram::ProgramDesc::StageDesc::
    794                     kCustomTextureDomain_OptFlagBit;
    795             }
    796 
    797             if (GrPixelConfigIsAlphaOnly(texture->config())) {
    798                 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation;
    799             } else {
    800                 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation;
    801             }
    802         } else {
    803             stage.fOptFlags     = 0;
    804             stage.fCoordMapping = (GrGLProgram::ProgramDesc::StageDesc::CoordMapping)0;
    805             stage.fModulation   = (GrGLProgram::ProgramDesc::StageDesc::Modulation)0;
    806         }
    807     }
    808 
    809     desc.fDualSrcOutput = GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
    810     // use canonical value when coverage/color distinction won't affect
    811     // generated code to prevent duplicate programs.
    812     desc.fFirstCoverageStage = kNumStages;
    813     if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
    814         // color filter is applied between color/coverage computation
    815         if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
    816             desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
    817         }
    818 
    819         // We could consider cases where the final color is solid (0xff alpha)
    820         // and the dst coeff can correctly be set to a non-dualsrc gl value.
    821         // (e.g. solid draw, and dst coeff is kZero. It's correct to make
    822         // the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
    823         // kOne).
    824         if (fDualSourceBlendingSupport) {
    825             if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
    826                 // write the coverage value to second color
    827                 desc.fDualSrcOutput =
    828                                 GrGLProgram::ProgramDesc::kCoverage_DualSrcOutput;
    829                 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
    830             } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
    831                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
    832                 // cover
    833                 desc.fDualSrcOutput =
    834                             GrGLProgram::ProgramDesc::kCoverageISA_DualSrcOutput;
    835                 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
    836             } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
    837                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
    838                 // cover
    839                 desc.fDualSrcOutput =
    840                         GrGLProgram::ProgramDesc::kCoverageISC_DualSrcOutput;
    841                 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
    842             }
    843         }
    844     }
    845 }
    846