Cleanup of shader building system

this is a huge refactor and cleanup of the gl shader building system in
Skia.  The entire shader building pipeline is now part of
GrGLProgramCreator, which takes a gp, and some fps, and creates a
program.  I added some subclasses of GrGLProgram to handle the
eccentricities of Nvpr/Nvpres.  Outside of the builders folder
and GrGLPrograms, this change is basically just a rename

solo gp

BUG=skia:

Committed: https://skia.googlesource.com/skia/+/fe1233c3f12f81bb675718516bbb32f72af726ec

Review URL: https://codereview.chromium.org/611653002
This commit is contained in:
joshualitt 2014-10-07 16:43:25 -07:00 committed by Commit bot
parent e6efd39a33
commit 47bb382830
45 changed files with 1717 additions and 2029 deletions

View File

@ -232,8 +232,6 @@
'<(skia_src_path)/gpu/gl/GrGLProgram.h',
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.h',
'<(skia_src_path)/gpu/gl/GrGLProgramEffects.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgramEffects.h',
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.h',
'<(skia_src_path)/gpu/gl/GrGLRenderTarget.cpp',
@ -258,17 +256,17 @@
'<(skia_src_path)/gpu/gl/GrGpuGL_program.cpp',
# Files for building GLSL shaders
'<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp',

View File

@ -92,7 +92,7 @@ public:
if (!fp->willUseInputColor()) {
fColorStages.reset();
}
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrProcessorStage, (fp));
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp));
return fp;
}
@ -104,7 +104,7 @@ public:
if (!fp->willUseInputColor()) {
fCoverageStages.reset();
}
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrProcessorStage, (fp));
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp));
return fp;
}

View File

@ -31,6 +31,8 @@ public:
fCoordChangeMatrixSet = false;
}
virtual ~GrProcessorStage() {}
GrProcessorStage(const GrProcessorStage& other) {
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
if (other.fCoordChangeMatrixSet) {
@ -147,11 +149,11 @@ public:
}
}
const GrProcessor* getProcessor() const { return fProc.get(); }
virtual const GrProcessor* getProcessor() const = 0;
void convertToPendingExec() { fProc.convertToPendingExec(); }
private:
protected:
bool fCoordChangeMatrixSet;
SkMatrix fCoordChangeMatrix;
GrProgramElementRef<const GrProcessor> fProc;
@ -161,18 +163,24 @@ class GrFragmentStage : public GrProcessorStage {
public:
GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
const GrFragmentProcessor* getFragmentProcessor() const {
return static_cast<const GrFragmentProcessor*>(this->getProcessor());
virtual const GrFragmentProcessor* getProcessor() const {
return static_cast<const GrFragmentProcessor*>(fProc.get());
}
typedef GrFragmentProcessor Processor;
typedef GrGLFragmentProcessor GLProcessor;
};
class GrGeometryStage : public GrProcessorStage {
public:
GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
const GrGeometryProcessor* getGeometryProcessor() const {
return static_cast<const GrGeometryProcessor*>(this->getProcessor());
virtual const GrGeometryProcessor* getProcessor() const {
return static_cast<const GrGeometryProcessor*>(fProc.get());
}
typedef GrGeometryProcessor Processor;
typedef GrGLGeometryProcessor GLProcessor;
};
#endif

View File

@ -9,7 +9,6 @@
#define GrTBackendProcessorFactory_DEFINED
#include "GrBackendProcessorFactory.h"
#include "gl/GrGLProgramEffects.h"
/**
* Implements GrBackendEffectFactory for a GrProcessor subclass as a singleton. This can be used by

View File

@ -18,7 +18,7 @@
#include "SkStrokeRec.h"
#include "SkTraceEvent.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
@ -528,7 +528,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -538,7 +538,7 @@ public:
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@ -565,7 +565,7 @@ public:
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
const GrShaderVar& inQuadEdge = geometryProcessor.cast<QuadEdgeEffect>().inQuadEdge();
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, inQuadEdge.c_str());
}

View File

@ -7,7 +7,7 @@
#include "GrAARectRenderer.h"
#include "GrGpu.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLGeometryProcessor.h"
#include "GrTBackendProcessorFactory.h"
@ -41,7 +41,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -55,10 +55,10 @@ public:
builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// TODO: compute all these offsets, spans, and scales in the VS
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
@ -167,7 +167,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -181,7 +181,7 @@ public:
&vsRectEdgeName, &fsRectEdgeName);
const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
// setup the varying for width/2+.5 and height/2+.5
@ -192,7 +192,7 @@ public:
vsWidthHeightName,
rectEffect.inWidthHeight().c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// TODO: compute all these offsets, spans, and scales in the VS
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);

View File

@ -266,7 +266,7 @@ bool GrDrawState::validateVertexAttribs() const {
if (this->hasGeometryProcessor()) {
const GrGeometryStage& stage = *this->getGeometryProcessor();
const GrGeometryProcessor* gp = stage.getGeometryProcessor();
const GrGeometryProcessor* gp = stage.getProcessor();
SkASSERT(gp);
// make sure that any attribute indices have the correct binding type, that the attrib
// type and effect's shader lang type are compatible, and that attributes shared by
@ -410,7 +410,7 @@ bool GrDrawState::hasSolidCoverage() const {
// Run through the coverage stages and see if the coverage will be all ones at the end.
if (this->hasGeometryProcessor()) {
const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
gp->computeInvariantOutput(&inout);
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
@ -436,13 +436,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
bool GrDrawState::willEffectReadDstColor() const {
if (!this->isColorWriteDisabled()) {
for (int s = 0; s < this->numColorStages(); ++s) {
if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
return true;
}
}
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
return true;
}
}

View File

@ -391,7 +391,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
SkASSERT(drawState.getRenderTarget());
if (drawState.hasGeometryProcessor()) {
const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor();
const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
int numTextures = gp->numTextures();
for (int t = 0; t < numTextures; ++t) {
GrTexture* texture = gp->texture(t);

View File

@ -222,7 +222,7 @@ void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
}
for (int i = 0; i < ds.numColorStages(); ++i) {
const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
if (!fp->willUseInputColor()) {
firstColorStage = i;
fInputColorIsUsed = false;
@ -270,10 +270,10 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
}
static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
if (stage.getFragmentProcessor()->willReadDstColor()) {
if (stage.getProcessor()->willReadDstColor()) {
*readsDst = true;
}
if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
if (stage.getProcessor()->willReadFragmentPosition()) {
*readsFragPosition = true;
}
}

View File

@ -7,7 +7,7 @@
#include "GrOvalRenderer.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
@ -92,7 +92,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -103,10 +103,10 @@ public:
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();;
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();;
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, circleEffect.inCircleEdge().c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName);
fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
if (circleEffect.isStroked()) {
@ -210,7 +210,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -224,7 +224,7 @@ public:
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsOffsetName,
ellipseEffect.inEllipseOffset().c_str());
@ -232,7 +232,7 @@ public:
vsBuilder->codeAppendf("%s = %s;", vsRadiiName, ellipseEffect.inEllipseRadii().c_str());
// for outer curve
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName);
fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
@ -359,7 +359,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -373,7 +373,7 @@ public:
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0",
&vsOffsetName0, &fsOffsetName0);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsOffsetName0,
ellipseEffect.inEllipseOffsets0().c_str());
const char *vsOffsetName1, *fsOffsetName1;
@ -382,7 +382,7 @@ public:
vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1,
ellipseEffect.inEllipseOffsets1().c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
// for outer curve

View File

@ -7,7 +7,7 @@
#include "GrBezierEffect.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
@ -17,7 +17,7 @@ class GrGLConicEffect : public GrGLGeometryProcessor {
public:
GrGLConicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -42,7 +42,7 @@ GrGLConicEffect::GrGLConicEffect(const GrBackendProcessorFactory& factory,
fEdgeType = ce.getEdgeType();
}
void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
void GrGLConicEffect::emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -55,10 +55,10 @@ void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
&vsName, &fsName);
const GrShaderVar& inConicCoeffs = geometryProcessor.cast<GrConicEffect>().inConicCoeffs();
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsName, inConicCoeffs.c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppend("float edgeAlpha;");
switch (fEdgeType) {
@ -171,7 +171,7 @@ class GrGLQuadEffect : public GrGLGeometryProcessor {
public:
GrGLQuadEffect(const GrBackendProcessorFactory&, const GrProcessor&);
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -196,7 +196,7 @@ GrGLQuadEffect::GrGLQuadEffect(const GrBackendProcessorFactory& factory,
fEdgeType = ce.getEdgeType();
}
void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
void GrGLQuadEffect::emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -206,11 +206,11 @@ void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inHairQuadEdge = geometryProcessor.cast<GrQuadEffect>().inHairQuadEdge();
vsBuilder->codeAppendf("%s = %s;", vsName, inHairQuadEdge.c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("float edgeAlpha;");
switch (fEdgeType) {
@ -309,7 +309,7 @@ class GrGLCubicEffect : public GrGLGeometryProcessor {
public:
GrGLCubicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -334,7 +334,7 @@ GrGLCubicEffect::GrGLCubicEffect(const GrBackendProcessorFactory& factory,
fEdgeType = ce.getEdgeType();
}
void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
void GrGLCubicEffect::emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -346,11 +346,11 @@ void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
&vsName, &fsName, GrGLShaderVar::kHigh_Precision);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inCubicCoeffs = geometryProcessor.cast<GrCubicEffect>().inCubicCoeffs();
vsBuilder->codeAppendf("%s = %s;", vsName, inCubicCoeffs.c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
GrGLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, GrGLShaderVar::kHigh_Precision);

View File

@ -6,7 +6,7 @@
*/
#include "GrCustomCoordsTextureEffect.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h"
@ -19,7 +19,7 @@ public:
GrGLCustomCoordsTextureEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -36,11 +36,11 @@ public:
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
fsCoordName = fsVaryingNamePtr;
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords();
vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, inTextureCoords.c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t%s = ", outputColor);
fsBuilder->appendTextureLookupAndModulate(inputColor,
samplers[0],

View File

@ -10,7 +10,7 @@
#include "../GrAARectRenderer.h"
#include "GrGeometryProcessor.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLSL.h"
@ -482,7 +482,7 @@ class GLDashingCircleEffect : public GrGLGeometryProcessor {
public:
GLDashingCircleEffect(const GrBackendProcessorFactory&, const GrProcessor&);
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -510,7 +510,7 @@ GLDashingCircleEffect::GLDashingCircleEffect(const GrBackendProcessorFactory& fa
fPrevIntervalLength = SK_ScalarMax;
}
void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
void GLDashingCircleEffect::emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -529,11 +529,11 @@ void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
const char *vsCoordName, *fsCoordName;
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dce.inCoord().c_str());
// transforms all points so that we can compare them to our test circle
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
fsCoordName, fsCoordName, paramName, paramName);
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
@ -694,7 +694,7 @@ class GLDashingLineEffect : public GrGLGeometryProcessor {
public:
GLDashingLineEffect(const GrBackendProcessorFactory&, const GrProcessor&);
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -721,7 +721,7 @@ GLDashingLineEffect::GLDashingLineEffect(const GrBackendProcessorFactory& factor
fPrevIntervalLength = SK_ScalarMax;
}
void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
void GLDashingLineEffect::emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -745,11 +745,11 @@ void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
const char *vsCoordName, *fsCoordName;
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, de.inCoord().c_str());
// transforms all points so that we can compare them to our test rect
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
fsCoordName, fsCoordName, intervalName, intervalName);
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);

View File

@ -6,7 +6,7 @@
*/
#include "GrDistanceFieldTextureEffect.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h"
@ -40,7 +40,7 @@ public:
#endif
{}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -51,7 +51,7 @@ public:
geometryProcessor.cast<GrDistanceFieldTextureEffect>();
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@ -61,7 +61,7 @@ public:
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
@ -267,7 +267,7 @@ public:
: INHERITED(factory)
, fTextureSize(SkISize::Make(-1, -1)) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& effect,
const GrProcessorKey& key,
const char* outputColor,
@ -278,7 +278,7 @@ public:
effect.cast<GrDistanceFieldNoGammaTextureEffect>();
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@ -288,7 +288,7 @@ public:
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
@ -439,7 +439,7 @@ public:
, fTextureSize(SkISize::Make(-1,-1))
, fTextColor(GrColor_ILLEGAL) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
@ -456,7 +456,7 @@ public:
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
@ -465,7 +465,7 @@ public:
kVec3f_GrSLType, "TextureSize",
&textureSizeUniName);
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));

View File

