Key shader on whether frag pos read is relative to top-left or bottom-left

R=robertphillips@google.com

Review URL: https://codereview.chromium.org/14633007

git-svn-id: http://skia.googlecode.com/svn/trunk@9113 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2013-05-13 18:50:25 +00:00
parent 8686be2fc3
commit b515881446
7 changed files with 63 additions and 28 deletions

View File

@ -451,7 +451,7 @@ public:
/** /**
* Checks whether any of the effects will read the dst pixel color. * Checks whether any of the effects will read the dst pixel color.
*/ */
bool willEffectReadDst() const { bool willEffectReadDstColor() const {
for (int s = 0; s < kNumStages; ++s) { for (int s = 0; s < kNumStages; ++s) {
if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) { if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) {
return true; return true;

View File

@ -407,7 +407,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
} }
bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) { bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) {
if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDst()) { if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
return true; return true;
} }
GrRenderTarget* rt = this->drawState()->getRenderTarget(); GrRenderTarget* rt = this->drawState()->getRenderTarget();
@ -639,7 +639,7 @@ void GrDrawTarget::onDrawRect(const GrRect& rect,
} }
} }
SkTLazy<SkRect> bounds; SkTLazy<SkRect> bounds;
if (this->getDrawState().willEffectReadDst()) { if (this->getDrawState().willEffectReadDstColor()) {
bounds.init(); bounds.init();
this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect); this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect);
} }

View File

@ -76,6 +76,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
} }
bool readsDst = false; bool readsDst = false;
bool readFragPosition = false;
int lastEnabledStage = -1; int lastEnabledStage = -1;
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
@ -90,6 +91,9 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
if (effect->willReadDstColor()) { if (effect->willReadDstColor()) {
readsDst = true; readsDst = true;
} }
if (effect->willReadFragmentPosition()) {
readFragPosition = true;
}
} else { } else {
desc->fEffectKeys[s] = 0; desc->fEffectKeys[s] = 0;
} }
@ -101,10 +105,17 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
if (NULL != dstCopy) { if (NULL != dstCopy) {
dstCopyTexture = dstCopy->texture(); dstCopyTexture = dstCopy->texture();
} }
desc->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); desc->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
GrAssert(0 != desc->fDstRead); GrAssert(0 != desc->fDstReadKey);
} else { } else {
desc->fDstRead = 0; desc->fDstReadKey = 0;
}
if (readFragPosition) {
desc->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
gpu->glCaps());
} else {
desc->fFragPosKey = 0;
} }
desc->fCoverageOutput = kModulate_CoverageOutput; desc->fCoverageOutput = kModulate_CoverageOutput;

View File

@ -79,7 +79,7 @@ private:
// (1 - colorRGB) as the secondary output. Only set if dual source blending is supported. // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
kSecondaryCoverageISC_CoverageOutput, kSecondaryCoverageISC_CoverageOutput,
// Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
// can only be set if fDstRead is set. // can only be set if fDstReadKey is non-zero.
kCombineWithDst_CoverageOutput, kCombineWithDst_CoverageOutput,
kCoverageOutputCnt kCoverageOutputCnt
@ -105,9 +105,12 @@ private:
bool fExperimentalGS; bool fExperimentalGS;
#endif #endif
GrGLShaderBuilder::DstReadKey fDstRead; // set by GrGLShaderBuilder if there GrGLShaderBuilder::DstReadKey fDstReadKey; // set by GrGLShaderBuilder if there
// are effects that must read the dst. // are effects that must read the dst.
// Otherwise, 0. // Otherwise, 0.
GrGLShaderBuilder::FragPosKey fFragPosKey; // set by GrGLShaderBuilder if there are
// effects that read the fragment position.
// Otherwise, 0.
// should the FS discard if the coverage is zero (to avoid stencil manipulation) // should the FS discard if the coverage is zero (to avoid stencil manipulation)
SkBool8 fDiscardIfZeroCoverage; SkBool8 fDiscardIfZeroCoverage;

View File

