Index: src/gpu/gl/GrGLProgramDesc.cpp |
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp |
index ecd48e014810eb4158a452a256418bad0aaba159..2c260cda52b16e3808fc03534b76e6d640ef49fc 100644 |
--- a/src/gpu/gl/GrGLProgramDesc.cpp |
+++ b/src/gpu/gl/GrGLProgramDesc.cpp |
@@ -14,29 +14,28 @@ |
#include "SkChecksum.h" |
-namespace { |
-inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage, |
- const GrGLCaps& caps, |
- bool useExplicitLocalCoords, |
- bool* setTrueIfReadsDst, |
- bool* setTrueIfReadsPos, |
- bool* setTrueIfHasVertexCode) { |
- const GrEffect* effect = stage.getEffect(); |
- const GrBackendEffectFactory& factory = effect->getFactory(); |
+static inline bool get_key_and_update_stats(const GrEffectStage& stage, |
+ const GrGLCaps& caps, |
+ bool useExplicitLocalCoords, |
+ GrEffectKeyBuilder* b, |
+ bool* setTrueIfReadsDst, |
+ bool* setTrueIfReadsPos, |
+ bool* setTrueIfHasVertexCode) { |
+ const GrBackendEffectFactory& factory = stage.getEffect()->getFactory(); |
GrDrawEffect drawEffect(stage, useExplicitLocalCoords); |
- if (effect->willReadDstColor()) { |
+ if (stage.getEffect()->willReadDstColor()) { |
*setTrueIfReadsDst = true; |
} |
- if (effect->willReadFragmentPosition()) { |
+ if (stage.getEffect()->willReadFragmentPosition()) { |
*setTrueIfReadsPos = true; |
} |
- if (effect->hasVertexCode()) { |
+ if (stage.getEffect()->hasVertexCode()) { |
*setTrueIfHasVertexCode = true; |
} |
- return factory.glEffectKey(drawEffect, caps); |
+ return factory.getGLEffectKey(drawEffect, caps, b); |
} |
-} |
-void GrGLProgramDesc::Build(const GrDrawState& drawState, |
+ |
+bool GrGLProgramDesc::Build(const GrDrawState& drawState, |
GrGpu::DrawType drawType, |
GrDrawState::BlendOptFlags blendOpts, |
GrBlendCoeff srcCoeff, |
@@ -94,45 +93,68 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, |
(!requiresColorAttrib && 0xffffffff == drawState.getColor()) || |
(!inputColorIsUsed); |
- int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) + |
- (skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage)); |
- |
- size_t newKeyLength = KeyLength(numEffects); |
- 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>() = SkToU32(newKeyLength); |
- |
- KeyHeader* header = desc->header(); |
- EffectKey* effectKeys = desc->effectKeys(); |
- |
- int currEffectKey = 0; |
bool readsDst = false; |
bool readFragPosition = false; |
// We use vertexshader-less shader programs only when drawing paths. |
bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType || |
GrGpu::kDrawPaths_DrawType == drawType); |
+ int numStages = 0; |
+ if (!skipColor) { |
+ numStages += drawState.numColorStages() - firstEffectiveColorStage; |
+ } |
+ if (!skipCoverage) { |
+ numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage; |
+ } |
+ GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t)); |
+ // Make room for everything up to and including the array of offsets to effect keys. |
+ desc->fKey.reset(); |
+ desc->fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages); |
+ size_t offset = desc->fKey.count(); |
+ int offsetIndex = 0; |
+ |
+ bool effectKeySuccess = true; |
if (!skipColor) { |
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { |
- effectKeys[currEffectKey++] = |
- get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), |
- requiresLocalCoordAttrib, &readsDst, &readFragPosition, |
- &hasVertexCode); |
+ uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() + |
+ kEffectKeyLengthsOffset + |
+ offsetIndex * sizeof(uint32_t)); |
+ *offsetLocation = offset; |
+ ++offsetIndex; |
+ |
+ GrEffectKeyBuilder b(&desc->fKey); |
+ effectKeySuccess |= get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), |
+ requiresLocalCoordAttrib, &b, &readsDst, |
+ &readFragPosition, &hasVertexCode); |
+ offset += b.size(); |
} |
} |
if (!skipCoverage) { |
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { |
- effectKeys[currEffectKey++] = |
- get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(), |
- requiresLocalCoordAttrib, &readsDst, &readFragPosition, |
- &hasVertexCode); |
+ uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() + |
+ kEffectKeyLengthsOffset + |
+ offsetIndex * sizeof(uint32_t)); |
+ *offsetLocation = offset; |
+ ++offsetIndex; |
+ GrEffectKeyBuilder b(&desc->fKey); |
+ effectKeySuccess |= get_key_and_update_stats(drawState.getCoverageStage(s), |
+ gpu->glCaps(), requiresLocalCoordAttrib, |
+ &b, &readsDst, &readFragPosition, |
+ &hasVertexCode); |
+ offset += b.size(); |
} |
} |
+ if (!effectKeySuccess) { |
+ desc->fKey.reset(); |
+ return false; |
+ } |
+ |
+ KeyHeader* header = desc->header(); |
+ // make sure any padding in the header is zeroed. |
+ memset(desc->header(), 0, kHeaderSize); |
+ |
+ // Because header is a pointer into the dynamic array, we can't push any new data into the key |
+ // below here. |
header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib; |
header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType; |
@@ -268,18 +290,23 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, |
header->fColorEffectCnt = colorStages->count(); |
header->fCoverageEffectCnt = coverageStages->count(); |
- *desc->checksum() = 0; |
- *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()), |
- newKeyLength); |
- desc->fInitialized = true; |
+ desc->finalize(); |
+ return true; |
+} |
+ |
+void GrGLProgramDesc::finalize() { |
+ int keyLength = fKey.count(); |
+ SkASSERT(0 == (keyLength % 4)); |
+ *this->atOffset<uint32_t, kLengthOffset>() = SkToU32(keyLength); |
+ |
+ uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>(); |
+ *checksum = 0; |
+ *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength); |
} |
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); |
- } |
+ size_t keyLength = other.keyLength(); |
+ fKey.reset(keyLength); |
+ memcpy(fKey.begin(), other.fKey.begin(), keyLength); |
return *this; |
} |