@ -24,7 +24,7 @@ public:
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
virtual void emitCode(GrGLFullProgramBuilder* builder,
virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,

View File

@ -9,9 +9,8 @@
#define GrGLProcessor_DEFINED
#include "GrBackendProcessorFactory.h"
#include "GrGLProgramEffects.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"
#include "GrGLProgramDataManager.h"
#include "GrTextureAccess.h"
/** @file
This file contains specializations for OpenGL of the shader stages declared in

View File

@ -7,8 +7,6 @@
#include "GrGLProgram.h"
#include "builders/GrGLFullProgramBuilder.h"
#include "builders/GrGLFragmentOnlyProgramBuilder.h"
#include "GrAllocator.h"
#include "GrProcessor.h"
#include "GrCoordTransform.h"
@ -23,45 +21,58 @@
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]) {
SkAutoTDelete<GrGLProgramBuilder> builder;
if (desc.getHeader().fUseFragShaderOnly) {
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(gpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::FixedFunction_TexturingMode);
SkASSERT(NULL == geometryProcessor);
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc)));
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
bool useExplicitLocalCoords,
int transformIdx) {
const GrCoordTransform& coordTransform =
processorStage.getProcessor()->coordTransform(transformIdx);
SkMatrix combined;
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
// If we have explicit local coords then we shouldn't need a coord change.
const SkMatrix& ccm =
useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
combined.setConcat(coordTransform.getMatrix(), ccm);
} else {
builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc)));
combined = coordTransform.getMatrix();
}
if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
SkASSERT(0 != builder->getProgramID());
return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
if (coordTransform.reverseY()) {
// combined.postScale(1,-1);
// combined.postTranslate(0,1);
combined.set(SkMatrix::kMSkewY,
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
combined.set(SkMatrix::kMScaleY,
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
combined.set(SkMatrix::kMTransY,
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
}
return NULL;
return combined;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const GrGLProgramBuilder& builder)
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledProcessors* geometryProcessor,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors)
: fColor(GrColor_ILLEGAL)
, fCoverage(GrColor_ILLEGAL)
, fDstCopyTexUnit(-1)
, fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
, fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
, fColorEffects(SkRef(builder.getColorEffects()))
, fCoverageEffects(SkRef(builder.getCoverageEffects()))
, fProgramID(builder.getProgramID())
, fHasVertexShader(builder.hasVertexShader())
, fTexCoordSetCnt(builder.getTexCoordSetCount())
, fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
, fGeometryProcessor(SkSafeRef(geometryProcessor))
, fColorEffects(SkRef(colorProcessors))
, fCoverageEffects(SkRef(coverageProcessors))
, fDesc(desc)
, fGpu(gpu)
, fProgramDataManager(gpu, this, builder) {
, fProgramDataManager(gpu, uniforms) {
this->initSamplerUniforms();
}
@ -83,12 +94,42 @@ void GrGLProgram::initSamplerUniforms() {
fDstCopyTexUnit = texUnitIdx++;
}
if (fGeometryProcessor.get()) {
fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
}
fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
this->initSamplers(fColorEffects.get(), &texUnitIdx);
this->initSamplers(fCoverageEffects.get(), &texUnitIdx);
}
void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) {
int numEffects = ip->fGLProcessors.count();
SkASSERT(numEffects == ip->fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e];
int numSamplers = samplers.count();
for (int s = 0; s < numSamplers; ++s) {
SkASSERT(samplers[s].fUniform.isValid());
fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
samplers[s].fTextureUnit = (*texUnitIdx)++;
}
}
}
void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip,
const GrProcessor& processor,
int effectIdx) {
const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx];
int numSamplers = samplers.count();
SkASSERT(numSamplers == processor.numTextures());
for (int s = 0; s < numSamplers; ++s) {
SkASSERT(samplers[s].fTextureUnit >= 0);
const GrTextureAccess& textureAccess = processor.textureAccess(s);
fGpu->bindTexture(samplers[s].fTextureUnit,
textureAccess.getParams(),
static_cast<GrGLTexture*>(textureAccess.getTexture()));
}
}
///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::setData(const GrOptDrawState& optState,
@ -126,21 +167,39 @@ void GrGLProgram::setData(const GrOptDrawState& optState,
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
}
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
if (fGeometryProcessor.get()) {
SkASSERT(geometryProcessor);
fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
}
fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
// PathTexGen state applies to the the fixed function vertex shader. For
// custom shaders, it's ignored, so we don't need to change the texgen
// settings in that case.
if (!fHasVertexShader) {
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
// Some of GrGLProgram subclasses need to update state here
this->didSetData(drawType);
}
void GrGLProgram::setTransformData(const GrProcessorStage& processor,
int effectIdx,
GrGLInstalledProcessors* ip) {
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
transforms[t].fCurrentValue = matrix;
}
}
}
void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
}
void GrGLProgram::setColor(const GrOptDrawState& optState,
GrColor color,
SharedGLState* sharedState) {
@ -220,22 +279,25 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState,
void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrOptDrawState& optState) {
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->height()) {
fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
SkIntToScalar(optState.getRenderTarget()->height()));
}
// call subclasses to set the actual view matrix
this->onSetMatrixAndRenderTargetHeight(drawType, optState);
}
void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrOptDrawState& optState) {
const GrRenderTarget* rt = optState.getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
SkIntToScalar(size.fHeight));
}
if (GrGpu::IsPathRenderingDrawType(drawType)) {
fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = optState.getViewMatrix();
@ -251,3 +313,115 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors,
coverageProcessors) {
}
void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrOptDrawState& optState) {
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
const GrRenderTarget* rt = optState.getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
}
/////////////////////////////////////////////////////////////////////////////////////////
GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors,
const SeparableVaryingInfoArray& separableVaryings)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
coverageProcessors) {
int count = separableVaryings.count();
fVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
Varying& varying = fVaryings[i];
const SeparableVaryingInfo& builderVarying = separableVaryings[i];
SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
SkDEBUGCODE(
varying.fType = builderVarying.fVariable.getType();
);
varying.fLocation = builderVarying.fLocation;
}
}
void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
}
void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor,
int effectIdx,
GrGLInstalledProcessors* ip) {
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
transforms[t].fCurrentValue = transform;
const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()];
SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType);
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
transform);
}
}
//////////////////////////////////////////////////////////////////////////////////////
GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors,
int texCoordSetCnt)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
coverageProcessors)
, fTexCoordSetCnt(texCoordSetCnt) {
}
void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
}
void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage,
int effectIdx,
GrGLInstalledProcessors* ip) {
// We've hidden the texcoord index in the first entry of the transforms array for each effect
int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle();
int numTransforms = processorStage.getProcessor()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
const SkMatrix& transform = get_transform_matrix(processorStage, false, t);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
if (processorStage.isPerspectiveCoordTransform(t, false)) {
components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
}
}

View File

@ -10,6 +10,7 @@
#define GrGLProgram_DEFINED
#include "builders/GrGLProgramBuilder.h"
#include "builders/GrGLNvprProgramBuilder.h"
#include "GrDrawState.h"
#include "GrGLContext.h"
#include "GrGLProgramDesc.h"
@ -21,7 +22,7 @@
#include "SkXfermode.h"
class GrGLProcessor;
class GrGLProgramEffects;
class GrGLInstalledProcessors;
class GrGLProgramBuilder;
/**
@ -39,13 +40,6 @@ public:
typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles;
static GrGLProgram* Create(GrGpuGL* gpu,
const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]);
virtual ~GrGLProgram();
/**
@ -60,7 +54,10 @@ public:
*/
GrGLuint programID() const { return fProgramID; }
bool hasVertexShader() const { return fHasVertexShader; }
/*
* The base class always has a vertex shader, only the NVPR variants may omit a vertex shader
*/
virtual bool hasVertexShader() const { return true; }
/**
* Some GL state that is relevant to programs is not stored per-program. In particular color
@ -161,15 +158,22 @@ public:
const GrDeviceCoordTexture* dstCopy, // can be NULL
SharedGLState*);
private:
protected:
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
GrGLProgram(GrGpuGL*,
const GrGLProgramDesc&,
const GrGLProgramBuilder&);
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledProcessors* geometryProcessor,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors);
// Sets the texture units for samplers.
void initSamplerUniforms();
void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
// Helper for setData(). Makes GL calls to specify the initial color when there is not
// per-vertex colors.
@ -179,29 +183,134 @@ private:
// per-vertex coverages.
void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
template <class ProcessorStage>
void setData(const ProcessorStage* effectStages[],
GrGLInstalledProcessors* installedProcessors) {
int numEffects = installedProcessors->fGLProcessors.count();
SkASSERT(numEffects == installedProcessors->fTransforms.count());
SkASSERT(numEffects == installedProcessors->fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
const GrProcessor& effect = *effectStages[e]->getProcessor();
installedProcessors->fGLProcessors[e]->setData(fProgramDataManager, effect);
this->setTransformData(*effectStages[e], e, installedProcessors);
this->bindTextures(installedProcessors, effect, e);
}
}
virtual void setTransformData(const GrProcessorStage& effectStage,
int effectIdx,
GrGLInstalledProcessors* pe);
void bindTextures(const GrGLInstalledProcessors*, const GrProcessor&, int effectIdx);
/*
* Legacy NVPR needs a hook here to flush path tex gen settings.
* TODO when legacy nvpr is removed, remove this call.
*/
virtual void didSetData(GrGpu::DrawType);
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&);
void setMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
// these reflect the current values of uniforms (GL uniform values travel with program)
MatrixState fMatrixState;
GrColor fColor;
GrColor fCoverage;
int fDstCopyTexUnit;
MatrixState fMatrixState;
GrColor fColor;
GrColor fCoverage;
int fDstCopyTexUnit;
BuiltinUniformHandles fBuiltinUniformHandles;
GrGLuint fProgramID;
BuiltinUniformHandles fBuiltinUniformHandles;
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
GrGLuint fProgramID;
bool fHasVertexShader;
int fTexCoordSetCnt;
// the installed effects
SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
GrGLProgramDesc fDesc;
GrGpuGL* fGpu;
GrGLProgramDesc fDesc;
GrGpuGL* fGpu;
GrGLProgramDataManager fProgramDataManager;
GrGLProgramDataManager fProgramDataManager;
friend class GrGLProgramBuilder;
typedef SkRefCnt INHERITED;
};
/*
* Below are slight specializations of the program object for the different types of programs
* The default GrGL programs consist of at the very least a vertex and fragment shader.
* Legacy Nvpr only has a fragment shader, 1.3+ Nvpr ignores the vertex shader, but both require
* specialized methods for setting transform data. Both types of NVPR also require setting the
* projection matrix through a special function call
*/
class GrGLNvprProgramBase : public GrGLProgram {
protected:
GrGLNvprProgramBase(GrGpuGL*,
const GrGLProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors);
virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
typedef GrGLProgram INHERITED;
};
class GrGLNvprProgram : public GrGLNvprProgramBase {
public:
virtual bool hasVertexShader() const SK_OVERRIDE { return true; }
private:
typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo;
typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray;
GrGLNvprProgram(GrGpuGL*,
const GrGLProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors,
const SeparableVaryingInfoArray& separableVaryings);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrProcessorStage&,
int effectIdx,
GrGLInstalledProcessors*) SK_OVERRIDE;
struct Varying {
GrGLint fLocation;
SkDEBUGCODE(
GrSLType fType;
);
};
SkTArray<Varying, true> fVaryings;
friend class GrGLNvprProgramBuilder;
typedef GrGLNvprProgramBase INHERITED;
};
class GrGLLegacyNvprProgram : public GrGLNvprProgramBase {
public:
virtual bool hasVertexShader() const SK_OVERRIDE { return false; }
private:
GrGLLegacyNvprProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors,
int texCoordSetCnt);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrProcessorStage&,
int effectIdx,
GrGLInstalledProcessors*) SK_OVERRIDE;
int fTexCoordSetCnt;
friend class GrGLLegacyNvprProgramBuilder;
typedef GrGLNvprProgramBase INHERITED;
};
#endif

View File

@ -5,9 +5,7 @@
* found in the LICENSE file.
*/
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLPathRendering.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "gl/GrGpuGL.h"
#include "SkMatrix.h"
@ -16,16 +14,13 @@
SkASSERT(arrayCount <= uni.fArrayCount || \
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
GrGLProgram* program,
const GrGLProgramBuilder& builder)
: fGpu(gpu),
fProgram(program) {
int count = builder.getUniformInfos().count();
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoArray& uniforms)
: fGpu(gpu) {
int count = uniforms.count();
fUniforms.push_back_n(count);
for (int i = 0; i < count; i++) {
Uniform& uniform = fUniforms[i];
const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i];
const UniformInfo& builderUniform = uniforms[i];
SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
builderUniform.fVariable.getArrayCount() > 0);
SkDEBUGCODE(
@ -38,26 +33,13 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
uniform.fVSLocation = builderUniform.fLocation;
} else {
uniform.fVSLocation = kUnusedUniform;
}
}
if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) {
uniform.fFSLocation = builderUniform.fLocation;
} else {
uniform.fFSLocation = kUnusedUniform;
}
}
count = builder.getSeparableVaryingInfos().count();
fVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
Varying& varying = fVaryings[i];
const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
builder.getSeparableVaryingInfos()[i];
SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
SkDEBUGCODE(
varying.fType = builderVarying.fVariable.getType();
);
varying.fLocation = builderVarying.fLocation;
}
}
void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
@ -276,14 +258,3 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix
};
this->setMatrix3f(u, mt);
}
void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
unsigned components,
const SkMatrix& matrix) const {
const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
matrix);
}

View File