@ -112,7 +112,8 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
, fSetupFragPosition(false) , fSetupFragPosition(false)
, fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle)
, fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle) , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle)
, fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle) { , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.fFragPosKey) {
fPositionVar = &fVSAttrs.push_back(); fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
@ -125,13 +126,13 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
fLocalCoordsVar = fPositionVar; fLocalCoordsVar = fPositionVar;
} }
// Emit code to read the dst copy textue if necessary. // Emit code to read the dst copy textue if necessary.
if (kNoDstRead_DstReadKey != desc.fDstRead && if (kNoDstRead_DstReadKey != desc.fDstReadKey &&
GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) { GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & desc.fDstRead); bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & desc.fDstReadKey);
const char* dstCopyTopLeftName; const char* dstCopyTopLeftName;
const char* dstCopyCoordScaleName; const char* dstCopyCoordScaleName;
uint32_t configMask; uint32_t configMask;
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & desc.fDstRead)) { if (SkToBool(kUseAlphaConfig_DstReadKeyBit & desc.fDstReadKey)) {
configMask = kA_GrColorComponentFlag; configMask = kA_GrColorComponentFlag;
} else { } else {
configMask = kRGBA_GrColorComponentFlags; configMask = kRGBA_GrColorComponentFlags;
@ -351,6 +352,16 @@ GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture*
return static_cast<DstReadKey>(key); return static_cast<DstReadKey>(key);
} }
GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
const GrGLCaps&) {
if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
return kTopLeftFragPosRead_FragPosKey;
} else {
return kBottomLeftFragPosRead_FragPosKey;
}
}
const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
if (caps.textureRedSupport()) { if (caps.textureRedSupport()) {
@ -473,8 +484,16 @@ const char* GrGLShaderBuilder::fragmentPosition() {
return ""; return "";
} }
} }
#if 1 if (fTopLeftFragPosRead) {
if (fCtxInfo.caps()->fragCoordConventionsSupport()) { if (!fSetupFragPosition) {
fFSInputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kIn_TypeModifier,
"gl_FragCoord",
GrGLShaderVar::kDefault_Precision);
fSetupFragPosition = true;
}
return "gl_FragCoord";
} else if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
if (!fSetupFragPosition) { if (!fSetupFragPosition) {
SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
fFSInputs.push_back().set(kVec4f_GrSLType, fFSInputs.push_back().set(kVec4f_GrSLType,
@ -506,18 +525,6 @@ const char* GrGLShaderBuilder::fragmentPosition() {
GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform); GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform);
return kCoordName; return kCoordName;
} }
#else
// This is the path we'll need to use once we have support for TopLeft
// render targets.
if (!fSetupFragPosition) {
fFSInputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kIn_TypeModifier,
"gl_FragCoord",
GrGLShaderVar::kDefault_Precision);
fSetupFragPosition = true;
}
return "gl_FragCoord";
#endif
} }

View File

@ -193,12 +193,18 @@ public:
const GrGLCaps&); const GrGLCaps&);
typedef uint8_t DstReadKey; typedef uint8_t DstReadKey;
typedef uint8_t FragPosKey;
/** Returns a key for adding code to read the copy-of-dst color in service of effects that /** Returns a key for adding code to read the copy-of-dst color in service of effects that
require reading the dst. It must not return 0 because 0 indicates that there is no dst require reading the dst. It must not return 0 because 0 indicates that there is no dst
copy read at all. */ copy read at all (in which case this function should not be called). */
static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&); static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
/** Returns a key for reading the fragment location. This should only be called if there is an
effect that will requires the fragment position. If the fragment position is not required,
the key is 0. */
static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);
/** If texture swizzling is available using tex parameters then it is preferred over mangling /** If texture swizzling is available using tex parameters then it is preferred over mangling
the generated shader code. This potentially allows greater reuse of cached shaders. */ the generated shader code. This potentially allows greater reuse of cached shaders. */
static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
@ -424,6 +430,12 @@ private:
kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left. kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
}; };
enum {
kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
};
const GrGLContextInfo& fCtxInfo; const GrGLContextInfo& fCtxInfo;
GrGLUniformManager& fUniformManager; GrGLUniformManager& fUniformManager;
uint32_t fFSFeaturesAddedMask; uint32_t fFSFeaturesAddedMask;
@ -443,6 +455,8 @@ private:
GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform; GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
GrGLUniformManager::UniformHandle fDstCopyScaleUniform; GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
bool fTopLeftFragPosRead;
SkSTArray<10, AttributePair, true> fEffectAttributes; SkSTArray<10, AttributePair, true> fEffectAttributes;
GrGLShaderVar* fPositionVar; GrGLShaderVar* fPositionVar;

View File

@ -70,7 +70,7 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
} }
if (dstRead) { if (dstRead) {
this->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstTexture, gpu->glCaps()); this->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstTexture, gpu->glCaps());
} }
CoverageOutput coverageOutput; CoverageOutput coverageOutput;