Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrGpuGL.h"
      9 
     10 #include "GrEffect.h"
     11 #include "GrGLEffect.h"
     12 #include "GrGpuVertex.h"
     13 
     14 typedef GrGLUniformManager::UniformHandle UniformHandle;
     15 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
     16 
     17 #define SKIP_CACHE_CHECK    true
     18 #define GR_UINT32_MAX   static_cast<uint32_t>(-1)
     19 
     20 GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
     21     : fCount(0)
     22     , fCurrLRUStamp(0)
     23     , fGL(gl) {
     24 }
     25 
     26 void GrGpuGL::ProgramCache::abandon() {
     27     for (int i = 0; i < fCount; ++i) {
     28         GrAssert(NULL != fEntries[i].fProgram.get());
     29         fEntries[i].fProgram->abandon();
     30         fEntries[i].fProgram.reset(NULL);
     31     }
     32     fCount = 0;
     33 }
     34 
     35 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc,
     36                                                const GrEffectStage* stages[]) {
     37     Entry newEntry;
     38     newEntry.fKey.setKeyData(desc.asKey());
     39 
     40     Entry* entry = fHashCache.find(newEntry.fKey);
     41     if (NULL == entry) {
     42         newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages));
     43         if (NULL == newEntry.fProgram.get()) {
     44             return NULL;
     45         }
     46         if (fCount < kMaxEntries) {
     47             entry = fEntries + fCount;
     48             ++fCount;
     49         } else {
     50             GrAssert(kMaxEntries == fCount);
     51             entry = fEntries;
     52             for (int i = 1; i < kMaxEntries; ++i) {
     53                 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
     54                     entry = fEntries + i;
     55                 }
     56             }
     57             fHashCache.remove(entry->fKey, entry);
     58         }
     59         *entry = newEntry;
     60         fHashCache.insert(entry->fKey, entry);
     61     }
     62 
     63     entry->fLRUStamp = fCurrLRUStamp;
     64     if (GR_UINT32_MAX == fCurrLRUStamp) {
     65         // wrap around! just trash our LRU, one time hit.
     66         for (int i = 0; i < fCount; ++i) {
     67             fEntries[i].fLRUStamp = 0;
     68         }
     69     }
     70     ++fCurrLRUStamp;
     71     return entry->fProgram;
     72 }
     73 
     74 ////////////////////////////////////////////////////////////////////////////////
     75 
     76 void GrGpuGL::abandonResources(){
     77     INHERITED::abandonResources();
     78     fProgramCache->abandon();
     79     fHWProgramID = 0;
     80 }
     81 
     82 ////////////////////////////////////////////////////////////////////////////////
     83 
     84 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
     85 
     86 void GrGpuGL::flushViewMatrix(DrawType type) {
     87     const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(this->getDrawState().getRenderTarget());
     88     SkISize viewportSize;
     89     const GrGLIRect& viewport = rt->getViewport();
     90     viewportSize.set(viewport.fWidth, viewport.fHeight);
     91 
     92     const SkMatrix& vm = this->getDrawState().getViewMatrix();
     93 
     94     if (kStencilPath_DrawType == type) {
     95         if (fHWPathMatrixState.fViewMatrix != vm ||
     96             fHWPathMatrixState.fRTSize != viewportSize) {
     97             // rescale the coords from skia's "device" coords to GL's normalized coords,
     98             // and perform a y-flip.
     99             SkMatrix m;
    100             m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
    101             m.postTranslate(-SK_Scalar1, SK_Scalar1);
    102             m.preConcat(vm);
    103 
    104             // GL wants a column-major 4x4.
    105             GrGLfloat mv[]  = {
    106                 // col 0
    107                 SkScalarToFloat(m[SkMatrix::kMScaleX]),
    108                 SkScalarToFloat(m[SkMatrix::kMSkewY]),
    109                 0,
    110                 SkScalarToFloat(m[SkMatrix::kMPersp0]),
    111 
    112                 // col 1
    113                 SkScalarToFloat(m[SkMatrix::kMSkewX]),
    114                 SkScalarToFloat(m[SkMatrix::kMScaleY]),
    115                 0,
    116                 SkScalarToFloat(m[SkMatrix::kMPersp1]),
    117 
    118                 // col 2
    119                 0, 0, 0, 0,
    120 
    121                 // col3
    122                 SkScalarToFloat(m[SkMatrix::kMTransX]),
    123                 SkScalarToFloat(m[SkMatrix::kMTransY]),
    124                 0.0f,
    125                 SkScalarToFloat(m[SkMatrix::kMPersp2])
    126             };
    127             GL_CALL(MatrixMode(GR_GL_PROJECTION));
    128             GL_CALL(LoadMatrixf(mv));
    129             fHWPathMatrixState.fViewMatrix = vm;
    130             fHWPathMatrixState.fRTSize = viewportSize;
    131         }
    132     } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
    133                fCurrentProgram->fViewportSize != viewportSize) {
    134         SkMatrix m;
    135         m.setAll(
    136             SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1,
    137             0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1,
    138             0, 0, SkMatrix::I()[8]);
    139         m.setConcat(m, vm);
    140 
    141         // ES doesn't allow you to pass true to the transpose param,
    142         // so do our own transpose
    143         GrGLfloat mt[]  = {
    144             SkScalarToFloat(m[SkMatrix::kMScaleX]),
    145             SkScalarToFloat(m[SkMatrix::kMSkewY]),
    146             SkScalarToFloat(m[SkMatrix::kMPersp0]),
    147             SkScalarToFloat(m[SkMatrix::kMSkewX]),
    148             SkScalarToFloat(m[SkMatrix::kMScaleY]),
    149             SkScalarToFloat(m[SkMatrix::kMPersp1]),
    150             SkScalarToFloat(m[SkMatrix::kMTransX]),
    151             SkScalarToFloat(m[SkMatrix::kMTransY]),
    152             SkScalarToFloat(m[SkMatrix::kMPersp2])
    153         };
    154         fCurrentProgram->fUniformManager.setMatrix3f(
    155                                             fCurrentProgram->fUniformHandles.fViewMatrixUni,
    156                                             mt);
    157         fCurrentProgram->fViewMatrix = vm;
    158         fCurrentProgram->fViewportSize = viewportSize;
    159     }
    160 }
    161 
    162 ///////////////////////////////////////////////////////////////////////////////
    163 
    164 void GrGpuGL::flushColor(GrColor color) {
    165     const ProgramDesc& desc = fCurrentProgram->getDesc();
    166     const GrDrawState& drawState = this->getDrawState();
    167 
    168     if (this->getVertexLayout() & GrDrawState::kColor_VertexLayoutBit) {
    169         // color will be specified per-vertex as an attribute
    170         // invalidate the const vertex attrib color
    171         fHWConstAttribColor = GrColor_ILLEGAL;
    172     } else {
    173         switch (desc.fColorInput) {
    174             case ProgramDesc::kAttribute_ColorInput:
    175                 if (fHWConstAttribColor != color) {
    176                     // OpenGL ES only supports the float varieties of glVertexAttrib
    177                     GrGLfloat c[4];
    178                     GrColorToRGBAFloat(color, c);
    179                     GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
    180                     fHWConstAttribColor = color;
    181                 }
    182                 break;
    183             case ProgramDesc::kUniform_ColorInput:
    184                 if (fCurrentProgram->fColor != color) {
    185                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    186                     GrGLfloat c[4];
    187                     GrColorToRGBAFloat(color, c);
    188                     GrAssert(kInvalidUniformHandle !=  fCurrentProgram->fUniformHandles.fColorUni);
    189                     fCurrentProgram->fUniformManager.set4fv(
    190                                                         fCurrentProgram->fUniformHandles.fColorUni,
    191                                                         0, 1, c);
    192                     fCurrentProgram->fColor = color;
    193                 }
    194                 break;
    195             case ProgramDesc::kSolidWhite_ColorInput:
    196             case ProgramDesc::kTransBlack_ColorInput:
    197                 break;
    198             default:
    199                 GrCrash("Unknown color type.");
    200         }
    201     }
    202     UniformHandle filterColorUni = fCurrentProgram->fUniformHandles.fColorFilterUni;
    203     if (kInvalidUniformHandle != filterColorUni &&
    204         fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) {
    205         GrGLfloat c[4];
    206         GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
    207         fCurrentProgram->fUniformManager.set4fv(filterColorUni, 0, 1, c);
    208         fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor();
    209     }
    210 }
    211 
    212 void GrGpuGL::flushCoverage(GrColor coverage) {
    213     const ProgramDesc& desc = fCurrentProgram->getDesc();
    214     // const GrDrawState& drawState = this->getDrawState();
    215 
    216 
    217     if (this->getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit) {
    218         // coverage will be specified per-vertex as an attribute
    219         // invalidate the const vertex attrib coverage
    220         fHWConstAttribCoverage = GrColor_ILLEGAL;
    221     } else {
    222         switch (desc.fCoverageInput) {
    223             case ProgramDesc::kAttribute_ColorInput:
    224                 if (fHWConstAttribCoverage != coverage) {
    225                     // OpenGL ES only supports the float varieties of
    226                     // glVertexAttrib
    227                     GrGLfloat c[4];
    228                     GrColorToRGBAFloat(coverage, c);
    229                     GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(),
    230                                             c));
    231                     fHWConstAttribCoverage = coverage;
    232                 }
    233                 break;
    234             case ProgramDesc::kUniform_ColorInput:
    235                 if (fCurrentProgram->fCoverage != coverage) {
    236                     // OpenGL ES doesn't support unsigned byte varieties of
    237                     // glUniform
    238                     GrGLfloat c[4];
    239                     GrColorToRGBAFloat(coverage, c);
    240                     GrAssert(kInvalidUniformHandle !=
    241                              fCurrentProgram->fUniformHandles.fCoverageUni);
    242                     fCurrentProgram->fUniformManager.set4fv(
    243                                                     fCurrentProgram->fUniformHandles.fCoverageUni,
    244                                                     0, 1, c);
    245                     fCurrentProgram->fCoverage = coverage;
    246                 }
    247                 break;
    248             case ProgramDesc::kSolidWhite_ColorInput:
    249             case ProgramDesc::kTransBlack_ColorInput:
    250                 break;
    251             default:
    252                 GrCrash("Unknown coverage type.");
    253         }
    254     }
    255 }
    256 
    257 bool GrGpuGL::flushGraphicsState(DrawType type) {
    258     const GrDrawState& drawState = this->getDrawState();
    259 
    260     // GrGpu::setupClipAndFlushState should have already checked this
    261     // and bailed if not true.
    262     GrAssert(NULL != drawState.getRenderTarget());
    263 
    264     if (kStencilPath_DrawType != type) {
    265         this->flushMiscFixedFunctionState();
    266 
    267         GrBlendCoeff srcCoeff;
    268         GrBlendCoeff dstCoeff;
    269         BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
    270         if (kSkipDraw_BlendOptFlag & blendOpts) {
    271             return false;
    272         }
    273 
    274         const GrEffectStage* stages[GrDrawState::kNumStages];
    275         for (int i = 0; i < GrDrawState::kNumStages; ++i) {
    276             stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL;
    277         }
    278         GrGLProgram::Desc desc;
    279         this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, &desc);
    280 
    281         fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
    282         if (NULL == fCurrentProgram.get()) {
    283             GrAssert(!"Failed to create program!");
    284             return false;
    285         }
    286         fCurrentProgram.get()->ref();
    287 
    288         if (fHWProgramID != fCurrentProgram->fProgramID) {
    289             GL_CALL(UseProgram(fCurrentProgram->fProgramID));
    290             fHWProgramID = fCurrentProgram->fProgramID;
    291         }
    292         fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
    293         this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
    294 
    295         GrColor color;
    296         GrColor coverage;
    297         if (blendOpts & kEmitTransBlack_BlendOptFlag) {
    298             color = 0;
    299             coverage = 0;
    300         } else if (blendOpts & kEmitCoverage_BlendOptFlag) {
    301             color = 0xffffffff;
    302             coverage = drawState.getCoverage();
    303         } else {
    304             color = drawState.getColor();
    305             coverage = drawState.getCoverage();
    306         }
    307         this->flushColor(color);
    308         this->flushCoverage(coverage);
    309 
    310         fCurrentProgram->setData(this);
    311     }
    312     this->flushStencil(type);
    313     this->flushViewMatrix(type);
    314     this->flushScissor();
    315     this->flushAAState(type);
    316 
    317     GrIRect* devRect = NULL;
    318     GrIRect devClipBounds;
    319     if (drawState.isClipState()) {
    320         this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
    321         devRect = &devClipBounds;
    322     }
    323     // This must come after textures are flushed because a texture may need
    324     // to be msaa-resolved (which will modify bound FBO state).
    325     this->flushRenderTarget(devRect);
    326 
    327     return true;
    328 }
    329 
    330 #if GR_TEXT_SCALAR_IS_USHORT
    331     #define TEXT_COORDS_GL_TYPE          GR_GL_UNSIGNED_SHORT
    332     #define TEXT_COORDS_ARE_NORMALIZED   1
    333 #elif GR_TEXT_SCALAR_IS_FLOAT
    334     #define TEXT_COORDS_GL_TYPE          GR_GL_FLOAT
    335     #define TEXT_COORDS_ARE_NORMALIZED   0
    336 #elif GR_TEXT_SCALAR_IS_FIXED
    337     #define TEXT_COORDS_GL_TYPE          GR_GL_FIXED
    338     #define TEXT_COORDS_ARE_NORMALIZED   0
    339 #else
    340     #error "unknown GR_TEXT_SCALAR type"
    341 #endif
    342 
    343 void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
    344 
    345     int newColorOffset;
    346     int newCoverageOffset;
    347     int newTexCoordOffsets[GrDrawState::kMaxTexCoords];
    348     int newEdgeOffset;
    349 
    350     GrVertexLayout currLayout = this->getVertexLayout();
    351 
    352     GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout,
    353                                                                  newTexCoordOffsets,
    354                                                                  &newColorOffset,
    355                                                                  &newCoverageOffset,
    356                                                                  &newEdgeOffset);
    357     int oldColorOffset;
    358     int oldCoverageOffset;
    359     int oldTexCoordOffsets[GrDrawState::kMaxTexCoords];
    360     int oldEdgeOffset;
    361 
    362     GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
    363                                                                  oldTexCoordOffsets,
    364                                                                  &oldColorOffset,
    365                                                                  &oldCoverageOffset,
    366                                                                  &oldEdgeOffset);
    367 
    368     int extraVertexOffset;
    369     this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
    370 
    371     GrGLenum scalarType;
    372     bool texCoordNorm;
    373     if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) {
    374         scalarType = TEXT_COORDS_GL_TYPE;
    375         texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED);
    376     } else {
    377         scalarType = GR_GL_FLOAT;
    378         texCoordNorm = false;
    379     }
    380 
    381     size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride;
    382 
    383     // all the Pointers must be set if any of these are true
    384     bool allOffsetsChange =  fHWGeometryState.fArrayPtrsDirty ||
    385                              vertexOffset != fHWGeometryState.fVertexOffset ||
    386                              newStride != oldStride;
    387 
    388     // position and tex coord offsets change if above conditions are true
    389     // or the type/normalization changed based on text vs nontext type coords.
    390     bool posAndTexChange = allOffsetsChange ||
    391                            (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) &&
    392                                 (GrDrawState::kTextFormat_VertexLayoutBit &
    393                                   (fHWGeometryState.fVertexLayout ^ currLayout)));
    394 
    395     if (posAndTexChange) {
    396         int idx = GrGLProgram::PositionAttributeIdx();
    397         GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
    398                                   (GrGLvoid*)vertexOffset));
    399         fHWGeometryState.fVertexOffset = vertexOffset;
    400     }
    401 
    402     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    403         if (newTexCoordOffsets[t] > 0) {
    404             GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
    405             int idx = GrGLProgram::TexCoordAttributeIdx(t);
    406             if (oldTexCoordOffsets[t] <= 0) {
    407                 GL_CALL(EnableVertexAttribArray(idx));
    408                 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
    409                                           newStride, texCoordOffset));
    410             } else if (posAndTexChange ||
    411                        newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
    412                 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
    413                                           newStride, texCoordOffset));
    414             }
    415         } else if (oldTexCoordOffsets[t] > 0) {
    416             GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
    417         }
    418     }
    419 
    420     if (newColorOffset > 0) {
    421         GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
    422         int idx = GrGLProgram::ColorAttributeIdx();
    423         if (oldColorOffset <= 0) {
    424             GL_CALL(EnableVertexAttribArray(idx));
    425             GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    426                                       true, newStride, colorOffset));
    427         } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
    428             GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    429                                       true, newStride, colorOffset));
    430         }
    431     } else if (oldColorOffset > 0) {
    432         GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
    433     }
    434 
    435     if (newCoverageOffset > 0) {
    436         GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
    437         int idx = GrGLProgram::CoverageAttributeIdx();
    438         if (oldCoverageOffset <= 0) {
    439             GL_CALL(EnableVertexAttribArray(idx));
    440             GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    441                                         true, newStride, coverageOffset));
    442         } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
    443             GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
    444                                         true, newStride, coverageOffset));
    445         }
    446     } else if (oldCoverageOffset > 0) {
    447         GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
    448     }
    449 
    450     if (newEdgeOffset > 0) {
    451         GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
    452         int idx = GrGLProgram::EdgeAttributeIdx();
    453         if (oldEdgeOffset <= 0) {
    454             GL_CALL(EnableVertexAttribArray(idx));
    455             GL_CALL(VertexAttribPointer(idx, 4, scalarType,
    456                                         false, newStride, edgeOffset));
    457         } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) {
    458             GL_CALL(VertexAttribPointer(idx, 4, scalarType,
    459                                         false, newStride, edgeOffset));
    460         }
    461     } else if (oldEdgeOffset > 0) {
    462         GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
    463     }
    464 
    465     fHWGeometryState.fVertexLayout = currLayout;
    466     fHWGeometryState.fArrayPtrsDirty = false;
    467 }
    468 
    469 void GrGpuGL::buildProgram(bool isPoints,
    470                            BlendOptFlags blendOpts,
    471                            GrBlendCoeff dstCoeff,
    472                            ProgramDesc* desc) {
    473     const GrDrawState& drawState = this->getDrawState();
    474 
    475     // This should already have been caught
    476     GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts));
    477 
    478     bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
    479 
    480     bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag |
    481                                            kEmitCoverage_BlendOptFlag));
    482 
    483     // The descriptor is used as a cache key. Thus when a field of the
    484     // descriptor will not affect program generation (because of the vertex
    485     // layout in use or other descriptor field settings) it should be set
    486     // to a canonical value to avoid duplicate programs with different keys.
    487 
    488     // Must initialize all fields or cache will have false negatives!
    489     desc->fVertexLayout = this->getVertexLayout();
    490 
    491     desc->fEmitsPointSize = isPoints;
    492 
    493     bool requiresAttributeColors = !skipColor &&
    494                                    SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit);
    495     bool requiresAttributeCoverage = !skipCoverage &&
    496                                      SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit);
    497 
    498     // fColorInput/fCoverageInput records how colors are specified for the.
    499     // program. So we strip the bits from the layout to avoid false negatives
    500     // when searching for an existing program in the cache.
    501     desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
    502 
    503     desc->fColorFilterXfermode = skipColor ?
    504                                 SkXfermode::kDst_Mode :
    505                                 drawState.getColorFilterMode();
    506 
    507     // no reason to do edge aa or look at per-vertex coverage if coverage is
    508     // ignored
    509     if (skipCoverage) {
    510         desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
    511     }
    512 
    513     bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
    514     bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) ||
    515                              (!requiresAttributeColors && 0xffffffff == drawState.getColor());
    516     if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
    517         desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
    518     } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
    519         desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput;
    520     } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
    521         desc->fColorInput = ProgramDesc::kUniform_ColorInput;
    522     } else {
    523         desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
    524     }
    525 
    526     bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
    527 
    528     if (skipCoverage) {
    529         desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
    530     } else if (covIsSolidWhite) {
    531         desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
    532     } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
    533         desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
    534     } else {
    535         desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
    536     }
    537 
    538     int lastEnabledStage = -1;
    539 
    540     if (!skipCoverage && (desc->fVertexLayout &GrDrawState::kEdge_VertexLayoutBit)) {
    541         desc->fVertexEdgeType = drawState.getVertexEdgeType();
    542         desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite();
    543     } else {
    544         // Use canonical values when edge-aa is not enabled to avoid program cache misses.
    545         desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
    546         desc->fDiscardIfOutsideEdge = false;
    547     }
    548 
    549     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    550 
    551         bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
    552         if (!skip && drawState.isStageEnabled(s)) {
    553             lastEnabledStage = s;
    554             const GrEffectRef& effect = *drawState.getStage(s).getEffect();
    555             const GrBackendEffectFactory& factory = effect->getFactory();
    556             desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps());
    557         } else {
    558             desc->fEffectKeys[s] = 0;
    559         }
    560     }
    561 
    562     desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
    563 
    564     // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
    565     // other than pass through values from the VS to the FS anyway).
    566 #if 0 && GR_GL_EXPERIMENTAL_GS
    567     desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
    568 #endif
    569 
    570     // We want to avoid generating programs with different "first cov stage" values when they would
    571     // compute the same result. We set field in the desc to kNumStages when either there are no
    572     // coverage stages or the distinction between coverage and color is immaterial.
    573     int firstCoverageStage = GrDrawState::kNumStages;
    574     desc->fFirstCoverageStage = GrDrawState::kNumStages;
    575     bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
    576     if (hasCoverage) {
    577         firstCoverageStage = drawState.getFirstCoverageStage();
    578     }
    579 
    580     // other coverage inputs
    581     if (!hasCoverage) {
    582         hasCoverage = requiresAttributeCoverage ||
    583                       (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit);
    584     }
    585 
    586     if (hasCoverage) {
    587         // color filter is applied between color/coverage computation
    588         if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
    589             desc->fFirstCoverageStage = firstCoverageStage;
    590         }
    591 
    592         if (this->getCaps().dualSourceBlendingSupport() &&
    593             !(blendOpts & (kEmitCoverage_BlendOptFlag | kCoverageAsAlpha_BlendOptFlag))) {
    594             if (kZero_GrBlendCoeff == dstCoeff) {
    595                 // write the coverage value to second color
    596                 desc->fDualSrcOutput =  ProgramDesc::kCoverage_DualSrcOutput;
    597                 desc->fFirstCoverageStage = firstCoverageStage;
    598             } else if (kSA_GrBlendCoeff == dstCoeff) {
    599                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
    600                 desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
    601                 desc->fFirstCoverageStage = firstCoverageStage;
    602             } else if (kSC_GrBlendCoeff == dstCoeff) {
    603                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
    604                 desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
    605                 desc->fFirstCoverageStage = firstCoverageStage;
    606             }
    607         }
    608     }
    609 }
    610