@ -56,22 +56,18 @@ public:
friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
};
class VaryingHandle : public ShaderResourceHandle {
public:
/** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder.
* The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/
static VaryingHandle CreateFromSeparableVaryingIndex(int i) {
return VaryingHandle(i);
}
VaryingHandle() { }
bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; }
private:
VaryingHandle(int value) : ShaderResourceHandle(value) { }
int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
struct UniformInfo {
GrGLShaderVar fVariable;
uint32_t fVisibility;
GrGLint fLocation;
};
GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&);
// This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
// after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
// name strings. Otherwise, we'd have to hand out copies.
typedef GrTAllocator<UniformInfo> UniformInfoArray;
GrGLProgramDataManager(GrGpuGL*, const UniformInfoArray&);
/** Functions for uploading uniform values. The varities ending in v can be used to upload to an
* array of uniforms. arrayCount must be <= the array count of the uniform.
@ -95,10 +91,6 @@ public:
// convenience method for uploading a SkMatrix to a 3x3 matrix uniform
void setSkMatrix(UniformHandle, const SkMatrix&) const;
void setProgramPathFragmentInputTransform(VaryingHandle i,
unsigned components,
const SkMatrix& matrix) const;
private:
enum {
kUnusedUniform = -1,
@ -112,19 +104,10 @@ private:
int fArrayCount;
);
};
struct Varying {
GrGLint fLocation;
SkDEBUGCODE(
GrSLType fType;
);
};
SkTArray<Uniform, true> fUniforms;
SkTArray<Varying, true> fVaryings;
GrGpuGL* fGpu;
GrGLProgram* fProgram;
typedef SkRefCnt INHERITED;
};
#endif

View File

@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/builders/GrGLFragmentShaderBuilder.h"
#include "GrGLProgramDesc.h"
#include "GrBackendProcessorFactory.h"
#include "GrProcessor.h"
@ -178,7 +178,7 @@ bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
if (NULL == key) {
return false;
}
uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor());
uint32_t attribKey = gen_attrib_key(stage.getProcessor());
// Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
// don't fit.
@ -348,15 +348,16 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
dstCopyTexture = dstCopy->texture();
}
header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
gpu->glCaps());
gpu->glCaps());
SkASSERT(0 != header->fDstReadKey);
} else {
header->fDstReadKey = 0;
}
if (optState.readsFragPosition()) {
header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
optState.getRenderTarget(), gpu->glCaps());
header->fFragPosKey =
GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
gpu->glCaps());
} else {
header->fFragPosKey = 0;
}

View File

@ -247,11 +247,10 @@ private:
// visible to GrGLProcessors. Then make public accessors as necessary and remove friends.
friend class GrGLProgram;
friend class GrGLProgramBuilder;
friend class GrGLFullProgramBuilder;
friend class GrGLFragmentOnlyProgramBuilder;
friend class GrGLVertexShaderBuilder;
friend class GrGLLegacyNvprProgramBuilder;
friend class GrGLVertexBuilder;
friend class GrGLFragmentShaderBuilder;
friend class GrGLGeometryShaderBuilder;
friend class GrGLGeometryBuilder;
};
#endif

View File

@ -1,204 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLProgramEffects.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLPathRendering.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGpuGL.h"
typedef GrGLProcessor::TransformedCoords TransformedCoords;
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
typedef GrGLProcessor::TextureSampler TextureSampler;
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
namespace {
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
SkMatrix get_transform_matrix(const GrProcessorStage& effectStage,
bool useExplicitLocalCoords,
int transformIdx) {
const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(transformIdx);
SkMatrix combined;
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
// If we have explicit local coords then we shouldn't need a coord change.
const SkMatrix& ccm =
useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
combined.setConcat(coordTransform.getMatrix(), ccm);
} else {
combined = coordTransform.getMatrix();
}
if (coordTransform.reverseY()) {
// combined.postScale(1,-1);
// combined.postTranslate(0,1);
combined.set(SkMatrix::kMSkewY,
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
combined.set(SkMatrix::kMScaleY,
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
combined.set(SkMatrix::kMTransY,
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
}
return combined;
}
}
////////////////////////////////////////////////////////////////////////////////
GrGLProgramEffects::~GrGLProgramEffects() {
int numEffects = fGLProcessors.count();
for (int e = 0; e < numEffects; ++e) {
SkDELETE(fGLProcessors[e]);
}
}
void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
int numEffects = fGLProcessors.count();
SkASSERT(numEffects == fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
SkTArray<Sampler, true>& samplers = fSamplers[e];
int numSamplers = samplers.count();
for (int s = 0; s < numSamplers; ++s) {
SkASSERT(samplers[s].fUniform.isValid());
programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
samplers[s].fTextureUnit = (*texUnitIdx)++;
}
}
}
void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrProcessor& effect, int effectIdx) {
const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
int numSamplers = samplers.count();
SkASSERT(numSamplers == effect.numTextures());
for (int s = 0; s < numSamplers; ++s) {
SkASSERT(samplers[s].fTextureUnit >= 0);
const GrTextureAccess& textureAccess = effect.textureAccess(s);
gpu->bindTexture(samplers[s].fTextureUnit,
textureAccess.getParams(),
static_cast<GrGLTexture*>(textureAccess.getTexture()));
}
}
////////////////////////////////////////////////////////////////////////////////
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
GrGpu::DrawType drawType,
const GrGLProgramDataManager& programDataManager,
const GrGeometryStage* effectStages) {
SkASSERT(1 == fGLProcessors.count());
SkASSERT(1 == fTransforms.count());
SkASSERT(1 == fSamplers.count());
this->setDataInternal(gpu, drawType, programDataManager, *effectStages, 0);
}
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
GrGpu::DrawType drawType,
const GrGLProgramDataManager& programDataManager,
const GrFragmentStage* effectStages[]) {
int numEffects = fGLProcessors.count();
SkASSERT(numEffects == fTransforms.count());
SkASSERT(numEffects == fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
this->setDataInternal(gpu, drawType, programDataManager, *effectStages[e], e);
}
}
void GrGLVertexProgramEffects::setDataInternal(GrGpuGL* gpu,
GrGpu::DrawType drawType,
const GrGLProgramDataManager& programDataManager,
const GrProcessorStage& effectStage,
int index) {
const GrProcessor& effect = *effectStage.getProcessor();
fGLProcessors[index]->setData(programDataManager, effect);
if (GrGpu::IsPathRenderingDrawType(drawType)) {
this->setPathTransformData(gpu, programDataManager, effectStage, index);
} else {
this->setTransformData(gpu, programDataManager, effectStage, index);
}
this->bindTextures(gpu, effect, index);
}
void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
const GrGLProgramDataManager& pdman,
const GrProcessorStage& effectStage,
int effectIdx) {
SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
pdman.setSkMatrix(transforms[t].fHandle, matrix);
transforms[t].fCurrentValue = matrix;
}
}
}
void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
const GrGLProgramDataManager& pdman,
const GrProcessorStage& effectStage,
int effectIdx) {
SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
transforms[t].fCurrentValue = transform;
switch (transforms[t].fType) {
case kVec2f_GrSLType:
pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
break;
case kVec3f_GrSLType:
pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
break;
default:
SkFAIL("Unexpected matrix type.");
}
}
}
////////////////////////////////////////////////////////////////////////////////
void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
GrGpu::DrawType,
const GrGLProgramDataManager& pdman,
const GrFragmentStage* effectStages[]) {
int numEffects = fGLProcessors.count();
SkASSERT(numEffects == fTransforms.count());
SkASSERT(numEffects == fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
const GrProcessorStage& effectStage = *effectStages[e];
const GrProcessor& effect = *effectStage.getProcessor();
fGLProcessors[e]->setData(pdman, effect);
this->setPathTexGenState(gpu, effectStage, e);
this->bindTextures(gpu, effect, e);
}
}
void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
const GrProcessorStage& effectStage,
int effectIdx) {
int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
int numTransforms = effectStage.getProcessor()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
if (effectStage.isPerspectiveCoordTransform(t, false)) {
components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
gpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
}
}

View File

@ -1,201 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLProgramEffects_DEFINED
#define GrGLProgramEffects_DEFINED
#include "GrBackendProcessorFactory.h"
#include "GrGLProgramDataManager.h"
#include "GrGpu.h"
#include "GrTexture.h"
#include "GrTextureAccess.h"
class GrProcessor;
class GrProcessorStage;
class GrGLVertexProgramEffectsBuilder;
class GrGLProgramBuilder;
class GrGLFullProgramBuilder;
class GrGLFragmentOnlyProgramBuilder;
/**
* This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
* and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
* state and shader uniforms.
*/
class GrGLProgramEffects : public SkRefCnt {
public:
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
virtual ~GrGLProgramEffects();
/**
* Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
* available unit to *texUnitIdx when it returns.
*/
void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
/**
* Calls setData() on each effect, and sets their transformation matrices and texture bindings.
*/
virtual void setData(GrGpuGL*,
GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrGeometryStage* effectStages) {
SkFAIL("For geometry processor only");
}
virtual void setData(GrGpuGL*,
GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrFragmentStage* effectStages[]) = 0;
protected:
GrGLProgramEffects(int reserveCount)
: fGLProcessors(reserveCount)
, fSamplers(reserveCount) {
}
/**
* Helper for setData(). Binds all the textures for an effect.
*/
void bindTextures(GrGpuGL*, const GrProcessor&, int effectIdx);
struct Sampler {
SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
UniformHandle fUniform;
int fTextureUnit;
};
/*
* Helpers for shader builders to build up program effects objects alongside shader code
*/
void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
SkTArray<GrGLProcessor*> fGLProcessors;
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
private:
friend class GrGLProgramBuilder;
friend class GrGLFullProgramBuilder;
friend class GrGLFragmentOnlyShaderBuilder;
typedef SkRefCnt INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
/**
* This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
*/
class GrGLVertexProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrGeometryStage* effectStages) SK_OVERRIDE;
virtual void setData(GrGpuGL*,
GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrFragmentStage* effectStages[]) SK_OVERRIDE;
private:
GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
: INHERITED(reserveCount)
, fTransforms(reserveCount)
, fHasExplicitLocalCoords(explicitLocalCoords) {
}
struct Transform {
Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
UniformHandle fHandle;
SkMatrix fCurrentValue;
};
struct PathTransform {
PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
VaryingHandle fHandle;
SkMatrix fCurrentValue;
GrSLType fType;
};
/*
* These functions are used by the builders to build up program effects along side the shader
* code itself
*/
SkSTArray<2, Transform, true>& addTransforms() { return fTransforms.push_back(); }
SkTArray<PathTransform, true>& addPathTransforms() { return fPathTransforms.push_back(); }
/**
* Helper for setData(). Sets all the transform matrices for an effect.
*/
void setDataInternal(GrGpuGL* gpu,
GrGpu::DrawType drawType,
const GrGLProgramDataManager& programDataManager,
const GrProcessorStage& effectStage,
int index);
void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrProcessorStage&,
int effectIdx);
void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&,
const GrProcessorStage&, int effectIdx);
SkTArray<SkSTArray<2, Transform, true> > fTransforms;
SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
bool fHasExplicitLocalCoords;
friend class GrGLFullProgramBuilder;
typedef GrGLProgramEffects INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
/**
* This is a GrGLProgramEffects implementation that does coord transforms with
* the the NV_path_rendering PathTexGen functionality.
*/
class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrFragmentStage* effectStages[]) SK_OVERRIDE;
private:
GrGLPathTexGenProgramEffects(int reserveCount)
: INHERITED(reserveCount)
, fTransforms(reserveCount) {
}
/**
* Helper for setData(). Sets the PathTexGen state for each transform in an effect.
*/
void setPathTexGenState(GrGpuGL*, const GrProcessorStage&, int effectIdx);
struct Transforms {
Transforms(int texCoordIndex)
: fTexCoordIndex(texCoordIndex) {}
int fTexCoordIndex;
};
/*
* Helper for fragment only shader builder to build up the program effects alongside the shader
*/
void addTransforms(int coordIndex) {
fTransforms.push_back(Transforms(coordIndex));
}
SkTArray<Transforms> fTransforms;
friend class GrGLFragmentOnlyProgramBuilder;
typedef GrGLProgramEffects INHERITED;
};
#endif

View File

@ -179,8 +179,9 @@ private:
~ProgramCache();
void abandon();
GrGLProgram* getProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
GrGLProgram* getProgram(const GrOptDrawState&,
const GrGLProgramDesc&,
DrawType,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]);

View File

@ -7,6 +7,7 @@
#include "GrGpuGL.h"
#include "builders/GrGLProgramBuilder.h"
#include "GrProcessor.h"
#include "GrGLProcessor.h"
#include "GrGLPathRendering.h"
@ -92,6 +93,7 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
DrawType type,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]) {
@ -129,8 +131,9 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
GrGLProgram* program = GrGLProgram::Create(fGpu, optState, desc, geometryProcessor,
colorStages, coverageStages);
GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
geometryProcessor, colorStages,
coverageStages, fGpu);
if (NULL == program) {
return NULL;
}
@ -254,6 +257,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
desc,
type,
geometryProcessor,
colorStages.begin(),
coverageStages.begin()));

View File

@ -1,107 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLFragmentOnlyProgramBuilder.h"
#include "../GrGpuGL.h"
GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: INHERITED(gpu, optState, desc) {
SkASSERT(desc.getHeader().fUseFragShaderOnly);
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}
int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
int firstFreeCoordSet = fTexCoordSetCnt;
fTexCoordSetCnt += count;
SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
return firstFreeCoordSet;
}
void
GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) {
///////////////////////////////////////////////////////////////////////////
// emit the per-effect code for both color and coverage effects
EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
this->desc().numColorEffects(),
colorKeyProvider,
inputColor));
EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
this->desc().numCoverageEffects(),
coverageKeyProvider,
inputCoverage));
}
GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::onCreateAndEmitEffects(
const GrFragmentStage* effectStages[], int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
fProgramEffects.reset(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (effectCnt)));
this->INHERITED::createAndEmitEffects(effectStages,
effectCnt,
keyProvider,
inOutFSColor);
return fProgramEffects.detach();
}
void GrGLFragmentOnlyProgramBuilder::emitEffect(const GrProcessorStage& stage,
const GrProcessorKey& key,
const char* outColor,
const char* inColor,
int stageIndex) {
SkASSERT(fProgramEffects.get());
const GrProcessor& effect = *stage.getProcessor();
SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
this->setupPathTexGen(stage, &coords);
this->emitSamplers(effect, &samplers);
SkASSERT(fEffectEmitter);
GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
fProgramEffects->addEffect(glEffect);
GrGLFragmentShaderBuilder* fsBuilder = this->getFragmentShaderBuilder();
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
fsBuilder->codeAppend(openBrace.c_str());
fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
fsBuilder->codeAppend("\t}\n");
}
void GrGLFragmentOnlyProgramBuilder::setupPathTexGen(
const GrProcessorStage& effectStage, GrGLProcessor::TransformedCoordsArray* outCoords) {
int numTransforms = effectStage.getProcessor()->numTransforms();
int texCoordIndex = this->addTexCoordSets(numTransforms);
fProgramEffects->addTransforms(texCoordIndex);
SkString name;
for (int t = 0; t < numTransforms; ++t) {
GrSLType type =
effectStage.isPerspectiveCoordTransform(t, false) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLFragmentOnlyProgramBuilder_DEFINED
#define GrGLFragmentOnlyProgramBuilder_DEFINED
#include "GrGLProgramBuilder.h"
class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
public:
GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
int addTexCoordSets(int count);
private:
virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor);
virtual void emitEffect(const GrProcessorStage& stage,
const GrProcessorKey& key,
const char* outColor,
const char* inColor,
int stageIndex) SK_OVERRIDE;
/**
* Helper for emitEffect(). Allocates texture units from the builder for each transform in an
* effect. The transforms all use adjacent texture units. They either use two or three of the
* coordinates at a given texture unit, depending on if they need perspective interpolation.
* The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
* types are appended to the TransformedCoordsArray* object, which is in turn passed to the
* effect's emitCode() function.
*/
void setupPathTexGen(const GrProcessorStage&, GrGLProcessor::TransformedCoordsArray*);
virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
typedef GrGLProgramBuilder INHERITED;
};
#endif

View File

