diff options
-rw-r--r-- | gyp/gpu.gyp | 2 | ||||
-rw-r--r-- | include/gpu/GrCustomStage.h (renamed from src/gpu/GrCustomStage.h) | 4 | ||||
-rw-r--r-- | include/gpu/GrSamplerState.h | 22 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 96 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 17 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramStage.h | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGLShaders.cpp | 56 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGLShaders.h | 4 |
8 files changed, 185 insertions, 27 deletions
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 685eca18be..f0f9821672 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -178,6 +178,7 @@ '../include/gpu/GrConfig.h', '../include/gpu/GrContext.h', '../include/gpu/GrContextFactory.h', + '../include/gpu/GrCustomStage.h', '../include/gpu/GrFontScaler.h', '../include/gpu/GrGlyph.h', '../include/gpu/GrInstanceCounter.h', @@ -221,7 +222,6 @@ '../src/gpu/GrClip.cpp', '../src/gpu/GrContext.cpp', '../src/gpu/GrCustomStage.cpp', - '../src/gpu/GrCustomStage.h', '../src/gpu/GrDefaultPathRenderer.cpp', '../src/gpu/GrDefaultPathRenderer.h', '../src/gpu/GrDefaultTextContext.cpp', diff --git a/src/gpu/GrCustomStage.h b/include/gpu/GrCustomStage.h index a5b8133c7f..25ab005472 100644 --- a/src/gpu/GrCustomStage.h +++ b/include/gpu/GrCustomStage.h @@ -8,13 +8,15 @@ #ifndef GrCustomStage_DEFINED #define GrCustomStage_DEFINED +#include "GrRefCnt.h" + class GrContext; class GrGLProgramStageFactory; /** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the Ganesh shading pipeline. TODO: may want to refcount these? */ -class GrCustomStage { +class GrCustomStage : public GrRefCnt { public: diff --git a/include/gpu/GrSamplerState.h b/include/gpu/GrSamplerState.h index 50a6cc9ec7..d9957bd578 100644 --- a/include/gpu/GrSamplerState.h +++ b/include/gpu/GrSamplerState.h @@ -11,8 +11,9 @@ #ifndef GrSamplerState_DEFINED #define GrSamplerState_DEFINED -#include "GrTypes.h" +#include "GrCustomStage.h" #include "GrMatrix.h" +#include "GrTypes.h" #define MAX_KERNEL_WIDTH 25 @@ -110,12 +111,17 @@ public: * unfiltered, and use identity matrix. */ GrSamplerState() - : fRadial2CenterX1() + : fCustomStage (NULL) + , fRadial2CenterX1() , fRadial2Radius0() , fRadial2PosRoot() { this->reset(); } + ~GrSamplerState() { + GrSafeUnref(fCustomStage); + } + WrapMode getWrapX() const { return fWrapX; } WrapMode getWrapY() const { return fWrapY; } FilterDirection getFilterDirection() const { return fFilterDirection; } @@ -188,6 +194,7 @@ public: fMatrix = matrix; fTextureDomain.setEmpty(); fSwapRAndB = false; + GrSafeSetNull(fCustomStage); } void reset(WrapMode wrapXAndY, Filter filter, const GrMatrix& matrix) { this->reset(wrapXAndY, filter, kDefault_FilterDirection, matrix); @@ -236,6 +243,11 @@ public: fKernelWidth = radius; } + void setCustomStage(GrCustomStage* stage) { + GrSafeAssign(fCustomStage, stage); + } + GrCustomStage* getCustomStage() const { return fCustomStage; } + private: WrapMode fWrapX : 8; WrapMode fWrapY : 8; @@ -246,6 +258,12 @@ private: bool fSwapRAndB; GrRect fTextureDomain; + /// BUG! Ganesh only works correctly so long as fCustomStage is + /// NULL; we need to have a complex ID system here so that we can + /// have an equality-like comparison to determine whether two + /// fCustomStages are equal. + GrCustomStage* fCustomStage; + // these are undefined unless fSampleMode == kRadial2_SampleMode GrScalar fRadial2CenterX1; GrScalar fRadial2Radius0; diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 16a60cee91..fb98b4d3a7 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -10,6 +10,8 @@ #include "GrGLProgram.h" #include "../GrAllocator.h" +#include "GrCustomStage.h" +#include "GrGLProgramStage.h" #include "GrGLShaderVar.h" #include "SkTrace.h" #include "SkXfermode.h" @@ -620,8 +622,17 @@ const char* GrGLProgram::adjustInColor(const GrStringBuilder& inColor) const { } } +// If this destructor is in the header file, we must include GrGLProgramStage +// instead of just forward-declaring it. +GrGLProgram::CachedData::~CachedData() { + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + delete fCustomStage[i]; + } +} + bool GrGLProgram::genProgram(const GrGLContextInfo& gl, + GrCustomStage** customStages, GrGLProgram::CachedData* programData) const { ShaderCodeSegments segments; @@ -733,6 +744,21 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, } /////////////////////////////////////////////////////////////////////////// + // Convert generic effect representation to GL-specific backend so they + // can be accesseed in genStageCode() and in subsequent uses of + // programData. + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + GrCustomStage* customStage = customStages[s]; + if (NULL != customStage) { + GrGLProgramStageFactory* factory = customStage->getGLFactory(); + programData->fCustomStage[s] = + factory->createGLInstance(customStage); + } else { + programData->fCustomStage[s] = NULL; + } + } + + /////////////////////////////////////////////////////////////////////////// // compute the final color // if we have color stages string them together, feeding the output color @@ -766,7 +792,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, outColor.c_str(), inCoords, &segments, - &programData->fUniLocations.fStages[s]); + &programData->fUniLocations.fStages[s], + programData->fCustomStage[s]); inColor = outColor; } } @@ -878,13 +905,14 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, inCoords = texCoordAttrs[tcIdx].c_str(); } - genStageCode(gl, s, - fProgramDesc.fStages[s], - inCoverage.size() ? inCoverage.c_str() : NULL, - outCoverage.c_str(), - inCoords, - &segments, - &programData->fUniLocations.fStages[s]); + this->genStageCode(gl, s, + fProgramDesc.fStages[s], + inCoverage.size() ? inCoverage.c_str() : NULL, + outCoverage.c_str(), + inCoords, + &segments, + &programData->fUniLocations.fStages[s], + programData->fCustomStage[s]); inCoverage = outCoverage; } } @@ -1348,6 +1376,11 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, imageIncrementName.c_str())); GrAssert(kUnusedUniform != locations.fImageIncrementUni); } + + if (NULL != programData->fCustomStage[s]) { + programData->fCustomStage[s]-> + initUniforms(gl.interface(), progID); + } } } GL_CALL(UseProgram(progID)); @@ -1363,6 +1396,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, programData->fTextureWidth[s] = -1; programData->fTextureHeight[s] = -1; programData->fTextureDomain[s].setEmpty(); + // Must not reset fStageOverride[] here. } programData->fViewMatrix = GrMatrix::InvalidMatrix(); programData->fColor = GrColor_ILLEGAL; @@ -1712,7 +1746,8 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, const char* fsOutColor, const char* vsInCoord, ShaderCodeSegments* segments, - StageUniLocations* locations) const { + StageUniLocations* locations, + GrGLProgramStage* customStage) const { GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages); GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == @@ -1723,8 +1758,13 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, // gradients. static const int coordDims = 2; int varyingDims; + /// Vertex Shader Stuff + if (NULL != customStage) { + customStage->setupVSUnis(segments->fVSUnis, stageNum); + } + // decide whether we need a matrix to transform texture coords // and whether the varying needs a perspective coord. const char* matName = NULL; @@ -1808,7 +1848,20 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, &imageIncrementName, varyingVSName); } + if (NULL != customStage) { + GrStringBuilder vertexShader; + customStage->emitVS(&vertexShader, varyingVSName); + segments->fVSCode.appendf("{\n"); + segments->fVSCode.append(vertexShader); + segments->fVSCode.appendf("}\n"); + } + /// Fragment Shader Stuff + + if (NULL != customStage) { + customStage->setupFSUnis(segments->fFSUnis, stageNum); + } + GrStringBuilder fsCoordName; // function used to access the shader, may be made projective GrStringBuilder texFunc("texture2D"); @@ -1959,6 +2012,31 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, swizzle, modulate.c_str()); } } + + if (NULL != customStage) { + if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit | + StageDesc::kNoPerspective_OptFlagBit)) { + customStage->setSamplerMode(GrGLProgramStage::kDefault_SamplerMode); + } else if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping && + StageDesc::kSingle_FetchMode == desc.fFetchMode) { + customStage->setSamplerMode(GrGLProgramStage::kProj_SamplerMode); + } else { + customStage->setSamplerMode( + GrGLProgramStage::kExplicitDivide_SamplerMode); + } + + GrStringBuilder fragmentShader; + fsCoordName = customStage->emitTextureSetup( + &fragmentShader, varyingFSName, + stageNum, coordDims, varyingDims); + customStage->emitFS(&fragmentShader, fsOutColor, fsInColor, + samplerName, fsCoordName.c_str()); + + // Enclose custom code in a block to avoid namespace conflicts + segments->fFSCode.appendf("{\n"); + segments->fFSCode.append(fragmentShader); + segments->fFSCode.appendf("}\n"); + } } diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 0d8c39a786..73bfa949a6 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -19,6 +19,7 @@ #include "SkXfermode.h" class GrBinHashKeyBuilder; +class GrGLProgramStage; struct ShaderCodeSegments; @@ -49,6 +50,7 @@ public: * but in a separate cacheable container. */ bool genProgram(const GrGLContextInfo& gl, + GrCustomStage** customStages, CachedData* programData) const; /** @@ -180,6 +182,10 @@ public: uint8_t fCoordMapping; // casts to enum CoordMapping uint8_t fKernelWidth; + /** Non-zero if user-supplied code will write the stage's + contribution to the fragment shader. */ + uint16_t fCustomStageKey; + GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask == kInConfigBitMask); @@ -305,10 +311,12 @@ public: class CachedData : public ::GrNoncopyable { public: CachedData() { + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + fCustomStage[i] = NULL; + } } - ~CachedData() { - } + ~CachedData(); void copyAndTakeOwnership(CachedData& other) { memcpy(this, &other, sizeof(*this)); @@ -340,6 +348,8 @@ public: bool fRadial2PosRoot[GrDrawState::kNumStages]; GrRect fTextureDomain[GrDrawState::kNumStages]; + GrGLProgramStage* fCustomStage[GrDrawState::kNumStages]; + private: enum Constants { kUniLocationPreAllocSize = 8 @@ -366,7 +376,8 @@ private: const char* fsOutColor, const char* vsInCoord, ShaderCodeSegments* segments, - StageUniLocations* locations) const; + StageUniLocations* locations, + GrGLProgramStage* override) const; void genGeometryShader(const GrGLContextInfo& gl, ShaderCodeSegments* segments) const; diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h index 83c736d0dd..a56439980c 100644 --- a/src/gpu/gl/GrGLProgramStage.h +++ b/src/gpu/gl/GrGLProgramStage.h @@ -96,8 +96,6 @@ public: void setSamplerMode(SamplerMode shaderMode) { fSamplerMode = shaderMode; } -protected: - /** Returns the *effective* coord name after any perspective divide or other transform. */ GrStringBuilder emitTextureSetup(GrStringBuilder* code, @@ -106,6 +104,8 @@ protected: int coordDims, int varyingDims); +protected: + /** Convenience function for subclasses to write texture2D() or texture2DProj(), depending on fSamplerMode. */ void emitTextureLookup(GrStringBuilder* code, @@ -130,16 +130,19 @@ public: /** Returns a short unique identifier for this subclass x its parameters. If the key differs, different shader code must be generated; if the key matches, shader code can be reused. - 0 == no custom stage. */ + 0 == no custom stage. */ virtual uint16_t stageKey(const GrCustomStage*); + /** Returns a new instance of the appropriate implementation class + for the given GrCustomStage; caller is responsible for deleting + the object. */ virtual GrGLProgramStage* createGLInstance(GrCustomStage*) = 0; protected: /** Disable default constructor - instances should be singletons with static factory functions: our test examples are all stateless, - but we suspect that future implementations may want to cache data? */ + but we suspect that future implementations may want to cache data? */ GrGLProgramStageFactory() { } }; diff --git a/src/gpu/gl/GrGpuGLShaders.cpp b/src/gpu/gl/GrGpuGLShaders.cpp index 9627107e79..1fcfbbee2b 100644 --- a/src/gpu/gl/GrGpuGLShaders.cpp +++ b/src/gpu/gl/GrGpuGLShaders.cpp @@ -8,7 +8,9 @@ #include "../GrBinHashKey.h" +#include "GrCustomStage.h" #include "GrGLProgram.h" +#include "GrGLProgramStage.h" #include "GrGLSL.h" #include "GrGpuGLShaders.h" #include "../GrGpuVertex.h" @@ -82,13 +84,14 @@ public: } } - GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) { + GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc, + GrCustomStage** stages) { Entry newEntry; newEntry.fKey.setKeyData(desc.keyData()); Entry* entry = fHashCache.find(newEntry.fKey); if (NULL == entry) { - if (!desc.genProgram(fGL, &newEntry.fProgramData)) { + if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) { return NULL; } if (fCount < kMaxEntries) { @@ -242,6 +245,8 @@ bool GrGpuGLShaders::programUnitTest() { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } + GrCustomStage* customStages[GrDrawState::kNumStages]; + for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random_bool(&random)) { @@ -288,9 +293,13 @@ bool GrGpuGLShaders::programUnitTest() { stage.fInConfigFlags &= ~kMulByAlphaMask; break; } + + stage.fCustomStageKey = 0; + customStages[s] = NULL; } CachedData cachedData; - if (!program.genProgram(this->glContextInfo(), &cachedData)) { + if (!program.genProgram(this->glContextInfo(), customStages, + &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); @@ -772,8 +781,10 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { return false; } - this->buildProgram(type, blendOpts, dstCoeff); - fProgramData = fProgramCache->getProgramData(fCurrentProgram); + GrCustomStage* customStages [GrDrawState::kNumStages]; + this->buildProgram(type, blendOpts, dstCoeff, customStages); + fProgramData = fProgramCache->getProgramData(fCurrentProgram, + customStages); if (NULL == fProgramData) { GrAssert(!"Failed to create program!"); return false; @@ -814,6 +825,13 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { this->flushTexelSize(s); this->flushTextureDomain(s); + + if (NULL != fProgramData->fCustomStage[s]) { + const GrSamplerState& sampler = + this->getDrawState().getSampler(s); + fProgramData->fCustomStage[s]->setData( + this->glInterface(), sampler.getCustomStage()); + } } } this->flushEdgeAAData(); @@ -962,9 +980,29 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, fHWGeometryState.fArrayPtrsDirty = false; } +namespace { + +void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage, + const GrSamplerState& sampler, + GrCustomStage** customStages, + GrGLProgram* program, int index) { + GrCustomStage* customStage = sampler.getCustomStage(); + if (customStage) { + GrGLProgramStageFactory* factory = customStage->getGLFactory(); + stage->fCustomStageKey = factory->stageKey(customStage); + customStages[index] = customStage; + } else { + stage->fCustomStageKey = 0; + customStages[index] = NULL; + } +} + +} + void GrGpuGLShaders::buildProgram(GrPrimitiveType type, BlendOptFlags blendOpts, - GrBlendCoeff dstCoeff) { + GrBlendCoeff dstCoeff, + GrCustomStage** customStages) { ProgramDesc& desc = fCurrentProgram.fProgramDesc; const GrDrawState& drawState = this->getDrawState(); @@ -1170,12 +1208,18 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, } else { stage.fKernelWidth = 0; } + + setup_custom_stage(&stage, sampler, customStages, + &fCurrentProgram, s); + } else { stage.fOptFlags = 0; stage.fCoordMapping = (StageDesc::CoordMapping) 0; stage.fInConfigFlags = 0; stage.fFetchMode = (StageDesc::FetchMode) 0; stage.fKernelWidth = 0; + stage.fCustomStageKey = 0; + customStages[s] = NULL; } } diff --git a/src/gpu/gl/GrGpuGLShaders.h b/src/gpu/gl/GrGpuGLShaders.h index 39bc97471d..2ce95eb28f 100644 --- a/src/gpu/gl/GrGpuGLShaders.h +++ b/src/gpu/gl/GrGpuGLShaders.h @@ -14,6 +14,7 @@ #include "GrGpuGL.h" #include "GrGLProgram.h" +class GrCustomStage; class GrGpuGLProgram; // Programmable OpenGL or OpenGL ES 2.0 @@ -86,7 +87,8 @@ private: void buildProgram(GrPrimitiveType typeBlend, BlendOptFlags blendOpts, - GrBlendCoeff dstCoeff); + GrBlendCoeff dstCoeff, + GrCustomStage** customStages); ProgramCache* fProgramCache; CachedData* fProgramData; |