Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Unified Diff: src/gpu/gl/GrGLProgramDesc.cpp

Issue 15252004: Make GrGLProgramDesc's key variable length by compacting the effect key array (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: address comments, fix unit test Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/gl/GrGLProgramDesc.h ('k') | src/gpu/gl/GrGLShaderBuilder.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/gl/GrGLProgramDesc.cpp
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index e8812fade79d743cb30146ec858ff7d1b01a18fc..276f9b5a09ea6b3e8a94078c531efebb63ec0e97 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -12,6 +12,8 @@
#include "GrGLShaderBuilder.h"
#include "GrGpuGL.h"
+#include "SkChecksum.h"
+
void GrGLProgramDesc::Build(const GrDrawState& drawState,
bool isPoints,
GrDrawState::BlendOptFlags blendOpts,
@@ -19,8 +21,8 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
GrBlendCoeff dstCoeff,
const GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
+ const GrEffectStage* stages[],
GrGLProgramDesc* desc) {
-
// This should already have been caught
GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
@@ -34,131 +36,169 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
// bindings in use or other descriptor field settings) it should be set
// to a canonical value to avoid duplicate programs with different keys.
-
- desc->fEmitsPointSize = isPoints;
-
bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
// we only need the local coords if we're actually going to generate effect code
bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
drawState.hasLocalCoordAttribute();
- // fColorInput/fCoverageInput records how colors are specified for the program so we strip the
- // bits from the bindings to avoid false negatives when searching for an existing program in the
- // cache.
-
- desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
-
-
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
(!requiresColorAttrib && 0xffffffff == drawState.getColor());
- if (colorIsTransBlack) {
- desc->fColorInput = kTransBlack_ColorInput;
- } else if (colorIsSolidWhite) {
- desc->fColorInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
- desc->fColorInput = kUniform_ColorInput;
- } else {
- desc->fColorInput = kAttribute_ColorInput;
- }
- bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
+ // Do an initial loop over the stages to count them. We count the color and coverage effects
+ // separately here. Later we may decide the distinction doesn't matter and will count all
+ // effects as color in desc. Two things will allow simplication of this mess: GrDrawState will
+ // have tight lists of color and coverage stages rather than a fixed size array with NULLS and
+ // the xfermode-color filter will be removed.
+ int colorEffectCnt = 0;
+ int coverageEffectCnt = 0;
+ if (!skipColor) {
+ for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
+ if (drawState.isStageEnabled(s)) {
+ stages[colorEffectCnt] = &drawState.getStage(s);
+ ++colorEffectCnt;
+ }
+ }
+ }
+ if (!skipCoverage) {
+ for (int s = drawState.getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
+ if (drawState.isStageEnabled(s)) {
+ stages[colorEffectCnt + coverageEffectCnt] = &drawState.getStage(s);
+ ++coverageEffectCnt;
+ }
+ }
+ }
- if (skipCoverage) {
- desc->fCoverageInput = kTransBlack_ColorInput;
- } else if (covIsSolidWhite) {
- desc->fCoverageInput = kSolidWhite_ColorInput;
- } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
- desc->fCoverageInput = kUniform_ColorInput;
- } else {
- desc->fCoverageInput = kAttribute_ColorInput;
+ size_t newKeyLength = KeyLength(colorEffectCnt + coverageEffectCnt);
+ bool allocChanged;
+ desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
+ if (allocChanged || !desc->fInitialized) {
+ // make sure any padding in the header is zero if we we haven't used this allocation before.
+ memset(desc->header(), 0, kHeaderSize);
}
+ // write the key length
+ *desc->atOffset<uint32_t, kLengthOffset>() = newKeyLength;
+
+ KeyHeader* header = desc->header();
+ EffectKey* effectKeys = desc->effectKeys();
+ int currEffectKey = 0;
bool readsDst = false;
bool readFragPosition = false;
- int lastEnabledStage = -1;
-
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-
bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
if (!skip && drawState.isStageEnabled(s)) {
- lastEnabledStage = s;
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
const GrBackendEffectFactory& factory = effect->getFactory();
GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
- desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
+ effectKeys[currEffectKey] = factory.glEffectKey(drawEffect, gpu->glCaps());
+ ++currEffectKey;
if (effect->willReadDstColor()) {
readsDst = true;
}
if (effect->willReadFragmentPosition()) {
readFragPosition = true;
}
- } else {
- desc->fEffectKeys[s] = 0;
}
}
+ header->fEmitsPointSize = isPoints;
+ header->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
+
+ // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
+ // other than pass through values from the VS to the FS anyway).
+#if GR_GL_EXPERIMENTAL_GS
+#if 0
+ header->fExperimentalGS = gpu->caps().geometryShaderSupport();
+#else
+ header->fExperimentalGS = false;
+#endif
+#endif
+ if (colorIsTransBlack) {
+ header->fColorInput = kTransBlack_ColorInput;
+ } else if (colorIsSolidWhite) {
+ header->fColorInput = kSolidWhite_ColorInput;
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
+ header->fColorInput = kUniform_ColorInput;
+ } else {
+ header->fColorInput = kAttribute_ColorInput;
+ }
+
+ bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
+
+ if (skipCoverage) {
+ header->fCoverageInput = kTransBlack_ColorInput;
+ } else if (covIsSolidWhite) {
+ header->fCoverageInput = kSolidWhite_ColorInput;
+ } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
+ header->fCoverageInput = kUniform_ColorInput;
+ } else {
+ header->fCoverageInput = kAttribute_ColorInput;
+ }
+
if (readsDst) {
GrAssert(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
const GrTexture* dstCopyTexture = NULL;
if (NULL != dstCopy) {
dstCopyTexture = dstCopy->texture();
}
- desc->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
- GrAssert(0 != desc->fDstReadKey);
+ header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
+ GrAssert(0 != header->fDstReadKey);
} else {
- desc->fDstReadKey = 0;
+ header->fDstReadKey = 0;
}
if (readFragPosition) {
- desc->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
+ header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
gpu->glCaps());
} else {
- desc->fFragPosKey = 0;
+ header->fFragPosKey = 0;
}
- desc->fCoverageOutput = kModulate_CoverageOutput;
-
- // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
- // other than pass through values from the VS to the FS anyway).
-#if GR_GL_EXPERIMENTAL_GS
-#if 0
- desc->fExperimentalGS = gpu->caps().geometryShaderSupport();
-#else
- desc->fExperimentalGS = false;
-#endif
-#endif
-
- // We leave this set to kNumStages until we discover that the coverage/color distinction is
- // material to the generated program. We do this to avoid distinct keys that generate equivalent
- // programs.
- desc->fFirstCoverageStage = GrDrawState::kNumStages;
- // This tracks the actual first coverage stage.
- int firstCoverageStage = GrDrawState::kNumStages;
- desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage.
- bool hasCoverage = false;
- // If we're rendering coverage-as-color then it's as though there are no coverage stages.
- if (!drawState.isCoverageDrawing()) {
- // We can have coverage either through a stage or coverage vertex attributes.
- if (drawState.getFirstCoverageStage() <= lastEnabledStage) {
- firstCoverageStage = drawState.getFirstCoverageStage();
- hasCoverage = true;
- } else {
- hasCoverage = requiresCoverageAttrib;
- }
+ // Record attribute indices
+ header->fPositionAttributeIndex = drawState.positionAttributeIndex();
+ header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
+
+ // For constant color and coverage we need an attribute with an index beyond those already set
+ int availableAttributeIndex = drawState.getVertexAttribCount();
+ if (requiresColorAttrib) {
+ header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
+ } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
+ GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
+ header->fColorAttributeIndex = availableAttributeIndex;
+ availableAttributeIndex++;
+ } else {
+ header->fColorAttributeIndex = -1;
+ }
+
+ if (requiresCoverageAttrib) {
+ header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
+ } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
+ GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
+ header->fCoverageAttributeIndex = availableAttributeIndex;
+ } else {
+ header->fCoverageAttributeIndex = -1;
}
- if (hasCoverage) {
+ // Here we deal with whether/how we handle color and coverage separately.
+
+ // Set these defaults and then possibly change our mind if there is coverage.
+ header->fDiscardIfZeroCoverage = false;
+ header->fCoverageOutput = kModulate_CoverageOutput;
+
+ // If we do have coverage determine whether it matters.
+ bool separateCoverageFromColor = false;
+ if (!drawState.isCoverageDrawing() && (coverageEffectCnt > 0 || requiresCoverageAttrib)) {
// color filter is applied between color/coverage computation
- if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
- desc->fFirstCoverageStage = firstCoverageStage;
+ if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
+ separateCoverageFromColor = true;
}
// If we're stenciling then we want to discard samples that have zero coverage
if (drawState.getStencil().doesWrite()) {
- desc->fDiscardIfZeroCoverage = true;
- desc->fFirstCoverageStage = firstCoverageStage;
+ header->fDiscardIfZeroCoverage = true;
+ separateCoverageFromColor = true;
}
if (gpu->caps()->dualSourceBlendingSupport() &&
@@ -166,46 +206,45 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
if (kZero_GrBlendCoeff == dstCoeff) {
// write the coverage value to second color
- desc->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
- desc->fFirstCoverageStage = firstCoverageStage;
+ header->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
+ separateCoverageFromColor = true;
} else if (kSA_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- desc->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
- desc->fFirstCoverageStage = firstCoverageStage;
+ header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
+ separateCoverageFromColor = true;
} else if (kSC_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- desc->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
- desc->fFirstCoverageStage = firstCoverageStage;
+ header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
+ separateCoverageFromColor = true;
}
} else if (readsDst &&
kOne_GrBlendCoeff == srcCoeff &&
kZero_GrBlendCoeff == dstCoeff) {
- desc->fCoverageOutput = kCombineWithDst_CoverageOutput;
- desc->fFirstCoverageStage = firstCoverageStage;
+ header->fCoverageOutput = kCombineWithDst_CoverageOutput;
+ separateCoverageFromColor = true;
}
}
-
- desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
- desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
-
- // For constant color and coverage we need an attribute with an index beyond those already set
- int availableAttributeIndex = drawState.getVertexAttribCount();
- if (requiresColorAttrib) {
- desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
- } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
- GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
- desc->fColorAttributeIndex = availableAttributeIndex;
- availableAttributeIndex++;
+ if (separateCoverageFromColor) {
+ header->fColorEffectCnt = colorEffectCnt;
+ header->fCoverageEffectCnt = coverageEffectCnt;
} else {
- desc->fColorAttributeIndex = -1;
+ header->fColorEffectCnt = colorEffectCnt + coverageEffectCnt;
+ header->fCoverageEffectCnt = 0;
}
- if (requiresCoverageAttrib) {
- desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
- } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
- GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
- desc->fCoverageAttributeIndex = availableAttributeIndex;
- } else {
- desc->fCoverageAttributeIndex = -1;
+ *desc->checksum() = 0;
+ *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),
+ newKeyLength);
+ desc->fInitialized = true;
+}
+
+GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
+ fInitialized = other.fInitialized;
+ if (fInitialized) {
+ size_t keyLength = other.keyLength();
+ fKey.reset(keyLength);
+ memcpy(fKey.get(), other.fKey.get(), keyLength);
}
+ return *this;
}
+
« no previous file with comments | « src/gpu/gl/GrGLProgramDesc.h ('k') | src/gpu/gl/GrGLShaderBuilder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698