@ -10,15 +10,15 @@
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
namespace {
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
static const char kDstCopyColorName[] = "_dstColor";
inline const char* declared_color_output_name() { return "fsColorOut"; }
inline const char* dual_source_output_name() { return "dualSourceOut"; }
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
static const char* declared_color_output_name() { return "fsColorOut"; }
static const char* dual_source_output_name() { return "dualSourceOut"; }
static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
GrGLStandard standard,
SkString* str) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
@ -40,10 +40,10 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
}
}
}
}
GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
const GrTexture* dstCopy, const GrGLCaps& caps) {
GrGLFragmentShaderBuilder::DstReadKey
GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
const GrGLCaps& caps) {
uint32_t key = kYesDstRead_DstReadKeyBit;
if (caps.fbFetchSupport()) {
return key;
@ -60,8 +60,9 @@ GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
return static_cast<DstReadKey>(key);
}
GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
const GrRenderTarget* dst, const GrGLCaps&) {
GrGLFragmentShaderBuilder::FragPosKey
GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
const GrGLCaps&) {
if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
return kTopLeftFragPosRead_FragPosKey;
} else {
@ -75,33 +76,9 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
, fHasCustomColorOutput(false)
, fHasSecondaryOutput(false)
, fSetupFragPosition(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
}
const char* GrGLFragmentShaderBuilder::dstColor() {
if (fProgramBuilder->fCodeStage.inStageCode()) {
const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor();
// TODO GPs can't read dst color, and full program builder only returns a pointer to the
// base fragment shader builder which does not have this function. Unfortunately,
// the code stage class only has a GrProcessor pointer so this is required for the time
// being
if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) {
SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor "
"did not request access.");
return "";
}
}
GrGpuGL* gpu = fProgramBuilder->gpu();
if (gpu->glCaps().fbFetchSupport()) {
this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
gpu->glCaps().fbFetchExtensionString());
return gpu->glCaps().fbFetchColorName();
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
return kDstCopyColorName;
} else {
return "";
}
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
, fHasReadDstColor(false)
, fHasReadFragmentPosition(false) {
}
bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
@ -140,15 +117,7 @@ SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
}
const char* GrGLFragmentShaderBuilder::fragmentPosition() {
GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
if (cs->inStageCode()) {
const GrProcessor* effect = cs->effectStage()->getProcessor();
if (!effect->willReadFragmentPosition()) {
SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor "
"did not request access.");
return "";
}
}
fHasReadFragmentPosition = true;
GrGpuGL* gpu = fProgramBuilder->gpu();
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
@ -175,16 +144,15 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
static const char* kCoordName = "fragCoordYDown";
if (!fSetupFragPosition) {
// temporarily change the stage index because we're inserting non-stage code.
GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
const char* rtHeightName;
fProgramBuilder->fUniformHandles.fRTHeightUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType,
"RTHeight",
&rtHeightName);
kFloat_GrSLType,
"RTHeight",
&rtHeightName);
// Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
// causes programs to fail to link. Making this function return a vec2() didn't fix the
@ -198,24 +166,133 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
}
}
void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
const char* name,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision) {
fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
if (fsInName) {
*fsInName = name;
const char* GrGLFragmentShaderBuilder::dstColor() {
fHasReadDstColor = true;
GrGpuGL* gpu = fProgramBuilder->gpu();
if (gpu->glCaps().fbFetchSupport()) {
this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
gpu->glCaps().fbFetchExtensionString());
return gpu->glCaps().fbFetchColorName();
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
return kDstCopyColorName;
} else {
return "";
}
}
void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
GrGpuGL* gpu = fProgramBuilder->gpu();
if (fHasCustomColorOutput) {
GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
const char* dstCopyTopLeftName;
const char* dstCopyCoordScaleName;
const char* dstCopySamplerName;
uint32_t configMask;
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) {
configMask = kA_GrColorComponentFlag;
} else {
configMask = kRGBA_GrColorComponentFlags;
}
if (fHasSecondaryOutput) {
GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kSampler2D_GrSLType,
"DstCopySampler",
&dstCopySamplerName);
fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec2f_GrSLType,
"DstCopyUpperLeft",
&dstCopyTopLeftName);
fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec2f_GrSLType,
"DstCopyCoordScale",
&dstCopyCoordScaleName);
const char* fragPos = this->fragmentPosition();
this->codeAppend("// Read color from copy of the destination.\n");
this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
if (!topDown) {
this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
}
this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName);
this->appendTextureLookup(dstCopySamplerName,
"_dstTexCoord",
configMask,
"rgba");
this->codeAppend(";");
}
void GrGLFragmentShaderBuilder::enableCustomOutput() {
SkASSERT(!fHasCustomColorOutput);
fHasCustomColorOutput = true;
fOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier,
declared_color_output_name());
}
void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
SkASSERT(!fHasSecondaryOutput);
fHasSecondaryOutput = true;
fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
dual_source_output_name());
}
const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
}
const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
return dual_source_output_name();
}
void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputColor,
const GrGLSLExpr4& inputCoverage) {
this->enableSecondaryOutput();
const char* secondaryOutputName = this->getSecondaryColorOutputName();
GrGLSLExpr4 coeff(1);
switch (fProgramBuilder->header().fSecondaryOutputType) {
case GrOptDrawState::kCoverage_SecondaryOutputType:
break;
case GrOptDrawState::kCoverageISA_SecondaryOutputType:
// Get (1-A) into coeff
coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
break;
case GrOptDrawState::kCoverageISC_SecondaryOutputType:
// Get (1-RGBA) into coeff
coeff = GrGLSLExpr4(1) - inputColor;
break;
default:
SkFAIL("Unexpected Secondary Output");
}
// Get coeff * coverage into modulate and then write that to the dual source output.
this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
}
void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor,
const GrGLSLExpr4& inputCoverage) {
GrGLSLExpr4 fragColor = inputColor * inputCoverage;
switch (fProgramBuilder->header().fPrimaryOutputType) {
case GrOptDrawState::kModulate_PrimaryOutputType:
break;
case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
{
// Tack on "+(1-coverage)dst onto the frag color.
GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
fragColor = fragColor + dstContribution;
}
break;
default:
SkFAIL("Unknown Primary Output");
}
// On any post 1.10 GLSL supporting GPU, we declare custom output
if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) {
this->enableCustomOutput();
}
this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str());
}
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
@ -227,10 +304,10 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
gpu->glStandard(),
&fragShaderSrc);
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
this->appendDecls(fInputs, &fragShaderSrc);
// We shouldn't have declared outputs on 1.10
SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
this->appendDecls(fOutputs, &fragShaderSrc);
fragShaderSrc.append(fFunctions);
fragShaderSrc.append("void main() {\n");
fragShaderSrc.append(fCode);
@ -248,121 +325,21 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
return true;
}
void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
GrGpuGL* gpu = fProgramBuilder->gpu();
///////////////////////////////////////////////////////////////////////////
// emit code to read the dst copy texture, if necessary
if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
const char* dstCopyTopLeftName;
const char* dstCopyCoordScaleName;
const char* dstCopySamplerName;
uint32_t configMask;
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
configMask = kA_GrColorComponentFlag;
} else {
configMask = kRGBA_GrColorComponentFlags;
}
fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kSampler2D_GrSLType,
"DstCopySampler",
&dstCopySamplerName);
fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec2f_GrSLType,
"DstCopyUpperLeft",
&dstCopyTopLeftName);
fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec2f_GrSLType,
"DstCopyCoordScale",
&dstCopyCoordScaleName);
const char* fragPos = fragmentPosition();
this->codeAppend("// Read color from copy of the destination.\n");
this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
if (!topDown) {
this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
}
this->codeAppendf("vec4 %s = ", kDstCopyColorName);
this->appendTextureLookup(dstCopySamplerName,
"_dstTexCoord",
configMask,
"rgba");
this->codeAppend(";");
void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
if (fHasCustomColorOutput) {
GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
}
if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
fOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier,
declared_color_output_name());
fHasCustomColorOutput = true;
if (fHasSecondaryOutput) {
GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
}
}
void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
///////////////////////////////////////////////////////////////////////////
// write the secondary color output if necessary
if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
const char* secondaryOutputName = this->enableSecondaryOutput();
GrGLSLExpr4 coeff(1);
switch (header.fSecondaryOutputType) {
case GrOptDrawState::kCoverage_SecondaryOutputType:
break;
case GrOptDrawState::kCoverageISA_SecondaryOutputType:
// Get (1-A) into coeff
coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
break;
case GrOptDrawState::kCoverageISC_SecondaryOutputType:
// Get (1-RGBA) into coeff
coeff = GrGLSLExpr4(1) - inputColor;
break;
default:
SkFAIL("Unexpected Secondary Output");
}
// Get coeff * coverage into modulate and then write that to the dual source output.
codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
const char* name,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision) {
fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
if (fsInName) {
*fsInName = name;
}
///////////////////////////////////////////////////////////////////////////
// combine color and coverage as frag color
// Get "color * coverage" into fragColor
GrGLSLExpr4 fragColor = inputColor * inputCoverage;
switch (header.fPrimaryOutputType) {
case GrOptDrawState::kModulate_PrimaryOutputType:
break;
case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
{
// Tack on "+(1-coverage)dst onto the frag color.
GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
fragColor = fragColor + dstContribution;
}
break;
default:
SkFAIL("Unknown Primary Output");
}
codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
}
const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
if (!fHasSecondaryOutput) {
fOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier,
dual_source_output_name());
fHasSecondaryOutput = true;
}
return dual_source_output_name();
}
const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
}

View File

@ -7,18 +7,16 @@
#ifndef GrGLFragmentShaderBuilder_DEFINED
#define GrGLFragmentShaderBuilder_DEFINED
#include "GrGLShaderBuilder.h"
class GrGLProgramBuilder;
/*
* This base class encapsulates the functionality which all GrProcessors are allowed to use in their
* fragment shader
* This base class encapsulates the functionality which the GP uses to build fragment shaders
*/
class GrGLProcessorFragmentShaderBuilder : public GrGLShaderBuilder {
class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
public:
GrGLProcessorFragmentShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
virtual ~GrGLProcessorFragmentShaderBuilder() {}
GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
virtual ~GrGLGPFragmentBuilder() {}
/**
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile
* if code is added that uses one of these features without calling enableFeature()
@ -53,20 +51,23 @@ private:
/*
* Fragment processor's, in addition to all of the above, may need to use dst color so they use
* this builder to create their shader
* this builder to create their shader. Because this is the only shader builder the FP sees, we
* just call it FPShaderBuilder
*/
class GrGLFragmentProcessorShaderBuilder : public GrGLProcessorFragmentShaderBuilder {
class GrGLFPFragmentBuilder : public GrGLGPFragmentBuilder {
public:
GrGLFragmentProcessorShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
GrGLFPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
/** Returns the variable name that holds the color of the destination pixel. This may be NULL if
no effect advertised that it will read the destination. */
virtual const char* dstColor() = 0;
private:
typedef GrGLProcessorFragmentShaderBuilder INHERITED;
typedef GrGLGPFragmentBuilder INHERITED;
};
class GrGLFragmentShaderBuilder : public GrGLFragmentProcessorShaderBuilder {
// TODO rename to Fragment Builder
class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
public:
typedef uint8_t DstReadKey;
typedef uint8_t FragPosKey;
@ -83,39 +84,42 @@ public:
GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc);
virtual const char* dstColor() SK_OVERRIDE;
// true public interface, defined explicitly in the abstract interfaces above
virtual bool enableFeature(GLSLFeature) SK_OVERRIDE;
virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
int index) SK_OVERRIDE;
virtual const char* fragmentPosition() SK_OVERRIDE;
virtual const char* dstColor() SK_OVERRIDE;
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
void emitCodeToReadDstTexture();
void enableCustomOutput();
void enableSecondaryOutput();
const char* getPrimaryColorOutputName() const;
const char* getSecondaryColorOutputName() const;
void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
void bindFragmentShaderLocations(GrGLuint programID);
private:
/*
* An internal call for GrGLFullProgramBuilder to use to add varyings to the vertex shader
* An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
*/
void addVarying(GrSLType type,
const char* name,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision);
/*
* Private functions used by GrGLProgramBuilder for compilation
*/
void bindProgramLocations(GrGLuint programId);
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
void emitCodeBeforeEffects();
void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
/** Enables using the secondary color output and returns the name of the var in which it is
to be stored */
const char* enableSecondaryOutput();
/** Gets the name of the primary color output. */
const char* getColorOutputName() const;
// As GLProcessors emit code, there are some conditions we need to verify. We use the below
// state to track this. The reset call is called per processor emitted.
bool hasReadDstColor() const { return fHasReadDstColor; }
bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
void reset() {
fHasReadDstColor = false;
fHasReadFragmentPosition = false;
}
private:
/**
* Features that should only be enabled by GrGLFragmentShaderBuilder itself.
*/
@ -132,21 +136,29 @@ private:
kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
};
// Interpretation of FragPosKey when generating code
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.
};
static const char* kDstCopyColorName;
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
bool fSetupFragPosition;
bool fTopLeftFragPosRead;
friend class GrGLProgramBuilder;
friend class GrGLFullProgramBuilder;
// some state to verify shaders and effects are consistent, this is reset between effects by
// the program creator
bool fHasReadDstColor;
bool fHasReadFragmentPosition;
typedef GrGLFragmentProcessorShaderBuilder INHERITED;
friend class GrGLNvprProgramBuilder;
friend class GrGLProgramBuilder;
typedef GrGLFPFragmentBuilder INHERITED;
};
#endif

View File

