aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gyp2
-rw-r--r--include/gpu/GrCustomStage.h (renamed from src/gpu/GrCustomStage.h)4
-rw-r--r--include/gpu/GrSamplerState.h22
-rw-r--r--src/gpu/gl/GrGLProgram.cpp96
-rw-r--r--src/gpu/gl/GrGLProgram.h17
-rw-r--r--src/gpu/gl/GrGLProgramStage.h11
-rw-r--r--src/gpu/gl/GrGpuGLShaders.cpp56
-rw-r--r--src/gpu/gl/GrGpuGLShaders.h4
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;