gfx/skia/trunk/src/gpu/gl/GrGLProgramDesc.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright 2013 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  */
     8 #include "GrGLProgramDesc.h"
     9 #include "GrBackendEffectFactory.h"
    10 #include "GrDrawEffect.h"
    11 #include "GrEffect.h"
    12 #include "GrGLShaderBuilder.h"
    13 #include "GrGpuGL.h"
    15 #include "SkChecksum.h"
    17 namespace {
    18 inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage,
    19                                                       const GrGLCaps& caps,
    20                                                       bool useExplicitLocalCoords,
    21                                                       bool* setTrueIfReadsDst,
    22                                                       bool* setTrueIfReadsPos,
    23                                                       bool* setTrueIfHasVertexCode) {
    24     const GrEffectRef& effect = *stage.getEffect();
    25     const GrBackendEffectFactory& factory = effect->getFactory();
    26     GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
    27     if (effect->willReadDstColor()) {
    28         *setTrueIfReadsDst = true;
    29     }
    30     if (effect->willReadFragmentPosition()) {
    31         *setTrueIfReadsPos = true;
    32     }
    33     if (effect->hasVertexCode()) {
    34         *setTrueIfHasVertexCode = true;
    35     }
    36     return factory.glEffectKey(drawEffect, caps);
    37 }
    38 }
    39 void GrGLProgramDesc::Build(const GrDrawState& drawState,
    40                             bool isPoints,
    41                             GrDrawState::BlendOptFlags blendOpts,
    42                             GrBlendCoeff srcCoeff,
    43                             GrBlendCoeff dstCoeff,
    44                             const GrGpuGL* gpu,
    45                             const GrDeviceCoordTexture* dstCopy,
    46                             SkTArray<const GrEffectStage*, true>* colorStages,
    47                             SkTArray<const GrEffectStage*, true>* coverageStages,
    48                             GrGLProgramDesc* desc) {
    49     colorStages->reset();
    50     coverageStages->reset();
    52     // This should already have been caught
    53     SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
    55     bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
    57     bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
    58                                            GrDrawState::kEmitCoverage_BlendOptFlag));
    59     int firstEffectiveColorStage = 0;
    60     bool inputColorIsUsed = true;
    61     if (!skipColor) {
    62         firstEffectiveColorStage = drawState.numColorStages();
    63         while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
    64             --firstEffectiveColorStage;
    65             const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect()->get();
    66             inputColorIsUsed = effect->willUseInputColor();
    67         }
    68     }
    70     int firstEffectiveCoverageStage = 0;
    71     bool inputCoverageIsUsed = true;
    72     if (!skipCoverage) {
    73         firstEffectiveCoverageStage = drawState.numCoverageStages();
    74         while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
    75             --firstEffectiveCoverageStage;
    76             const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect()->get();
    77             inputCoverageIsUsed = effect->willUseInputColor();
    78         }
    79     }
    81     // The descriptor is used as a cache key. Thus when a field of the
    82     // descriptor will not affect program generation (because of the attribute
    83     // bindings in use or other descriptor field settings) it should be set
    84     // to a canonical value to avoid duplicate programs with different keys.
    86     bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
    87     bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
    88     // we only need the local coords if we're actually going to generate effect code
    89     bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
    90                                     drawState.hasLocalCoordAttribute();
    92     bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
    93     bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
    94                              (!requiresColorAttrib && 0xffffffff == drawState.getColor()) ||
    95                              (!inputColorIsUsed);
    97     int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) +
    98                      (skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage));
   100     size_t newKeyLength = KeyLength(numEffects);
   101     bool allocChanged;
   102     desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
   103     if (allocChanged || !desc->fInitialized) {
   104         // make sure any padding in the header is zero if we we haven't used this allocation before.
   105         memset(desc->header(), 0, kHeaderSize);
   106     }
   107     // write the key length
   108     *desc->atOffset<uint32_t, kLengthOffset>() = SkToU32(newKeyLength);
   110     KeyHeader* header = desc->header();
   111     EffectKey* effectKeys = desc->effectKeys();
   113     int currEffectKey = 0;
   114     bool readsDst = false;
   115     bool readFragPosition = false;
   116     bool hasVertexCode = false;
   117     if (!skipColor) {
   118         for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
   119             effectKeys[currEffectKey++] =
   120                 get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
   121                                          requiresLocalCoordAttrib, &readsDst, &readFragPosition,
   122                                          &hasVertexCode);
   123         }
   124     }
   125     if (!skipCoverage) {
   126         for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
   127             effectKeys[currEffectKey++] =
   128                 get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
   129                                          requiresLocalCoordAttrib, &readsDst, &readFragPosition,
   130                                          &hasVertexCode);
   131         }
   132     }
   134     header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
   135     header->fEmitsPointSize = isPoints;
   137     // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
   138     // other than pass through values from the VS to the FS anyway).
   139 #if GR_GL_EXPERIMENTAL_GS
   140 #if 0
   141     header->fExperimentalGS = gpu->caps().geometryShaderSupport();
   142 #else
   143     header->fExperimentalGS = false;
   144 #endif
   145 #endif
   146     bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
   148     if (colorIsTransBlack) {
   149         header->fColorInput = kTransBlack_ColorInput;
   150     } else if (colorIsSolidWhite) {
   151         header->fColorInput = kSolidWhite_ColorInput;
   152     } else if (defaultToUniformInputs && !requiresColorAttrib) {
   153         header->fColorInput = kUniform_ColorInput;
   154     } else {
   155         header->fColorInput = kAttribute_ColorInput;
   156         header->fHasVertexCode = true;
   157     }
   159     bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
   161     if (skipCoverage) {
   162         header->fCoverageInput = kTransBlack_ColorInput;
   163     } else if (covIsSolidWhite || !inputCoverageIsUsed) {
   164         header->fCoverageInput = kSolidWhite_ColorInput;
   165     } else if (defaultToUniformInputs && !requiresCoverageAttrib) {
   166         header->fCoverageInput = kUniform_ColorInput;
   167     } else {
   168         header->fCoverageInput = kAttribute_ColorInput;
   169         header->fHasVertexCode = true;
   170     }
   172     if (readsDst) {
   173         SkASSERT(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
   174         const GrTexture* dstCopyTexture = NULL;
   175         if (NULL != dstCopy) {
   176             dstCopyTexture = dstCopy->texture();
   177         }
   178         header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
   179         SkASSERT(0 != header->fDstReadKey);
   180     } else {
   181         header->fDstReadKey = 0;
   182     }
   184     if (readFragPosition) {
   185         header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
   186                                                                       gpu->glCaps());
   187     } else {
   188         header->fFragPosKey = 0;
   189     }
   191     // Record attribute indices
   192     header->fPositionAttributeIndex = drawState.positionAttributeIndex();
   193     header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
   195     // For constant color and coverage we need an attribute with an index beyond those already set
   196     int availableAttributeIndex = drawState.getVertexAttribCount();
   197     if (requiresColorAttrib) {
   198         header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
   199     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
   200         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
   201         header->fColorAttributeIndex = availableAttributeIndex;
   202         availableAttributeIndex++;
   203     } else {
   204         header->fColorAttributeIndex = -1;
   205     }
   207     if (requiresCoverageAttrib) {
   208         header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
   209     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
   210         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
   211         header->fCoverageAttributeIndex = availableAttributeIndex;
   212     } else {
   213         header->fCoverageAttributeIndex = -1;
   214     }
   216     // Here we deal with whether/how we handle color and coverage separately.
   218     // Set this default and then possibly change our mind if there is coverage.
   219     header->fCoverageOutput = kModulate_CoverageOutput;
   221     // If we do have coverage determine whether it matters.
   222     bool separateCoverageFromColor = false;
   223     if (!drawState.isCoverageDrawing() && !skipCoverage &&
   224         (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
   226         if (gpu->caps()->dualSourceBlendingSupport() &&
   227             !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
   228                            GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
   229             if (kZero_GrBlendCoeff == dstCoeff) {
   230                 // write the coverage value to second color
   231                 header->fCoverageOutput =  kSecondaryCoverage_CoverageOutput;
   232                 separateCoverageFromColor = true;
   233             } else if (kSA_GrBlendCoeff == dstCoeff) {
   234                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
   235                 header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
   236                 separateCoverageFromColor = true;
   237             } else if (kSC_GrBlendCoeff == dstCoeff) {
   238                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
   239                 header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
   240                 separateCoverageFromColor = true;
   241             }
   242         } else if (readsDst &&
   243                    kOne_GrBlendCoeff == srcCoeff &&
   244                    kZero_GrBlendCoeff == dstCoeff) {
   245             header->fCoverageOutput = kCombineWithDst_CoverageOutput;
   246             separateCoverageFromColor = true;
   247         }
   248     }
   249     if (!skipColor) {
   250         for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
   251             colorStages->push_back(&drawState.getColorStage(s));
   252         }
   253     }
   254     if (!skipCoverage) {
   255         SkTArray<const GrEffectStage*, true>* array;
   256         if (separateCoverageFromColor) {
   257             array = coverageStages;
   258         } else {
   259             array = colorStages;
   260         }
   261         for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
   262             array->push_back(&drawState.getCoverageStage(s));
   263         }
   264     }
   265     header->fColorEffectCnt = colorStages->count();
   266     header->fCoverageEffectCnt = coverageStages->count();
   268     *desc->checksum() = 0;
   269     *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),
   270                                             newKeyLength);
   271     desc->fInitialized = true;
   272 }
   274 GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
   275     fInitialized = other.fInitialized;
   276     if (fInitialized) {
   277         size_t keyLength = other.keyLength();
   278         fKey.reset(keyLength);
   279         memcpy(fKey.get(), other.fKey.get(), keyLength);
   280     }
   281     return *this;
   282 }

mercurial