@ -1,221 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLFullProgramBuilder.h"
#include "../GrGLGeometryProcessor.h"
#include "../GrGpuGL.h"
GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: INHERITED(gpu, optState, desc)
, fGLGeometryProcessorEmitter(this)
, fGS(this)
, fVS(this) {
}
void
GrGLFullProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) {
fVS.emitCodeBeforeEffects(inputColor, inputCoverage);
///////////////////////////////////////////////////////////////////////////
// emit the per-effect code for both color and coverage effects
EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
this->desc().numColorEffects(),
colorKeyProvider,
inputColor));
if (geometryProcessor) {
const GrGeometryProcessor& gp = *geometryProcessor->getGeometryProcessor();
fGLGeometryProcessorEmitter.set(&gp);
fEffectEmitter = &fGLGeometryProcessorEmitter;
fVS.emitAttributes(gp);
GrGLSLExpr4 gpInputCoverage = *inputCoverage;
GrGLSLExpr4 gpOutputCoverage;
EffectKeyProvider gpKeyProvider(&this->desc(),
EffectKeyProvider::kGeometryProcessor_EffectType);
bool useLocalCoords = this->getVertexShaderBuilder()->hasExplicitLocalCoords();
fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalCoords)));
this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInputCoverage,
&gpOutputCoverage);
fGeometryProcessor.reset(fProgramEffects.detach());
*inputCoverage = gpOutputCoverage;
}
EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
this->desc().numCoverageEffects(),
coverageKeyProvider,
inputCoverage));
fVS.emitCodeAfterEffects();
}
void GrGLFullProgramBuilder::addVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision) {
fVS.addVarying(type, name, vsOutName);
SkString* fsInputName = fVS.fOutputs.back().accessName();
#if GR_GL_EXPERIMENTAL_GS
if (desc().getHeader().fExperimentalGS) {
// TODO let the caller use these names
fGS.addVarying(type, fsInputName->c_str(), NULL);
fsInputName = fGS.fOutputs.back().accessName();
}
#endif
fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
}
GrGLFullProgramBuilder::VaryingHandle
GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName) {
addVarying(type, name, vsOutName, fsInName);
SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
varying.fVariable = fFS.fInputs.back();
return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
}
GrGLProgramEffects* GrGLFullProgramBuilder::onCreateAndEmitEffects(
const GrFragmentStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inOutFSColor) {
fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects,
(effectCnt,
this->getVertexShaderBuilder()->hasExplicitLocalCoords())));
this->INHERITED::createAndEmitEffects(effectStages,
effectCnt,
keyProvider,
inOutFSColor);
return fProgramEffects.detach();
}
void GrGLFullProgramBuilder::emitEffect(const GrProcessorStage& stage,
const GrProcessorKey& key,
const char* outColor,
const char* inColor,
int stageIndex) {
SkASSERT(fProgramEffects.get());
const GrProcessor& effect = *stage.getProcessor();
SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
this->emitTransforms(stage, &coords);
this->emitSamplers(effect, &samplers);
SkASSERT(fEffectEmitter);
GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
fProgramEffects->addEffect(glEffect);
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("{ // Stage %d: %s\n", stageIndex, glEffect->name());
fFS.codeAppend(openBrace.c_str());
fVS.codeAppend(openBrace.c_str());
fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
fVS.codeAppend("\t}\n");
fFS.codeAppend("\t}\n");
}
void GrGLFullProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
GrGLProcessor::TransformedCoordsArray* outCoords) {
SkTArray<GrGLVertexProgramEffects::Transform, true>& transforms =
fProgramEffects->addTransforms();
const GrProcessor* effect = effectStage.getProcessor();
int numTransforms = effect->numTransforms();
transforms.push_back_n(numTransforms);
SkTArray<GrGLVertexProgramEffects::PathTransform, true>* pathTransforms = NULL;
const GrGLCaps* glCaps = this->ctxInfo().caps();
if (glCaps->pathRenderingSupport() &&
this->gpu()->glPathRendering()->texturingMode() ==
GrGLPathRendering::SeparableShaders_TexturingMode) {
pathTransforms = &fProgramEffects->addPathTransforms();
pathTransforms->push_back_n(numTransforms);
}
for (int t = 0; t < numTransforms; t++) {
const char* uniName = "StageMatrix";
GrSLType varyingType =
effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
SkString suffixedUniName;
if (0 != t) {
suffixedUniName.append(uniName);
suffixedUniName.appendf("_%i", t);
uniName = suffixedUniName.c_str();
}
transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType,
uniName,
&uniName);
const char* varyingName = "MatrixCoord";
SkString suffixedVaryingName;
if (0 != t) {
suffixedVaryingName.append(varyingName);
suffixedVaryingName.appendf("_%i", t);
varyingName = suffixedVaryingName.c_str();
}
const char* vsVaryingName;
const char* fsVaryingName;
if (pathTransforms) {
(*pathTransforms)[t].fHandle =
this->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
(*pathTransforms)[t].fType = varyingType;
} else {
this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
}
const GrGLShaderVar& coords =
kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
fVS.positionAttribute() :
fVS.localCoordsAttribute();
// varying = matrix * coords (logically)
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
vsVaryingName, uniName, coords.c_str());
} else {
fVS.codeAppendf("%s = %s * vec3(%s, 1);",
vsVaryingName, uniName, coords.c_str());
}
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
(SkString(fsVaryingName), varyingType));
}
}
bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
return INHERITED::compileAndAttachShaders(programId, shaderIds)
&& fVS.compileAndAttachShaders(programId, shaderIds)
#if GR_GL_EXPERIMENTAL_GS
&& (!desc().getHeader().fExperimentalGS
|| fGS.compileAndAttachShaders(programId, shaderIds))
#endif
;
}
void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
fVS.bindProgramLocations(programId);
INHERITED::bindProgramLocations(programId);
}

View File

@ -1,130 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLFullProgramBuilder_DEFINED
#define GrGLFullProgramBuilder_DEFINED
#include "GrGLProgramBuilder.h"
#include "../GrGLGeometryProcessor.h"
class GrGLVertexProgramEffects;
class GrGLFullProgramBuilder : public GrGLProgramBuilder {
public:
GrGLFullProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
/** Add a varying variable to the current program to pass values between vertex and fragment
shaders. If the last two parameters are non-NULL, they are filled in with the name
generated. */
void addVarying(GrSLType type,
const char* name,
const char** vsOutName = NULL,
const char** fsInName = NULL,
GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
/** Add a separable varying input variable to the current program.
* A separable varying (fragment shader input) is a varying that can be used also when vertex
* shaders are not used. With a vertex shader, the operation is same as with other
* varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
* populate the variable. The APIs can refer to the variable through the returned handle.
*/
VaryingHandle addSeparableVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName);
GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
/*
* This non-virtual call will hide the parent call to prevent GPs from accessing fragment shader
* functionality they shouldn't be using
*/
GrGLProcessorFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
private:
virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor);
class GrGLGeometryProcessorEmitter : public GrGLProgramBuilder::GrGLProcessorEmitterInterface {
public:
GrGLGeometryProcessorEmitter(GrGLFullProgramBuilder* builder)
: fBuilder(builder)
, fGeometryProcessor(NULL)
, fGLGeometryProcessor(NULL) {}
virtual ~GrGLGeometryProcessorEmitter() {}
void set(const GrGeometryProcessor* gp) {
SkASSERT(NULL == fGeometryProcessor);
fGeometryProcessor = gp;
}
virtual GrGLProcessor* createGLInstance() {
SkASSERT(fGeometryProcessor);
SkASSERT(NULL == fGLGeometryProcessor);
fGLGeometryProcessor =
fGeometryProcessor->getFactory().createGLInstance(*fGeometryProcessor);
return fGLGeometryProcessor;
}
virtual void emit(const GrProcessorKey& key,
const char* outColor,
const char* inColor,
const GrGLProcessor::TransformedCoordsArray& coords,
const GrGLProcessor::TextureSamplerArray& samplers) {
SkASSERT(fGeometryProcessor);
SkASSERT(fGLGeometryProcessor);
fGLGeometryProcessor->emitCode(fBuilder, *fGeometryProcessor, key, outColor,
inColor, coords, samplers);
// this will not leak because it has already been used by createGLInstance
fGLGeometryProcessor = NULL;
fGeometryProcessor = NULL;
}
private:
GrGLFullProgramBuilder* fBuilder;
const GrGeometryProcessor* fGeometryProcessor;
GrGLGeometryProcessor* fGLGeometryProcessor;
};
virtual void emitEffect(const GrProcessorStage& stage,
const GrProcessorKey& key,
const char* outColor,
const char* inColor,
int stageIndex) SK_OVERRIDE;
/**
* Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
* Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
* vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
* of the varyings in the VS and FS as well their types are appended to the
* TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
*/
void emitTransforms(const GrProcessorStage& effectStage,
GrGLProcessor::TransformedCoordsArray* outCoords);
virtual bool compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
GrGLGeometryProcessorEmitter fGLGeometryProcessorEmitter;
GrGLGeometryShaderBuilder fGS;
GrGLVertexShaderBuilder fVS;
SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
typedef GrGLProgramBuilder INHERITED;
};
#endif

View File

@ -10,12 +10,12 @@
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program)
GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
: INHERITED(program) {
}
void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
void GrGLGeometryBuilder::addVarying(GrSLType type,
const char* name,
const char** gsOutName) {
// if we have a GS take each varying in as an array
@ -35,15 +35,15 @@ void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
}
bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId,
bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext();
SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()));
geomShaderSrc.append("layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n");
fProgramBuilder->appendDecls(fInputs, &geomShaderSrc);
fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc);
this->appendDecls(fInputs, &geomShaderSrc);
this->appendDecls(fOutputs, &geomShaderSrc);
geomShaderSrc.append("void main() {\n");
geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\n");

View File

@ -10,12 +10,9 @@
#include "GrGLShaderBuilder.h"
class GrGLProgramBuilder;
class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder {
class GrGLGeometryBuilder : public GrGLShaderBuilder {
public:
GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program);
private:
GrGLGeometryBuilder(GrGLProgramBuilder* program);
/*
* an internal call for GrGLFullProgramBuilder to add varyings
*/
@ -25,8 +22,7 @@ private:
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
friend class GrGLFullProgramBuilder;
typedef GrGLFullShaderBuilder INHERITED;
typedef GrGLShaderBuilder INHERITED;
};
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLLegacyNvprProgramBuilder.h"
#include "../GrGpuGL.h"
GrGLLegacyNvprProgramBuilder::GrGLLegacyNvprProgramBuilder(GrGpuGL* gpu,
const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: INHERITED(gpu, optState, desc)
, fTexCoordSetCnt(0) {
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}
int GrGLLegacyNvprProgramBuilder::addTexCoordSets(int count) {
int firstFreeCoordSet = fTexCoordSetCnt;
fTexCoordSetCnt += count;
SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
return firstFreeCoordSet;
}
void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors* installedProcessors) {
int numTransforms = processorStage.getProcessor()->numTransforms();
int texCoordIndex = this->addTexCoordSets(numTransforms);
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
installedProcessors->addTransforms();
// Use the first uniform location as the texcoord index. This may seem a bit hacky but it
// allows us to use one program effects object for all of our programs which really simplifies
// the code overall
transforms.push_back_n(1);
transforms[0].fHandle = GrGLInstalledProcessors::ShaderVarHandle(texCoordIndex);
SkString name;
for (int t = 0; t < numTransforms; ++t) {
GrSLType type = processorStage.isPerspectiveCoordTransform(t, false) ? kVec3f_GrSLType :
kVec2f_GrSLType;
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
}
}
GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
fColorEffects, fCoverageEffects, fTexCoordSetCnt));
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLLegacyNvprProgramBuilder_DEFINED
#define GrGLLegacyNvprProgramBuilder_DEFINED
#include "GrGLProgramBuilder.h"
class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
public:
GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
virtual GrGLProgram* createProgram(GrGLuint programID);
private:
int addTexCoordSets(int count);
void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors*);
int fTexCoordSetCnt;
typedef GrGLProgramBuilder INHERITED;
};
#endif

View File

@ -0,0 +1,84 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLNvprProgramBuilder.h"
#include "../GrGpuGL.h"
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
GrGLNvprProgramBuilder::GrGLNvprProgramBuilder(GrGpuGL* gpu,
const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: INHERITED(gpu, optState, desc)
, fSeparableVaryingInfos(kVarsPerBlock) {
}
void GrGLNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors* installedProcessors) {
const GrProcessor* effect = processorStage.getProcessor();
int numTransforms = effect->numTransforms();
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
installedProcessors->addTransforms();
transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
GrSLType varyingType =
processorStage.isPerspectiveCoordTransform(t, false) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
const char* varyingName = "MatrixCoord";
SkString suffixedVaryingName;
if (0 != t) {
suffixedVaryingName.append(varyingName);
suffixedVaryingName.appendf("_%i", t);
varyingName = suffixedVaryingName.c_str();
}
const char* vsVaryingName;
const char* fsVaryingName;
transforms[t].fHandle = this->addSeparableVarying(varyingType, varyingName,
&vsVaryingName, &fsVaryingName);
transforms[t].fType = varyingType;
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
(SkString(fsVaryingName), varyingType));
}
}
GrGLInstalledProcessors::ShaderVarHandle
GrGLNvprProgramBuilder::addSeparableVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName) {
addVarying(type, name, vsOutName, fsInName);
SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
varying.fVariable = fFS.fInputs.back();
return GrGLInstalledProcessors::ShaderVarHandle(fSeparableVaryingInfos.count() - 1);
}
void GrGLNvprProgramBuilder::resolveSeparableVaryings(GrGLuint programId) {
int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location,
GetProgramResourceLocation(programId,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
}
}
GrGLProgram* GrGLNvprProgramBuilder::createProgram(GrGLuint programID) {
// this is just for nvpr es, which has separable varyings that are plugged in after
// building
this->resolveSeparableVaryings(programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
fColorEffects, fCoverageEffects, fSeparableVaryingInfos));
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLNvprProgramBuilder_DEFINED
#define GrGLNvprProgramBuilder_DEFINED
#include "GrGLProgramBuilder.h"
class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
public:
GrGLNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
/*
* The separable varying info must be passed to GrGLProgram so this must
* be part of the public interface
*/
struct SeparableVaryingInfo {
GrGLShaderVar fVariable;
GrGLint fLocation;
};
typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
virtual GrGLProgram* createProgram(GrGLuint programID);
private:
virtual void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors*) SK_OVERRIDE;
typedef GrGLInstalledProcessors::ShaderVarHandle ShaderVarHandle;
/**
* Add a separable varying input variable to the current program.
* A separable varying (fragment shader input) is a varying that can be used also when vertex
* shaders are not used. With a vertex shader, the operation is same as with other
* varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
* populate the variable. The APIs can refer to the variable through the returned handle.
*/
ShaderVarHandle addSeparableVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName);
void resolveSeparableVaryings(GrGLuint programId);
SeparableVaryingInfoArray fSeparableVaryingInfos;
typedef GrGLProgramBuilder INHERITED;
};
#endif

