Hooks up the GrCustomStage/GrGLProgramStageFactory/GrGLProgramStage

classes from r3726 so they can be used. Does not implement any actual
effect stages.

Has one large known bug: if custom stages are provided, GrSamplerState
comparisons will break; this should preserve correct drawing, but decrease
performance - among other things, we'll break draw batching. To fix this
we'll need a RTTI system for GrCustomState objects, and we'll need to change
the GrSamplerState comparison from a memcmp to something that also does a
deep type-sensitive compare of any GrCustomState objects present.

http://codereview.appspot.com/6074043/



git-svn-id: http://skia.googlecode.com/svn/trunk@3742 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
tomhudson@google.com 2012-04-20 18:35:38 +00:00
Родитель 5a2e879ef8
Коммит 07eecdca3e
8 изменённых файлов: 185 добавлений и 27 удалений

Просмотреть файл

@ -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',

Просмотреть файл

@ -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:

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
@ -732,6 +743,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
@ -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");
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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() { }
};

Просмотреть файл

@ -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;
}
}

Просмотреть файл

@ -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;