View File

@ -5,110 +5,151 @@
* found in the LICENSE file.
*/
#include "GrGLProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
#include "GrCoordTransform.h"
#include "../GrGpuGL.h"
#include "GrGLFragmentShaderBuilder.h"
#include "GrCoordTransform.h"
#include "GrGLLegacyNvprProgramBuilder.h"
#include "GrGLNvprProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrTexture.h"
#include "GrGLVertexShaderBuilder.h"
#include "SkRTConf.h"
#include "SkTraceEvent.h"
namespace {
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]) {
const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
fFS.emitCodeBeforeEffects();
///////////////////////////////////////////////////////////////////////////
// get the initial color and coverage to feed into the first effect in each effect chain
GrGLSLExpr4 inputColor;
GrGLSLExpr4 inputCoverage;
if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
const char* name;
fUniformHandles.fColorUni =
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
"Color",
&name);
inputColor = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
inputColor = GrGLSLExpr4(1);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
const char* name;
fUniformHandles.fCoverageUni =
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
"Coverage",
&name);
inputCoverage = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
inputCoverage = GrGLSLExpr4(1);
}
// Subclasses drive effect emitting
this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor,
&inputCoverage);
fFS.emitCodeAfterEffects(inputColor, inputCoverage);
if (!this->finish()) {
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////
const int GrGLProgramBuilder::kVarsPerBlock = 8;
GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
GrGpu::DrawType drawType,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGpuGL* gpu) {
// create a builder. This will be handed off to effects so they can use it to add
// uniforms, varyings, textures, etc
SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
optState,
drawType,
SkToBool(geometryProcessor),
gpu));
GrGLProgramBuilder* pb = builder.get();
const GrGLProgramDesc::KeyHeader& header = pb->header();
// emit code to read the dst copy texture, if necessary
if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
&& !gpu->glCaps().fbFetchSupport()) {
pb->fFS.emitCodeToReadDstTexture();
}
// get the initial color and coverage to feed into the first effect in each effect chain
GrGLSLExpr4 inputColor, inputCoverage;
pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
// if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
// to setup a few more things like builtin vertex attributes
bool hasVertexShader = !header.fUseFragShaderOnly;
if (hasVertexShader) {
pb->fVS.setupLocalCoords();
pb->fVS.transformGLToSkiaCoords();
if (header.fEmitsPointSize) {
pb->fVS.codeAppend("gl_PointSize = 1.0;");
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
}
}
pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
&inputCoverage);
if (hasVertexShader) {
pb->fVS.transformSkiaToGLCoords();
}
// write the secondary color output if necessary
if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
}
pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
return pb->finalize();
}
GrGLProgramBuilder*
GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
const GrOptDrawState& optState,
GrGpu::DrawType drawType,
bool hasGeometryProcessor,
GrGpuGL* gpu) {
if (desc.getHeader().fUseFragShaderOnly) {
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(gpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::FixedFunction_TexturingMode);
SkASSERT(!hasGeometryProcessor);
return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
} else if (GrGpu::IsPathRenderingDrawType(drawType)) {
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(gpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::SeparableShaders_TexturingMode);
SkASSERT(!hasGeometryProcessor);
return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
} else {
return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
}
}
/////////////////////////////////////////////////////////////////////////////
GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: fEffectEmitter(NULL)
, fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly))
, fTexCoordSetCnt(0)
, fProgramID(0)
: fVS(this)
, fGS(this)
, fFS(this, desc)
, fSeparableVaryingInfos(kVarsPerBlock)
, fGrProcessorEmitter(this)
, fOutOfStage(true)
, fStageIndex(-1)
, fOptState(optState)
, fDesc(desc)
, fGpu(gpu)
, fUniforms(kVarsPerBlock) {
}
void GrGLProgramBuilder::addVarying(GrSLType type,
const char* name,
const char** vsOutName,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision) {
SkString* fsInputName = fVS.addVarying(type, name, vsOutName);
fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
}
void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
if ('\0' == prefix) {
*out = name;
} else {
out->printf("%c%s", prefix, name);
}
if (fCodeStage.inStageCode()) {
if (!fOutOfStage) {
if (out->endsWith('_')) {
// Names containing "__" are reserved.
out->append("x");
}
out->appendf("_Stage%d", fCodeStage.stageIndex());
out->appendf("_Stage%d", fStageIndex);
}
}
@ -143,13 +184,6 @@ GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
}
void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
for (int i = 0; i < vars.count(); ++i) {
vars[i].appendDecl(this->ctxInfo(), out);
out->append(";\n");
}
}
void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) {
@ -160,20 +194,129 @@ void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
}
}
void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* fsInOutColor) {
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
return fGpu->ctxInfo();
}
void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) {
const GrGLProgramDesc::KeyHeader& header = this->header();
if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
const char* name;
fUniformHandles.fColorUni =
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
"Color",
&name);
*inputColor = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
*inputColor = GrGLSLExpr4(1);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
const char* name;
fUniformHandles.fCoverageUni =
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
"Coverage",
&name);
*inputCoverage = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
*inputCoverage = GrGLSLExpr4(1);
}
}
void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) {
bool useLocalCoords = fVS.hasExplicitLocalCoords();
EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType);
int numColorEffects = fDesc.numColorEffects();
GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects,
useLocalCoords));
this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
inputColor, ip);
fColorEffects.reset(ip);
if (geometryProcessor) {
fVS.emitAttributes(*geometryProcessor->getProcessor());
EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType);
ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider,
inputCoverage, ip);
fGeometryProcessor.reset(ip);
}
EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType);
int numCoverageEffects = fDesc.numCoverageEffects();
ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords));
this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects,
coverageKeyProvider, inputCoverage, ip);
fCoverageEffects.reset(ip);
}
template <class ProcessorStage>
void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[],
int effectCnt,
const EffectKeyProvider& keyProvider,
GrGLSLExpr4* fsInOutColor,
GrGLInstalledProcessors* installedProcessors) {
bool effectEmitted = false;
GrGLSLExpr4 inColor = *fsInOutColor;
GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) {
fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor());
fEffectEmitter = &fGrProcessorEmitter;
// calls into the subclass to emit the actual effect into the program effect object
this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor);
// Program builders have a bit of state we need to clear with each effect
AutoStageAdvance adv(this);
const ProcessorStage& stage = *processStages[e];
SkASSERT(stage.getProcessor());
if (inColor.isZeros()) {
SkString inColorName;
// Effects have no way to communicate zeros, they treat an empty string as ones.
this->nameVariable(&inColorName, '\0', "input");
fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
inColor = inColorName;
}
// create var to hold stage result
SkString outColorName;
this->nameVariable(&outColorName, '\0', "output");
fFS.codeAppendf("vec4 %s;", outColorName.c_str());
outColor = outColorName;
SkASSERT(installedProcessors);
const typename ProcessorStage::Processor& processor = *stage.getProcessor();
SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms());
SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures());
this->emitTransforms(stage, &coords, installedProcessors);
this->emitSamplers(processor, &samplers, installedProcessors);
typename ProcessorStage::GLProcessor* glEffect =
processor.getFactory().createGLInstance(processor);
installedProcessors->addEffect(glEffect);
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
fFS.codeAppend(openBrace.c_str());
fVS.codeAppend(openBrace.c_str());
glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(),
inColor.isOnes() ? NULL : inColor.c_str(), coords, samplers);
// We have to check that effects and the code they emit are consistent, ie if an effect
// asks for dst color, then the emit code needs to follow suit
verify(processor);
fFS.codeAppend("}");
fVS.codeAppend("}");
inColor = outColor;
effectEmitted = true;
}
@ -182,40 +325,77 @@ void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage
}
}
void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage,
int effectIndex,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inColor,
GrGLSLExpr4* outColor) {
SkASSERT(effectStage.getProcessor());
CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
if (inColor->isZeros()) {
SkString inColorName;
// Effects have no way to communicate zeros, they treat an empty string as ones.
this->nameVariable(&inColorName, '\0', "input");
fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str());
*inColor = inColorName;
}
// create var to hold stage result
SkString outColorName;
this->nameVariable(&outColorName, '\0', "output");
fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
*outColor = outColorName;
this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(),
inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex());
*inColor = *outColor;
void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
}
void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
GrGLProcessor::TextureSamplerArray* outSamplers) {
SkTArray<GrGLProgramEffects::Sampler, true>& samplers =
this->getProgramEffects()->addSamplers();
int numTextures = effect.numTextures();
void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
}
void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors* installedProcessors) {
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
installedProcessors->addTransforms();
const GrProcessor* effect = effectStage.getProcessor();
int numTransforms = effect->numTransforms();
transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
const char* uniName = "StageMatrix";
GrSLType varyingType =
effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
SkString suffixedUniName;
if (0 != t) {
suffixedUniName.append(uniName);
suffixedUniName.appendf("_%i", t);
uniName = suffixedUniName.c_str();
}
transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType,
uniName,
&uniName).toShaderBuilderIndex();
const char* varyingName = "MatrixCoord";
SkString suffixedVaryingName;
if (0 != t) {
suffixedVaryingName.append(varyingName);
suffixedVaryingName.appendf("_%i", t);
varyingName = suffixedVaryingName.c_str();
}
const char* vsVaryingName;
const char* fsVaryingName;
this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
const GrGLShaderVar& coords =
kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
fVS.positionAttribute() :
fVS.localCoordsAttribute();
// varying = matrix * coords (logically)
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
vsVaryingName, uniName, coords.c_str());
} else {
fVS.codeAppendf("%s = %s * vec3(%s, 1);",
vsVaryingName, uniName, coords.c_str());
}
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
(SkString(fsVaryingName), varyingType));
}
}
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
GrGLProcessor::TextureSamplerArray* outSamplers,
GrGLInstalledProcessors* installedProcessors) {
SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
int numTextures = processor.numTextures();
samplers.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
@ -224,27 +404,37 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
kSampler2D_GrSLType,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
(samplers[t].fUniform, effect.textureAccess(t)));
(samplers[t].fUniform, processor.textureAccess(t)));
}
}
bool GrGLProgramBuilder::finish() {
SkASSERT(0 == fProgramID);
GL_CALL_RET(fProgramID, CreateProgram());
if (!fProgramID) {
return false;
GrGLProgram* GrGLProgramBuilder::finalize() {
// verify we can get a program id
GrGLuint programID;
GL_CALL_RET(programID, CreateProgram());
if (0 == programID) {
return NULL;
}
// compile shaders and bind attributes / uniforms
SkTDArray<GrGLuint> shadersToDelete;
if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
GL_CALL(DeleteProgram(fProgramID));
return false;
if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
this->cleanupProgram(programID, shadersToDelete);
return NULL;
}
this->bindProgramLocations(fProgramID);
GL_CALL(LinkProgram(fProgramID));
if (!this->header().fUseFragShaderOnly) {
if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
this->cleanupProgram(programID, shadersToDelete);
return NULL;
}
fVS.bindVertexAttributes(programID);
}
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (usingBindUniform) {
this->bindUniformLocations(programID);
}
fFS.bindFragmentShaderLocations(programID);
GL_CALL(LinkProgram(programID));
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
bool checkLinked = !fGpu->ctxInfo().isChromium();
@ -252,80 +442,78 @@ bool GrGLProgramBuilder::finish() {
checkLinked = true;
#endif
if (checkLinked) {
GrGLint linked = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
if (!linked) {
GrGLint infoLen = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GL_CALL(GetProgramInfoLog(fProgramID,
infoLen+1,
&length,
(char*)log.get()));
GrPrintf((char*)log.get());
}
SkDEBUGFAIL("Error linking program");
GL_CALL(DeleteProgram(fProgramID));
fProgramID = 0;
return false;
}
checkLinkStatus(programID);
}
this->resolveProgramLocations(fProgramID);
for (int i = 0; i < shadersToDelete.count(); ++i) {
GL_CALL(DeleteShader(shadersToDelete[i]));
}
return true;
}
bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
return fFS.compileAndAttachShaders(programId, shaderIds);
}
void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
fFS.bindProgramLocations(programId);
// skbug.com/2056
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (usingBindUniform) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = i;
}
}
}
void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (!usingBindUniform) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location,
GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = location;
}
this->resolveUniformLocations(programID);
}
int count = fSeparableVaryingInfos.count();
this->cleanupShaders(shadersToDelete);
return this->createProgram(programID);
}
void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = i;
}
}
bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
GrGLint linked = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
if (!linked) {
GrGLint infoLen = GR_GL_INIT_ZERO;
GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GL_CALL(GetProgramInfoLog(programID,
infoLen+1,
&length,
(char*)log.get()));
GrPrintf((char*)log.get());
}
SkDEBUGFAIL("Error linking program");
GL_CALL(DeleteProgram(programID));
programID = 0;
}
return SkToBool(linked);
}
void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location,
GetProgramResourceLocation(programId,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = location;
}
}
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
return fGpu->ctxInfo();
void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
GL_CALL(DeleteProgram(programID));
cleanupShaders(shaderIDs);
}
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
for (int i = 0; i < shaderIDs.count(); ++i) {
GL_CALL(DeleteShader(shaderIDs[i]));
}
}
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
fGeometryProcessor, fColorEffects, fCoverageEffects));
}
////////////////////////////////////////////////////////////////////////////////
GrGLInstalledProcessors::~GrGLInstalledProcessors() {
int numEffects = fGLProcessors.count();
for (int e = 0; e < numEffects; ++e) {
SkDELETE(fGLProcessors[e]);
}
}

View File

@ -8,31 +8,25 @@
#ifndef GrGLProgramBuilder_DEFINED
#define GrGLProgramBuilder_DEFINED
#include "GrAllocator.h"
#include "GrBackendProcessorFactory.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrGLFragmentShaderBuilder.h"
#include "GrGLGeometryShaderBuilder.h"
#include "GrGLVertexShaderBuilder.h"
#include "SkTypes.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h"
#include "../GrGLProgramDataManager.h"
#include "../GrGLUniformHandle.h"
#include <stdarg.h>
class GrGLInstalledProcessors;
class GrGLContextInfo;
class GrProcessorStage;
class GrGLProgramDesc;
/**
Contains all the incremental state of a shader as it is being built,as well as helpers to
manipulate that state.
*/
class GrGLProgramBuilder {
/*
* This is the base class for a series of interfaces. This base class *MUST* remain abstract with
* NO data members because it is used in multiple interface inheritance.
* Heirarchy:
* GrGLUniformBuilder
* / \
* GrGLFPBuilder GrGLGPBuilder
* \ /
* GrGLProgramBuilder(internal use only)
*/
class GrGLUniformBuilder {
public:
enum ShaderVisibility {
kVertex_Visibility = 0x1,
@ -40,8 +34,127 @@ public:
kFragment_Visibility = 0x4,
};
virtual ~GrGLUniformBuilder() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
visibility is a bitfield of ShaderVisibility values indicating from which shaders the
uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
it will refer to the final uniform name after return. Use the addUniformArray variant to add
an array of uniforms. */
virtual UniformHandle addUniform(uint32_t visibility,
GrSLType type,
const char* name,
const char** outName = NULL) = 0;
virtual UniformHandle addUniformArray(uint32_t visibility,
GrSLType type,
const char* name,
int arrayCount,
const char** outName = NULL) = 0;
virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
/**
* Shortcut for getUniformVariable(u).c_str()
*/
virtual const char* getUniformCStr(UniformHandle u) const = 0;
virtual const GrGLContextInfo& ctxInfo() const = 0;
virtual GrGpuGL* gpu() const = 0;
/*
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
*/
};
/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
class GrGLGPBuilder : public virtual GrGLUniformBuilder {
public:
virtual void addVarying(GrSLType type,
const char* name,
const char** vsOutName = NULL,
const char** fsInName = NULL,
GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
// TODO rename getFragmentBuilder
virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
/*
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
*/
};
/* a specializations for FPs. Lets the user add uniforms and FS code */
class GrGLFPBuilder : public virtual GrGLUniformBuilder {
public:
virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
/*
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
*/
};
/*
* Please note - no diamond problems because of virtual inheritance. Also, both base classes
* are pure virtual with no data members. This is the base class for program building.
* Subclasses are nearly identical but each has their own way of emitting transforms. State for
* each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
* respective builders
*/
class GrGLProgramBuilder : public GrGLGPBuilder,
public GrGLFPBuilder {
public:
/** Generates a shader program.
*
* The program implements what is specified in the stages given as input.
* After successful generation, the builder result objects are available
* to be used.
* @return true if generation was successful.
*/
static GrGLProgram* CreateProgram(const GrOptDrawState&,
const GrGLProgramDesc&,
GrGpu::DrawType,
const GrGeometryStage* inGeometryProcessor,
const GrFragmentStage* inColorStages[],
const GrFragmentStage* inCoverageStages[],
GrGpuGL* gpu);
virtual UniformHandle addUniform(uint32_t visibility,
GrSLType type,
const char* name,
const char** outName = NULL) SK_OVERRIDE {
return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
}
virtual UniformHandle addUniformArray(uint32_t visibility,
GrSLType type,
const char* name,
int arrayCount,
const char** outName = NULL) SK_OVERRIDE;
virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
return fUniforms[u.toShaderBuilderIndex()].fVariable;
}
virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
return this->getUniformVariable(u).c_str();
}
virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
virtual GrGLFragmentShaderBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
virtual void addVarying(GrSLType type,
const char* name,
const char** vsOutName = NULL,
const char** fsInName = NULL,
GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
// Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles {
@ -60,277 +173,175 @@ public:
UniformHandle fDstCopySamplerUni;
};
struct UniformInfo {
GrGLShaderVar fVariable;
uint32_t fVisibility;
GrGLint fLocation;
};
// This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
// after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
// name strings. Otherwise, we'd have to hand out copies.
typedef GrTAllocator<UniformInfo> UniformInfoArray;
struct SeparableVaryingInfo {
GrGLShaderVar fVariable;
GrGLint fLocation;
};
typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
/** Generates a shader program.
*
* The program implements what is specified in the stages given as input.
* After successful generation, the builder result objects are available
* to be used.
* @return true if generation was successful.
*/
bool genProgram(const GrGeometryStage* inGeometryProcessor,
const GrFragmentStage* inColorStages[],
const GrFragmentStage* inCoverageStages[]);
GrGLProgramEffects* getGeometryProcessor() const {
SkASSERT(fProgramID); return fGeometryProcessor.get();
}
GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
const BuiltinUniformHandles& getBuiltinUniformHandles() const {
SkASSERT(fProgramID);
return fUniformHandles;
}
GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
const UniformInfoArray& getUniformInfos() const { return fUniforms; }
const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
return fSeparableVaryingInfos;
}
virtual ~GrGLProgramBuilder() {}
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
visibility is a bitfield of ShaderVisibility values indicating from which shaders the
uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
it will refer to the final uniform name after return. Use the addUniformArray variant to add
an array of uniforms. */
GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
GrSLType type,
const char* name,
const char** outName = NULL) {
return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
}
GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
GrSLType type,
const char* name,
int arrayCount,
const char** outName = NULL);
const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
return fUniforms[u.toShaderBuilderIndex()].fVariable;
}
/**
* Shortcut for getUniformVariable(u).c_str()
*/
const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
return this->getUniformVariable(u).c_str();
}
const GrGLContextInfo& ctxInfo() const;
GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
GrGpuGL* gpu() const { return fGpu; }
protected:
typedef GrTAllocator<GrGLShaderVar> VarArray;
static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
const GrOptDrawState&,
GrGpu::DrawType,
bool hasGeometryProcessor,
GrGpuGL*);
GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
const GrOptDrawState& optState() const { return fOptState; }
const GrGLProgramDesc& desc() const { return fDesc; }
// Helper for emitEffects().
void createAndEmitEffects(const GrFragmentStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor);
/*
* A helper function called to emit the geometry processor as well as individual coverage
* and color stages. this will call into subclasses emit effect
*/
void emitEffect(const GrProcessorStage& effectStage,
int effectIndex,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inColor,
GrGLSLExpr4* outColor);
/**
* Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
* appends the necessary data to the TextureSamplerArray* object so effects can add texture
* lookups to their code. This method is only meant to be called during the construction phase.
*/
void emitSamplers(const GrProcessor& effect,
GrGLProcessor::TextureSamplerArray* outSamplers);
const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
// Generates a name for a variable. The generated string will be name prefixed by the prefix
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
// generating stage code.
void nameVariable(SkString* out, char prefix, const char* name);
void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage);
template <class ProcessorStage>
void createAndEmitProcessors(const ProcessorStage*[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* fsInOutColor,
GrGLInstalledProcessors*);
void verify(const GrGeometryProcessor&);
void verify(const GrFragmentProcessor&);
void emitSamplers(const GrProcessor&,
GrGLProcessor::TextureSamplerArray* outSamplers,
GrGLInstalledProcessors*);
virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
// each specific program builder has a distinct transform and must override this function
virtual void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
GrGLInstalledProcessors*);
GrGLProgram* finalize();
void bindUniformLocations(GrGLuint programID);
bool checkLinkStatus(GrGLuint programID);
void resolveUniformLocations(GrGLuint programID);
virtual void bindProgramLocations(GrGLuint programId);
void resolveProgramLocations(GrGLuint programId);
void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
// Subclasses create different programs
virtual GrGLProgram* createProgram(GrGLuint programID);
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
class CodeStage : SkNoncopyable {
// reset is called by program creator between each processor's emit code. It increments the
// stage offset for variable name mangling, and also ensures verfication variables in the
// fragment shader are cleared.
void reset() {
this->enterStage();
this->addStage();
fFS.reset();
}
void addStage() { fStageIndex++; }
// This simple class exits the stage and then restores the stage when it goes out of scope
class AutoStageRestore {
public:
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
bool inStageCode() const {
this->validate();
return SkToBool(fEffectStage);
}
const GrProcessorStage* effectStage() const {
this->validate();
return fEffectStage;
}
int stageIndex() const {
this->validate();
return fCurrentIndex;
}
class AutoStageRestore : SkNoncopyable {
public:
AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
SkASSERT(codeStage);
fSavedIndex = codeStage->fCurrentIndex;
fSavedEffectStage = codeStage->fEffectStage;
if (NULL == newStage) {
codeStage->fCurrentIndex = -1;
} else {
codeStage->fCurrentIndex = codeStage->fNextIndex++;
}
codeStage->fEffectStage = newStage;
fCodeStage = codeStage;
}
~AutoStageRestore() {
fCodeStage->fCurrentIndex = fSavedIndex;
fCodeStage->fEffectStage = fSavedEffectStage;
}
private:
CodeStage* fCodeStage;
int fSavedIndex;
const GrProcessorStage* fSavedEffectStage;
};
AutoStageRestore(GrGLProgramBuilder* pb)
: fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
private:
void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
int fNextIndex;
int fCurrentIndex;
const GrProcessorStage* fEffectStage;
GrGLProgramBuilder* fPB;
bool fOutOfStage;
};
class GrGLProcessorEmitterInterface {
public:
virtual ~GrGLProcessorEmitterInterface() {}
virtual GrGLProcessor* createGLInstance() = 0;
virtual void emit(const GrProcessorKey& key,
const char* outColor,
const char* inColor,
const GrGLProcessor::TransformedCoordsArray& coords,
const GrGLProcessor::TextureSamplerArray& samplers) = 0;
};
class GrGLFragmentProcessorEmitter : public GrGLProcessorEmitterInterface {
class AutoStageAdvance {
public:
GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
: fBuilder(builder)
, fFragmentProcessor(NULL)
, fGLFragmentProcessor(NULL) {}
virtual ~GrGLFragmentProcessorEmitter() {}
void set(const GrFragmentProcessor* fp) {
SkASSERT(NULL == fFragmentProcessor);
fFragmentProcessor = fp;
}
virtual GrGLProcessor* createGLInstance() {
SkASSERT(fFragmentProcessor);
SkASSERT(NULL == fGLFragmentProcessor);
fGLFragmentProcessor =
fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
return fGLFragmentProcessor;
}
virtual void emit(const GrProcessorKey& key,
const char* outColor,
const char* inColor,
const GrGLProcessor::TransformedCoordsArray& coords,
const GrGLProcessor::TextureSamplerArray& samplers) {
SkASSERT(fFragmentProcessor);
SkASSERT(fGLFragmentProcessor);
fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
coords, samplers);
// this will not leak because it hasa already been used by createGLInstance
fGLFragmentProcessor = NULL;
fFragmentProcessor = NULL;
}
AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
~AutoStageAdvance() { fPB->exitStage(); }
private:
GrGLProgramBuilder* fBuilder;
const GrFragmentProcessor* fFragmentProcessor;
GrGLFragmentProcessor* fGLFragmentProcessor;
GrGLProgramBuilder* fPB;
};
void exitStage() { fOutOfStage = true; }
void enterStage() { fOutOfStage = false; }
int stageIndex() const { return fStageIndex; }
typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
typedef GrGLProgramDataManager::UniformInfo UniformInfo;
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
// number of each input/output type in a single allocation block, used by many builders
static const int kVarsPerBlock;
BuiltinUniformHandles fUniformHandles;
GrGLVertexBuilder fVS;
GrGLGeometryBuilder fGS;
GrGLFragmentShaderBuilder fFS;
bool fOutOfStage;
int fStageIndex;
SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
const GrOptDrawState& fOptState;
const GrGLProgramDesc& fDesc;
GrGpuGL* fGpu;
UniformInfoArray fUniforms;
friend class GrGLShaderBuilder;
friend class GrGLVertexBuilder;
friend class GrGLFragmentShaderBuilder;
friend class GrGLGeometryBuilder;
};
/**
* This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
* and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
* state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
*
* TODO We really don't need this class to have an array of processors. It makes sense for it
* to just have one, also break out the transforms
*/
class GrGLInstalledProcessors : public SkRefCnt {
public:
GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
: fGLProcessors(reserveCount)
, fSamplers(reserveCount)
, fTransforms(reserveCount)
, fHasExplicitLocalCoords(hasExplicitLocalCoords) {
}
virtual ~GrGLInstalledProcessors();
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
struct Sampler {
SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
UniformHandle fUniform;
int fTextureUnit;
};
GrGLProcessorEmitterInterface* fEffectEmitter;
CodeStage fCodeStage;
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
BuiltinUniformHandles fUniformHandles;
bool fFragOnly;
int fTexCoordSetCnt;
GrGLuint fProgramID;
GrGLFragmentShaderBuilder fFS;
SeparableVaryingInfoArray fSeparableVaryingInfos;
class ShaderVarHandle {
public:
bool isValid() const { return fHandle > -1; }
ShaderVarHandle() : fHandle(-1) {}
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
int handle() const { SkASSERT(this->isValid()); return fHandle; }
UniformHandle convertToUniformHandle() {
SkASSERT(this->isValid());
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
}
private:
virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[],
GrGLSLExpr4* inputColor,
GrGLSLExpr4* inputCoverage) = 0;
/*
* Subclasses override emitEffect below to emit data and code for a specific single effect
*/
virtual void emitEffect(const GrProcessorStage&,
const GrProcessorKey&,
const char* outColor,
const char* inColor,
int stageIndex) = 0;
private:
int fHandle;
};
/*
* Because we have fragment only builders, and those builders need to implement a subclass
* of program effects, we have to have base classes overload the program effects here
*/
virtual GrGLProgramEffects* getProgramEffects() = 0;
struct Transform {
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
ShaderVarHandle fHandle;
SkMatrix fCurrentValue;
GrSLType fType;
};
/**
* Compiles all the shaders, links them into a program, and writes the program id to the output
* struct.
**/
bool finish();
void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
GrGLFragmentProcessorEmitter fGrProcessorEmitter;
const GrOptDrawState& fOptState;
const GrGLProgramDesc& fDesc;
GrGpuGL* fGpu;
UniformInfoArray fUniforms;
SkTArray<GrGLProcessor*> fGLProcessors;
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
SkTArray<SkSTArray<2, Transform, true> > fTransforms;
bool fHasExplicitLocalCoords;
friend class GrGLShaderBuilder;
friend class GrGLVertexShaderBuilder;

View File

@ -6,7 +6,7 @@
*/
#include "GrGLShaderBuilder.h"
#include "GrGLFullProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
#include "../GrGLShaderVar.h"
@ -53,13 +53,12 @@ void append_texture_lookup(SkString* out,
out->appendf(".%s", swizzle);
}
}
static const int kVarsPerBlock = 8;
}
GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
: fProgramBuilder(program)
, fInputs(kVarsPerBlock)
, fOutputs(kVarsPerBlock)
, fInputs(GrGLProgramBuilder::kVarsPerBlock)
, fOutputs(GrGLProgramBuilder::kVarsPerBlock)
, fFeaturesAddedMask(0) {
}
@ -143,6 +142,13 @@ void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionNam
}
}
void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
for (int i = 0; i < vars.count(); ++i) {
vars[i].appendDecl(fProgramBuilder->ctxInfo(), out);
out->append(";\n");
}
}
void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
const char* coordName,
uint32_t configComponentMask,
@ -155,8 +161,3 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
swizzle,
kVec2f_GrSLType);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program)
: INHERITED(program)
, fFullProgramBuilder(program) {}

View File

@ -9,21 +9,12 @@
#define GrGLShaderBuilder_DEFINED
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h"
#include "GrBackendProcessorFactory.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "SkTypes.h"
#include <stdarg.h>
class GrGLContextInfo;
class GrProcessorStage;
class GrGLProgramDesc;
class GrGLProgramBuilder;
class GrGLFullProgramBuilder;
/**
base class for all shaders builders
@ -32,6 +23,7 @@ class GrGLShaderBuilder {
public:
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
typedef GrGLProcessor::TextureSampler TextureSampler;
GrGLShaderBuilder(GrGLProgramBuilder* program);
void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
@ -112,7 +104,7 @@ public:
GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
/**
* Helper for begining and ending a block in the fragment code.
* Helper for begining and ending a block in the shader code.
*/
class ShaderBlock {
public:
@ -127,7 +119,10 @@ public:
private:
GrGLShaderBuilder* fBuilder;
};
protected:
typedef GrTAllocator<GrGLShaderVar> VarArray;
void appendDecls(const VarArray& vars, SkString* out) const;
/*
* this super low level function is just for use internally to builders
@ -142,8 +137,6 @@ protected:
*/
void addFeature(uint32_t featureBit, const char* extensionName);
typedef GrTAllocator<GrGLShaderVar> VarArray;
GrGLProgramBuilder* fProgramBuilder;
SkString fCode;
@ -154,21 +147,4 @@ protected:
VarArray fOutputs;
uint32_t fFeaturesAddedMask;
};
/*
* Full Shader builder is the base class for shaders which are only accessible through full program
* builder, ie vertex, geometry, and later TCU / TES. Using this base class, they can access the
* full program builder functionality through the full program pointer
*/
class GrGLFullShaderBuilder : public GrGLShaderBuilder {
public:
GrGLFullShaderBuilder(GrGLFullProgramBuilder* program);
GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; }
protected:
GrGLFullProgramBuilder* fFullProgramBuilder;
private:
typedef GrGLShaderBuilder INHERITED;
};
#endif

View File

@ -6,46 +6,25 @@
*/
#include "GrGLVertexShaderBuilder.h"
#include "GrGLFullProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrGLShaderStringBuilder.h"
#include "../GrGpuGL.h"
#include "../../GrOptDrawState.h"
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
namespace {
inline const char* color_attribute_name() { return "inColor"; }
inline const char* coverage_attribute_name() { return "inCoverage"; }
}
static const char* color_attribute_name() { return "inColor"; }
static const char* coverage_attribute_name() { return "inCoverage"; }
GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program)
: INHERITED(program)
, fPositionVar(NULL)
, fLocalCoordsVar(NULL) {
}
bool GrGLVertexShaderBuilder::addAttribute(const GrShaderVar& var) {
SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
for (int i = 0; i < fInputs.count(); ++i) {
const GrGLShaderVar& attr = fInputs[i];
// if attribute already added, don't add it again
if (attr.getName().equals(var.getName())) {
return false;
}
}
fInputs.push_back(var);
return true;
, fLocalCoordsVar(NULL)
, fEffectAttribOffset(0) {
}
void GrGLVertexShaderBuilder::emitAttributes(const GrGeometryProcessor& gp) {
const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
int numAttributes = vars.count();
for (int a = 0; a < numAttributes; ++a) {
this->addAttribute(vars[a]);
}
}
void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
SkString* GrGLVertexBuilder::addVarying(GrSLType type, const char* name,
const char** vsOutName) {
fOutputs.push_back();
fOutputs.back().setType(type);
fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
@ -54,30 +33,88 @@ void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const
if (vsOutName) {
*vsOutName = fOutputs.back().getName().c_str();
}
return fOutputs.back().accessName();
}
void GrGLVertexBuilder::setupLocalCoords() {
fPositionVar = &fInputs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) {
fLocalCoordsVar = &fInputs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
"inLocalCoords");
} else {
fLocalCoordsVar = fPositionVar;
}
fEffectAttribOffset = fInputs.count();
}
void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
GrGpuGL* gpu = fProgramBuilder->gpu();
void GrGLVertexBuilder::transformGLToSkiaCoords() {
const char* viewMName;
fProgramBuilder->fUniformHandles.fViewMatrixUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType,
"ViewM",
&viewMName);
// Transform the position into Skia's device coords.
this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);", viewMName, fPositionVar->c_str());
}
void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) {
SkString name(inName);
const char *vsName, *fsName;
fProgramBuilder->addVarying(kVec4f_GrSLType, name.c_str(), &vsName, &fsName);
name.prepend("in");
this->addAttribute(GrShaderVar(name.c_str(),
kVec4f_GrSLType,
GrShaderVar::kAttribute_TypeModifier));
this->codeAppendf("%s = %s;", vsName, name.c_str());
*out = fsName;
fEffectAttribOffset++;
}
void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) {
const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
int numAttributes = vars.count();
for (int a = 0; a < numAttributes; ++a) {
this->addAttribute(vars[a]);
}
}
void GrGLVertexBuilder::transformSkiaToGLCoords() {
const char* rtAdjustName;
fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kVec4f_GrSLType,
"rtAdjustment",
&rtAdjustName);
// Transform from Skia's device coords to GL's normalized device coords.
this->codeAppendf("gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
rtAdjustName, rtAdjustName);
}
void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
// Bind the attrib locations to same values for all shaders
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->header();
SkASSERT(-1 != header.fPositionAttributeIndex);
GL_CALL(BindAttribLocation(programId,
GL_CALL(BindAttribLocation(programID,
header.fPositionAttributeIndex,
fPositionVar->c_str()));
if (-1 != header.fLocalCoordAttributeIndex) {
GL_CALL(BindAttribLocation(programId,
GL_CALL(BindAttribLocation(programID,
header.fLocalCoordAttributeIndex,
fLocalCoordsVar->c_str()));
}
if (-1 != header.fColorAttributeIndex) {
GL_CALL(BindAttribLocation(programId,
GL_CALL(BindAttribLocation(programID,
header.fColorAttributeIndex,
color_attribute_name()));
}
if (-1 != header.fCoverageAttributeIndex) {
GL_CALL(BindAttribLocation(programId,
GL_CALL(BindAttribLocation(programID,
header.fCoverageAttributeIndex,
coverage_attribute_name()));
}
@ -86,6 +123,7 @@ void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
const GrVertexAttrib* vaPtr = optState.getVertexAttribs();
const int vaCount = optState.getVertexAttribCount();
// We start binding attributes after builtins
int i = fEffectAttribOffset;
for (int index = 0; index < vaCount; index++) {
if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) {
@ -97,22 +135,22 @@ void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
index != header.fCoverageAttributeIndex);
// We should never find another effect attribute if we have bound everything
SkASSERT(i < fInputs.count());
GL_CALL(BindAttribLocation(programId, index, fInputs[i].c_str()));
GL_CALL(BindAttribLocation(programID, index, fInputs[i].c_str()));
i++;
}
// Make sure we bound everything
SkASSERT(fInputs.count() == i);
}
bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
GrGpuGL* gpu = fProgramBuilder->gpu();
const GrGLContext& glCtx = gpu->glContext();
const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
this->appendDecls(fInputs, &vertShaderSrc);
this->appendDecls(fOutputs, &vertShaderSrc);
vertShaderSrc.append("void main() {");
vertShaderSrc.append(fCode);
vertShaderSrc.append("}\n");
@ -126,72 +164,15 @@ bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
return true;
}
void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
const char* rtAdjustName;
fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kVec4f_GrSLType,
"rtAdjustment",
&rtAdjustName);
// Transform from Skia's device coords to GL's normalized device coords.
this->codeAppendf(
"gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
rtAdjustName, rtAdjustName);
}
void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
fPositionVar = &fInputs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
if (-1 != header.fLocalCoordAttributeIndex) {
fLocalCoordsVar = &fInputs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
"inLocalCoords");
} else {
fLocalCoordsVar = fPositionVar;
}
const char* viewMName;
fProgramBuilder->fUniformHandles.fViewMatrixUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType,
"ViewM",
&viewMName);
// Transform the position into Skia's device coords.
this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
viewMName, fPositionVar->c_str());
// we output point size in the GS if present
if (header.fEmitsPointSize
#if GR_GL_EXPERIMENTAL_GS
&& !header.fExperimentalGS
#endif
) {
this->codeAppend("gl_PointSize = 1.0;");
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
this->addAttribute(GrShaderVar(color_attribute_name(),
kVec4f_GrSLType,
GrShaderVar::kAttribute_TypeModifier));
const char *vsName, *fsName;
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
this->codeAppendf("%s = %s;", vsName, color_attribute_name());
*color = fsName;
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
this->addAttribute(GrShaderVar(coverage_attribute_name(),
kVec4f_GrSLType,
GrShaderVar::kAttribute_TypeModifier));
const char *vsName, *fsName;
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
*coverage = fsName;
}
fEffectAttribOffset = fInputs.count();
bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) {
SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
for (int i = 0; i < fInputs.count(); ++i) {
const GrGLShaderVar& attr = fInputs[i];
// if attribute already added, don't add it again
if (attr.getName().equals(var.getName())) {
return false;
}
}
fInputs.push_back(var);
return true;
}

View File

@ -7,26 +7,22 @@
#ifndef GrGLVertexShader_DEFINED
#define GrGLVertexShader_DEFINED
#include "GrGLShaderBuilder.h"
class GrGLProgramBuilder;
class GrGLVertexShaderBuilder : public GrGLFullShaderBuilder {
// TODO we only actually ever need to return a GrGLShaderBuilder for this guy, none of the below
// functions need to be part of VertexShaderBuilder's public interface
class GrGLVertexBuilder : public GrGLShaderBuilder {
public:
GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program);
/*
* this call is only for GrGLProgramEffects' internal use
*/
void emitAttributes(const GrGeometryProcessor& gp);
GrGLVertexBuilder(GrGLProgramBuilder* program);
/**
* Are explicit local coordinates provided as input to the vertex shader.
*/
bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
const SkString* getEffectAttributeName(int attributeIndex) const;
/** Returns a vertex attribute that represents the local coords in the VS. This may be the same
as positionAttribute() or it may not be. It depends upon whether the rendering code
specified explicit local coords or not in the GrDrawState. */
@ -37,28 +33,25 @@ public:
*/
const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
private:
/*
* Add attribute will push a new attribute onto the end. It will also assert if there is
* a duplicate attribute
* Internal call for GrGLProgramBuilder.addVarying
*/
bool addAttribute(const GrShaderVar& var);
/*
* Internal call for GrGLFullProgramBuilder.addVarying
*/
void addVarying(GrSLType type,
const char* name,
const char** vsOutName);
SkString* addVarying(GrSLType type, const char* name, const char** vsOutName);
/*
* private helpers for compilation by GrGLProgramBuilder
*/
void bindProgramLocations(GrGLuint programId);
void setupLocalCoords();
void transformGLToSkiaCoords();
void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out);
void emitAttributes(const GrGeometryProcessor& gp);
void transformSkiaToGLCoords();
void bindVertexAttributes(GrGLuint programID);
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage);
void emitCodeAfterEffects();
private:
// an internal call which checks for uniquness of a var before adding it to the list of inputs
bool addAttribute(const GrShaderVar& var);
struct AttributePair {
void set(int index, const SkString& name) {
fIndex = index; fName = name;
@ -71,9 +64,7 @@ private:
GrGLShaderVar* fLocalCoordsVar;
int fEffectAttribOffset;
friend class GrGLFullProgramBuilder;
typedef GrGLFullShaderBuilder INHERITED;
typedef GrGLShaderBuilder INHERITED;
};
#endif

View File

@ -16,6 +16,7 @@
#include "GrContextFactory.h"
#include "GrOptDrawState.h"
#include "effects/GrConfigConversionEffect.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLPathRendering.h"
#include "gl/GrGpuGL.h"
#include "SkChecksum.h"
@ -24,7 +25,7 @@
static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
bool* readsFragPosition, bool* requiresVertexShader) {
if (stage.getFragmentProcessor()->willReadDstColor()) {
if (stage.getProcessor()->willReadDstColor()) {
*readsDst = true;
}
if (stage.getProcessor()->willReadFragmentPosition()) {
@ -335,12 +336,14 @@ bool GrGpuGL::programUnitTest(int maxStages) {
SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
*this->caps(),
drawType));
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
*optState.get(),
pdesc,
geometryProcessor.get(),
stages,
stages + numColorStages));
SkAutoTUnref<GrGLProgram> program(
GrGLProgramBuilder::CreateProgram(*optState,
pdesc,
drawType,
geometryProcessor,
stages,
stages + numColorStages,
this));
for (int s = 0; s < numStages; ++s) {
SkDELETE(stages[s]);
}