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:

Review URL: https://codereview.chromium.org/611653002
This commit is contained in:
joshualitt 2014-10-07 12:16:35 -07:00 committed by Commit bot
parent 9323b8b8e1
commit fe1233c3f1
45 changed files with 1708 additions and 2029 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
#include "GrAARectRenderer.h" #include "GrAARectRenderer.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "gl/builders/GrGLFullProgramBuilder.h" #include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLProcessor.h" #include "gl/GrGLProcessor.h"
#include "gl/GrGLGeometryProcessor.h" #include "gl/GrGLGeometryProcessor.h"
#include "GrTBackendProcessorFactory.h" #include "GrTBackendProcessorFactory.h"
@ -41,7 +41,7 @@ public:
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {} : INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder, virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor, const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key, const GrProcessorKey& key,
const char* outputColor, const char* outputColor,
@ -55,10 +55,10 @@ public:
builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect(); 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()); 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 // 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 insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 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&) GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {} : INHERITED (factory) {}
virtual void emitCode(GrGLFullProgramBuilder* builder, virtual void emitCode(GrGLGPBuilder* builder,
const GrGeometryProcessor& geometryProcessor, const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key, const GrProcessorKey& key,
const char* outputColor, const char* outputColor,
@ -181,7 +181,7 @@ public:
&vsRectEdgeName, &fsRectEdgeName); &vsRectEdgeName, &fsRectEdgeName);
const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>(); const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str()); vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
// setup the varying for width/2+.5 and height/2+.5 // setup the varying for width/2+.5 and height/2+.5
@ -192,7 +192,7 @@ public:
vsWidthHeightName, vsWidthHeightName,
rectEffect.inWidthHeight().c_str()); rectEffect.inWidthHeight().c_str());
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// TODO: compute all these offsets, spans, and scales in the VS // 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 insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 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()) { if (this->hasGeometryProcessor()) {
const GrGeometryStage& stage = *this->getGeometryProcessor(); const GrGeometryStage& stage = *this->getGeometryProcessor();
const GrGeometryProcessor* gp = stage.getGeometryProcessor(); const GrGeometryProcessor* gp = stage.getProcessor();
SkASSERT(gp); SkASSERT(gp);
// make sure that any attribute indices have the correct binding type, that the attrib // 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 // 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. // Run through the coverage stages and see if the coverage will be all ones at the end.
if (this->hasGeometryProcessor()) { if (this->hasGeometryProcessor()) {
const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor(); const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
gp->computeInvariantOutput(&inout); gp->computeInvariantOutput(&inout);
} }
for (int s = 0; s < this->numCoverageStages(); ++s) { for (int s = 0; s < this->numCoverageStages(); ++s) {
@ -436,13 +436,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
bool GrDrawState::willEffectReadDstColor() const { bool GrDrawState::willEffectReadDstColor() const {
if (!this->isColorWriteDisabled()) { if (!this->isColorWriteDisabled()) {
for (int s = 0; s < this->numColorStages(); ++s) { for (int s = 0; s < this->numColorStages(); ++s) {
if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) { if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
return true; return true;
} }
} }
} }
for (int s = 0; s < this->numCoverageStages(); ++s) { for (int s = 0; s < this->numCoverageStages(); ++s) {
if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) { if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
return true; return true;
} }
} }

View File

@ -391,7 +391,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
SkASSERT(drawState.getRenderTarget()); SkASSERT(drawState.getRenderTarget());
if (drawState.hasGeometryProcessor()) { if (drawState.hasGeometryProcessor()) {
const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor(); const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
int numTextures = gp->numTextures(); int numTextures = gp->numTextures();
for (int t = 0; t < numTextures; ++t) { for (int t = 0; t < numTextures; ++t) {
GrTexture* texture = gp->texture(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) { 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()) { if (!fp->willUseInputColor()) {
firstColorStage = i; firstColorStage = i;
fInputColorIsUsed = false; fInputColorIsUsed = false;
@ -270,10 +270,10 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
} }
static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) { static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
if (stage.getFragmentProcessor()->willReadDstColor()) { if (stage.getProcessor()->willReadDstColor()) {
*readsDst = true; *readsDst = true;
} }
if (stage.getFragmentProcessor()->willReadFragmentPosition()) { if (stage.getProcessor()->willReadFragmentPosition()) {
*readsFragPosition = true; *readsFragPosition = true;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,6 @@
#include "GrGLProgram.h" #include "GrGLProgram.h"
#include "builders/GrGLFullProgramBuilder.h"
#include "builders/GrGLFragmentOnlyProgramBuilder.h"
#include "GrAllocator.h" #include "GrAllocator.h"
#include "GrProcessor.h" #include "GrProcessor.h"
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
@ -23,45 +21,58 @@
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, /**
const GrOptDrawState& optState, * Retrieves the final matrix that a transform needs to apply to its source coords.
const GrGLProgramDesc& desc, */
const GrGeometryStage* geometryProcessor, static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
const GrFragmentStage* colorStages[], bool useExplicitLocalCoords,
const GrFragmentStage* coverageStages[]) { int transformIdx) {
SkAutoTDelete<GrGLProgramBuilder> builder; const GrCoordTransform& coordTransform =
if (desc.getHeader().fUseFragShaderOnly) { processorStage.getProcessor()->coordTransform(transformIdx);
SkASSERT(gpu->glCaps().pathRenderingSupport()); SkMatrix combined;
SkASSERT(gpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::FixedFunction_TexturingMode); if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
SkASSERT(NULL == geometryProcessor); // If we have explicit local coords then we shouldn't need a coord change.
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc))); const SkMatrix& ccm =
useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
combined.setConcat(coordTransform.getMatrix(), ccm);
} else { } else {
builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc))); combined = coordTransform.getMatrix();
} }
if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) { if (coordTransform.reverseY()) {
SkASSERT(0 != builder->getProgramID()); // combined.postScale(1,-1);
return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder)); // 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, GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc, const GrGLProgramDesc& desc,
const GrGLProgramBuilder& builder) const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledProcessors* geometryProcessor,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors)
: fColor(GrColor_ILLEGAL) : fColor(GrColor_ILLEGAL)
, fCoverage(GrColor_ILLEGAL) , fCoverage(GrColor_ILLEGAL)
, fDstCopyTexUnit(-1) , fDstCopyTexUnit(-1)
, fBuiltinUniformHandles(builder.getBuiltinUniformHandles()) , fBuiltinUniformHandles(builtinUniforms)
, fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor())) , fProgramID(programID)
, fColorEffects(SkRef(builder.getColorEffects())) , fGeometryProcessor(SkSafeRef(geometryProcessor))
, fCoverageEffects(SkRef(builder.getCoverageEffects())) , fColorEffects(SkRef(colorProcessors))
, fProgramID(builder.getProgramID()) , fCoverageEffects(SkRef(coverageProcessors))
, fHasVertexShader(builder.hasVertexShader())
, fTexCoordSetCnt(builder.getTexCoordSetCount())
, fDesc(desc) , fDesc(desc)
, fGpu(gpu) , fGpu(gpu)
, fProgramDataManager(gpu, this, builder) { , fProgramDataManager(gpu, uniforms) {
this->initSamplerUniforms(); this->initSamplerUniforms();
} }
@ -83,12 +94,42 @@ void GrGLProgram::initSamplerUniforms() {
fDstCopyTexUnit = texUnitIdx++; fDstCopyTexUnit = texUnitIdx++;
} }
if (fGeometryProcessor.get()) { if (fGeometryProcessor.get()) {
fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx); this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
} }
fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx); this->initSamplers(fColorEffects.get(), &texUnitIdx);
fCoverageEffects->initSamplers(fProgramDataManager, &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, void GrGLProgram::setData(const GrOptDrawState& optState,
@ -126,21 +167,39 @@ void GrGLProgram::setData(const GrOptDrawState& optState,
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); 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()) { if (fGeometryProcessor.get()) {
SkASSERT(geometryProcessor); SkASSERT(geometryProcessor);
fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor); this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
} }
fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages); this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages); this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
// PathTexGen state applies to the the fixed function vertex shader. For // Some of GrGLProgram subclasses need to update state here
// custom shaders, it's ignored, so we don't need to change the texgen this->didSetData(drawType);
// settings in that case. }
if (!fHasVertexShader) {
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); 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, void GrGLProgram::setColor(const GrOptDrawState& optState,
GrColor color, GrColor color,
SharedGLState* sharedState) { SharedGLState* sharedState) {
@ -220,22 +279,25 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState,
void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrOptDrawState& optState) { 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()->width()) {
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(); const GrRenderTarget* rt = optState.getRenderTarget();
SkISize size; SkISize size;
size.set(rt->width(), rt->height()); size.set(rt->width(), rt->height());
if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
// Load the RT height uniform if it is needed to y-flip gl_FragCoord. fMatrixState.fRenderTargetSize != size ||
if (fBuiltinUniformHandles.fRTHeightUni.isValid() && !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
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())) {
SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = optState.getViewMatrix(); fMatrixState.fViewMatrix = optState.getViewMatrix();
@ -251,3 +313,115 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 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 #define GrGLProgram_DEFINED
#include "builders/GrGLProgramBuilder.h" #include "builders/GrGLProgramBuilder.h"
#include "builders/GrGLNvprProgramBuilder.h"
#include "GrDrawState.h" #include "GrDrawState.h"
#include "GrGLContext.h" #include "GrGLContext.h"
#include "GrGLProgramDesc.h" #include "GrGLProgramDesc.h"
@ -21,7 +22,7 @@
#include "SkXfermode.h" #include "SkXfermode.h"
class GrGLProcessor; class GrGLProcessor;
class GrGLProgramEffects; class GrGLInstalledProcessors;
class GrGLProgramBuilder; class GrGLProgramBuilder;
/** /**
@ -39,13 +40,6 @@ public:
typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles; 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(); virtual ~GrGLProgram();
/** /**
@ -60,7 +54,10 @@ public:
*/ */
GrGLuint programID() const { return fProgramID; } 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 * 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 const GrDeviceCoordTexture* dstCopy, // can be NULL
SharedGLState*); SharedGLState*);
private: protected:
typedef GrGLProgramDataManager::UniformHandle UniformHandle; typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
GrGLProgram(GrGpuGL*, GrGLProgram(GrGpuGL*,
const GrGLProgramDesc&, const GrGLProgramDesc&,
const GrGLProgramBuilder&); const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledProcessors* geometryProcessor,
GrGLInstalledProcessors* colorProcessors,
GrGLInstalledProcessors* coverageProcessors);
// Sets the texture units for samplers. // Sets the texture units for samplers.
void initSamplerUniforms(); void initSamplerUniforms();
void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
// Helper for setData(). Makes GL calls to specify the initial color when there is not // Helper for setData(). Makes GL calls to specify the initial color when there is not
// per-vertex colors. // per-vertex colors.
@ -179,29 +183,134 @@ private:
// per-vertex coverages. // per-vertex coverages.
void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*); 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 // 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) // these reflect the current values of uniforms (GL uniform values travel with program)
MatrixState fMatrixState; MatrixState fMatrixState;
GrColor fColor; GrColor fColor;
GrColor fCoverage; GrColor fCoverage;
int fDstCopyTexUnit; int fDstCopyTexUnit;
BuiltinUniformHandles fBuiltinUniformHandles;
GrGLuint fProgramID;
BuiltinUniformHandles fBuiltinUniformHandles; // the installed effects
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor; SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
SkAutoTUnref<GrGLProgramEffects> fColorEffects; SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects; SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
GrGLuint fProgramID;
bool fHasVertexShader;
int fTexCoordSetCnt;
GrGLProgramDesc fDesc; GrGLProgramDesc fDesc;
GrGpuGL* fGpu; GrGpuGL* fGpu;
GrGLProgramDataManager fProgramDataManager;
GrGLProgramDataManager fProgramDataManager; friend class GrGLProgramBuilder;
typedef SkRefCnt INHERITED; 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 #endif

View File

@ -5,9 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLPathRendering.h" #include "gl/GrGLPathRendering.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h" #include "gl/GrGLUniformHandle.h"
#include "gl/GrGpuGL.h" #include "gl/GrGpuGL.h"
#include "SkMatrix.h" #include "SkMatrix.h"
@ -16,16 +14,13 @@
SkASSERT(arrayCount <= uni.fArrayCount || \ SkASSERT(arrayCount <= uni.fArrayCount || \
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount)) (1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoArray& uniforms)
GrGLProgram* program, : fGpu(gpu) {
const GrGLProgramBuilder& builder) int count = uniforms.count();
: fGpu(gpu),
fProgram(program) {
int count = builder.getUniformInfos().count();
fUniforms.push_back_n(count); fUniforms.push_back_n(count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Uniform& uniform = fUniforms[i]; Uniform& uniform = fUniforms[i];
const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i]; const UniformInfo& builderUniform = uniforms[i];
SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() || SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
builderUniform.fVariable.getArrayCount() > 0); builderUniform.fVariable.getArrayCount() > 0);
SkDEBUGCODE( SkDEBUGCODE(
@ -38,26 +33,13 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
uniform.fVSLocation = builderUniform.fLocation; uniform.fVSLocation = builderUniform.fLocation;
} else { } else {
uniform.fVSLocation = kUnusedUniform; uniform.fVSLocation = kUnusedUniform;
} }
if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) { if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) {
uniform.fFSLocation = builderUniform.fLocation; uniform.fFSLocation = builderUniform.fLocation;
} else { } else {
uniform.fFSLocation = kUnusedUniform; 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 { void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
@ -276,14 +258,3 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix
}; };
this->setMatrix3f(u, mt); 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(). friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
}; };
class VaryingHandle : public ShaderResourceHandle { struct UniformInfo {
public: GrGLShaderVar fVariable;
/** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder. uint32_t fVisibility;
* The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/ GrGLint fLocation;
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().
}; };
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 /** 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. * 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 // convenience method for uploading a SkMatrix to a 3x3 matrix uniform
void setSkMatrix(UniformHandle, const SkMatrix&) const; void setSkMatrix(UniformHandle, const SkMatrix&) const;
void setProgramPathFragmentInputTransform(VaryingHandle i,
unsigned components,
const SkMatrix& matrix) const;
private: private:
enum { enum {
kUnusedUniform = -1, kUnusedUniform = -1,
@ -112,19 +104,10 @@ private:
int fArrayCount; int fArrayCount;
); );
}; };
struct Varying {
GrGLint fLocation;
SkDEBUGCODE(
GrSLType fType;
);
};
SkTArray<Uniform, true> fUniforms; SkTArray<Uniform, true> fUniforms;
SkTArray<Varying, true> fVaryings;
GrGpuGL* fGpu; GrGpuGL* fGpu;
GrGLProgram* fProgram;
typedef SkRefCnt INHERITED; typedef SkRefCnt INHERITED;
}; };
#endif #endif

View File

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

View File

@ -247,11 +247,10 @@ private:
// visible to GrGLProcessors. Then make public accessors as necessary and remove friends. // visible to GrGLProcessors. Then make public accessors as necessary and remove friends.
friend class GrGLProgram; friend class GrGLProgram;
friend class GrGLProgramBuilder; friend class GrGLProgramBuilder;
friend class GrGLFullProgramBuilder; friend class GrGLLegacyNvprProgramBuilder;
friend class GrGLFragmentOnlyProgramBuilder; friend class GrGLVertexBuilder;
friend class GrGLVertexShaderBuilder;
friend class GrGLFragmentShaderBuilder; friend class GrGLFragmentShaderBuilder;
friend class GrGLGeometryShaderBuilder; friend class GrGLGeometryBuilder;
}; };
#endif #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(); ~ProgramCache();
void abandon(); void abandon();
GrGLProgram* getProgram(const GrOptDrawState& optState, GrGLProgram* getProgram(const GrOptDrawState&,
const GrGLProgramDesc& desc, const GrGLProgramDesc&,
DrawType,
const GrGeometryStage* geometryProcessor, const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[], const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]); const GrFragmentStage* coverageStages[]);

View File

@ -7,6 +7,7 @@
#include "GrGpuGL.h" #include "GrGpuGL.h"
#include "builders/GrGLProgramBuilder.h"
#include "GrProcessor.h" #include "GrProcessor.h"
#include "GrGLProcessor.h" #include "GrGLProcessor.h"
#include "GrGLPathRendering.h" #include "GrGLPathRendering.h"
@ -92,6 +93,7 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc, const GrGLProgramDesc& desc,
DrawType type,
const GrGeometryStage* geometryProcessor, const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[], const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]) { const GrFragmentStage* coverageStages[]) {
@ -129,8 +131,9 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
#ifdef PROGRAM_CACHE_STATS #ifdef PROGRAM_CACHE_STATS
++fCacheMisses; ++fCacheMisses;
#endif #endif
GrGLProgram* program = GrGLProgram::Create(fGpu, optState, desc, geometryProcessor, GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
colorStages, coverageStages); geometryProcessor, colorStages,
coverageStages, fGpu);
if (NULL == program) { if (NULL == program) {
return NULL; return NULL;
} }
@ -254,6 +257,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
desc, desc,
type,
geometryProcessor, geometryProcessor,
colorStages.begin(), colorStages.begin(),
coverageStages.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 "GrGLProgramBuilder.h"
#include "../GrGpuGL.h" #include "../GrGpuGL.h"
namespace { #define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
// ES2 FS only guarantees mediump and lowp support // ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
static const char kDstCopyColorName[] = "_dstColor"; const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
inline const char* declared_color_output_name() { return "fsColorOut"; } static const char* declared_color_output_name() { return "fsColorOut"; }
inline const char* dual_source_output_name() { return "dualSourceOut"; } static const char* dual_source_output_name() { return "dualSourceOut"; }
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
GrGLStandard standard, GrGLStandard standard,
SkString* str) { SkString* str) {
// Desktop GLSL has added precision qualifiers but they don't do anything. // 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( GrGLFragmentShaderBuilder::DstReadKey
const GrTexture* dstCopy, const GrGLCaps& caps) { GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
const GrGLCaps& caps) {
uint32_t key = kYesDstRead_DstReadKeyBit; uint32_t key = kYesDstRead_DstReadKeyBit;
if (caps.fbFetchSupport()) { if (caps.fbFetchSupport()) {
return key; return key;
@ -60,8 +60,9 @@ GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
return static_cast<DstReadKey>(key); return static_cast<DstReadKey>(key);
} }
GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition( GrGLFragmentShaderBuilder::FragPosKey
const GrRenderTarget* dst, const GrGLCaps&) { GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
const GrGLCaps&) {
if (kTopLeft_GrSurfaceOrigin == dst->origin()) { if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
return kTopLeftFragPosRead_FragPosKey; return kTopLeftFragPosRead_FragPosKey;
} else { } else {
@ -75,33 +76,9 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
, fHasCustomColorOutput(false) , fHasCustomColorOutput(false)
, fHasSecondaryOutput(false) , fHasSecondaryOutput(false)
, fSetupFragPosition(false) , fSetupFragPosition(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){ , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
} , fHasReadDstColor(false)
, fHasReadFragmentPosition(false) {
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 "";
}
} }
bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
@ -140,15 +117,7 @@ SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
} }
const char* GrGLFragmentShaderBuilder::fragmentPosition() { const char* GrGLFragmentShaderBuilder::fragmentPosition() {
GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage; fHasReadFragmentPosition = true;
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 "";
}
}
GrGpuGL* gpu = fProgramBuilder->gpu(); GrGpuGL* gpu = fProgramBuilder->gpu();
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers // 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"; static const char* kCoordName = "fragCoordYDown";
if (!fSetupFragPosition) { if (!fSetupFragPosition) {
// temporarily change the stage index because we're inserting non-stage code. // 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()); SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
const char* rtHeightName; const char* rtHeightName;
fProgramBuilder->fUniformHandles.fRTHeightUni = fProgramBuilder->fUniformHandles.fRTHeightUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kFloat_GrSLType,
"RTHeight", "RTHeight",
&rtHeightName); &rtHeightName);
// Using glFragCoord.zw for the last two components tickles an Adreno driver bug that // 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 // 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* GrGLFragmentShaderBuilder::dstColor() {
const char* name, fHasReadDstColor = true;
const char** fsInName,
GrGLShaderVar::Precision fsPrecision) { GrGpuGL* gpu = fProgramBuilder->gpu();
fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision); if (gpu->glCaps().fbFetchSupport()) {
if (fsInName) { this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
*fsInName = name; gpu->glCaps().fbFetchExtensionString());
return gpu->glCaps().fbFetchColorName();
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
return kDstCopyColorName;
} else {
return "";
} }
} }
void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) { void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
GrGpuGL* gpu = fProgramBuilder->gpu(); bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
if (fHasCustomColorOutput) { const char* dstCopyTopLeftName;
GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); 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) { fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); 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, bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
@ -227,10 +304,10 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
gpu->glStandard(), gpu->glStandard(),
&fragShaderSrc); &fragShaderSrc);
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
fProgramBuilder->appendDecls(fInputs, &fragShaderSrc); this->appendDecls(fInputs, &fragShaderSrc);
// We shouldn't have declared outputs on 1.10 // We shouldn't have declared outputs on 1.10
SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc); this->appendDecls(fOutputs, &fragShaderSrc);
fragShaderSrc.append(fFunctions); fragShaderSrc.append(fFunctions);
fragShaderSrc.append("void main() {\n"); fragShaderSrc.append("void main() {\n");
fragShaderSrc.append(fCode); fragShaderSrc.append(fCode);
@ -248,121 +325,21 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
return true; return true;
} }
void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() { void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); if (fHasCustomColorOutput) {
GrGpuGL* gpu = fProgramBuilder->gpu(); GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
///////////////////////////////////////////////////////////////////////////
// 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(";");
} }
if (fHasSecondaryOutput) {
if (k110_GrGLSLGeneration != gpu->glslGeneration()) { GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
fOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier,
declared_color_output_name());
fHasCustomColorOutput = true;
} }
} }
void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) { void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); const char* name,
const char** fsInName,
/////////////////////////////////////////////////////////////////////////// GrGLShaderVar::Precision fsPrecision) {
// write the secondary color output if necessary fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { if (fsInName) {
const char* secondaryOutputName = this->enableSecondaryOutput(); *fsInName = name;
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());
} }
///////////////////////////////////////////////////////////////////////////
// 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 #ifndef GrGLFragmentShaderBuilder_DEFINED
#define GrGLFragmentShaderBuilder_DEFINED #define GrGLFragmentShaderBuilder_DEFINED
#include "GrGLShaderBuilder.h" #include "GrGLShaderBuilder.h"
class GrGLProgramBuilder;
/* /*
* This base class encapsulates the functionality which all GrProcessors are allowed to use in their * This base class encapsulates the functionality which the GP uses to build fragment shaders
* fragment shader
*/ */
class GrGLProcessorFragmentShaderBuilder : public GrGLShaderBuilder { class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
public: public:
GrGLProcessorFragmentShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {} GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
virtual ~GrGLProcessorFragmentShaderBuilder() {} virtual ~GrGLGPFragmentBuilder() {}
/** /**
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile * 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() * 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 * 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: 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 /** 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. */ no effect advertised that it will read the destination. */
virtual const char* dstColor() = 0; virtual const char* dstColor() = 0;
private: private:
typedef GrGLProcessorFragmentShaderBuilder INHERITED; typedef GrGLGPFragmentBuilder INHERITED;
}; };
class GrGLFragmentShaderBuilder : public GrGLFragmentProcessorShaderBuilder { // TODO rename to Fragment Builder
class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
public: public:
typedef uint8_t DstReadKey; typedef uint8_t DstReadKey;
typedef uint8_t FragPosKey; typedef uint8_t FragPosKey;
@ -83,39 +84,42 @@ public:
GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc); 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 bool enableFeature(GLSLFeature) SK_OVERRIDE;
virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords, virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
int index) SK_OVERRIDE; int index) SK_OVERRIDE;
virtual const char* fragmentPosition() 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, void addVarying(GrSLType type,
const char* name, const char* name,
const char** fsInName, const char** fsInName,
GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision); GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision);
/* // As GLProcessors emit code, there are some conditions we need to verify. We use the below
* Private functions used by GrGLProgramBuilder for compilation // state to track this. The reset call is called per processor emitted.
*/ bool hasReadDstColor() const { return fHasReadDstColor; }
void bindProgramLocations(GrGLuint programId); bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; void reset() {
void emitCodeBeforeEffects(); fHasReadDstColor = false;
void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage); fHasReadFragmentPosition = false;
}
/** 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;
private:
/** /**
* Features that should only be enabled by GrGLFragmentShaderBuilder itself. * 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. kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
}; };
// Interpretation of FragPosKey when generating code
enum { enum {
kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed. kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left. kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left. kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
}; };
static const char* kDstCopyColorName;
bool fHasCustomColorOutput; bool fHasCustomColorOutput;
bool fHasSecondaryOutput; bool fHasSecondaryOutput;
bool fSetupFragPosition; bool fSetupFragPosition;
bool fTopLeftFragPosRead; bool fTopLeftFragPosRead;
friend class GrGLProgramBuilder; // some state to verify shaders and effects are consistent, this is reset between effects by
friend class GrGLFullProgramBuilder; // the program creator
bool fHasReadDstColor;
bool fHasReadFragmentPosition;
typedef GrGLFragmentProcessorShaderBuilder INHERITED; friend class GrGLNvprProgramBuilder;
friend class GrGLProgramBuilder;
typedef GrGLFPFragmentBuilder INHERITED;
}; };
#endif #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 "GrGLProgramBuilder.h"
#include "../GrGpuGL.h" #include "../GrGpuGL.h"
GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program) GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
: INHERITED(program) { : INHERITED(program) {
} }
void GrGLGeometryShaderBuilder::addVarying(GrSLType type, void GrGLGeometryBuilder::addVarying(GrSLType type,
const char* name, const char* name,
const char** gsOutName) { const char** gsOutName) {
// if we have a GS take each varying in as an array // 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 { SkTDArray<GrGLuint>* shaderIds) const {
const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext(); const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext();
SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo())); SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()));
geomShaderSrc.append("layout(triangles) in;\n" geomShaderSrc.append("layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n"); "layout(triangle_strip, max_vertices = 6) out;\n");
fProgramBuilder->appendDecls(fInputs, &geomShaderSrc); this->appendDecls(fInputs, &geomShaderSrc);
fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc); this->appendDecls(fOutputs, &geomShaderSrc);
geomShaderSrc.append("void main() {\n"); geomShaderSrc.append("void main() {\n");
geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\n"); "\t\tgl_Position = gl_in[i].gl_Position;\n");

View File

@ -10,12 +10,9 @@
#include "GrGLShaderBuilder.h" #include "GrGLShaderBuilder.h"
class GrGLProgramBuilder; class GrGLGeometryBuilder : public GrGLShaderBuilder {
class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder {
public: public:
GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program); GrGLGeometryBuilder(GrGLProgramBuilder* program);
private:
/* /*
* an internal call for GrGLFullProgramBuilder to add varyings * an internal call for GrGLFullProgramBuilder to add varyings
*/ */
@ -25,8 +22,7 @@ private:
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
friend class GrGLFullProgramBuilder; typedef GrGLShaderBuilder INHERITED;
typedef GrGLFullShaderBuilder INHERITED;
}; };
#endif #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. * found in the LICENSE file.
*/ */
#include "GrGLProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLProgram.h" #include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h" #include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h" #include "gl/GrGLUniformHandle.h"
#include "GrCoordTransform.h"
#include "../GrGpuGL.h" #include "../GrGpuGL.h"
#include "GrGLFragmentShaderBuilder.h" #include "GrCoordTransform.h"
#include "GrGLLegacyNvprProgramBuilder.h"
#include "GrGLNvprProgramBuilder.h"
#include "GrGLProgramBuilder.h" #include "GrGLProgramBuilder.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "GrGLVertexShaderBuilder.h"
#include "SkRTConf.h" #include "SkRTConf.h"
#include "SkTraceEvent.h" #include "SkTraceEvent.h"
namespace {
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) #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) #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 // ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 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, GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
const GrGLProgramDesc& desc) const GrGLProgramDesc& desc)
: fEffectEmitter(NULL) : fVS(this)
, fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly)) , fGS(this)
, fTexCoordSetCnt(0)
, fProgramID(0)
, fFS(this, desc) , fFS(this, desc)
, fSeparableVaryingInfos(kVarsPerBlock) , fOutOfStage(true)
, fGrProcessorEmitter(this) , fStageIndex(-1)
, fOptState(optState) , fOptState(optState)
, fDesc(desc) , fDesc(desc)
, fGpu(gpu) , fGpu(gpu)
, fUniforms(kVarsPerBlock) { , 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) { void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
if ('\0' == prefix) { if ('\0' == prefix) {
*out = name; *out = name;
} else { } else {
out->printf("%c%s", prefix, name); out->printf("%c%s", prefix, name);
} }
if (fCodeStage.inStageCode()) { if (!fOutOfStage) {
if (out->endsWith('_')) { if (out->endsWith('_')) {
// Names containing "__" are reserved. // Names containing "__" are reserved.
out->append("x"); 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); 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, void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
SkString* out) const { SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) { for (int i = 0; i < fUniforms.count(); ++i) {
@ -160,20 +194,127 @@ void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
} }
} }
void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[], const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
int effectCnt, return fGpu->ctxInfo();
const GrGLProgramDesc::EffectKeyProvider& keyProvider, }
GrGLSLExpr4* fsInOutColor) {
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; bool effectEmitted = false;
GrGLSLExpr4 inColor = *fsInOutColor; GrGLSLExpr4 inColor = *fsInOutColor;
GrGLSLExpr4 outColor; GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) { for (int e = 0; e < effectCnt; ++e) {
fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor()); // Program builders have a bit of state we need to clear with each effect
fEffectEmitter = &fGrProcessorEmitter; this->reset();
// calls into the subclass to emit the actual effect into the program effect object const ProcessorStage& stage = *processStages[e];
this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor); 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());
glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(), 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("}");
inColor = outColor;
effectEmitted = true; effectEmitted = true;
} }
@ -182,40 +323,77 @@ void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage
} }
} }
void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage, void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
int effectIndex, SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
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::emitSamplers(const GrProcessor& effect, void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
GrGLProcessor::TextureSamplerArray* outSamplers) { SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
SkTArray<GrGLProgramEffects::Sampler, true>& samplers = SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
this->getProgramEffects()->addSamplers(); }
int numTextures = effect.numTextures();
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); samplers.push_back_n(numTextures);
SkString name; SkString name;
for (int t = 0; t < numTextures; ++t) { for (int t = 0; t < numTextures; ++t) {
@ -224,27 +402,37 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
kSampler2D_GrSLType, kSampler2D_GrSLType,
name.c_str()); name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
(samplers[t].fUniform, effect.textureAccess(t))); (samplers[t].fUniform, processor.textureAccess(t)));
} }
} }
bool GrGLProgramBuilder::finish() { GrGLProgram* GrGLProgramBuilder::finalize() {
SkASSERT(0 == fProgramID); // verify we can get a program id
GL_CALL_RET(fProgramID, CreateProgram()); GrGLuint programID;
if (!fProgramID) { GL_CALL_RET(programID, CreateProgram());
return false; if (0 == programID) {
return NULL;
} }
// compile shaders and bind attributes / uniforms
SkTDArray<GrGLuint> shadersToDelete; SkTDArray<GrGLuint> shadersToDelete;
if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete);
GL_CALL(DeleteProgram(fProgramID)); return NULL;
return false;
} }
if (!this->header().fUseFragShaderOnly) {
this->bindProgramLocations(fProgramID); if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
this->cleanupProgram(programID, shadersToDelete);
GL_CALL(LinkProgram(fProgramID)); 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. // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
bool checkLinked = !fGpu->ctxInfo().isChromium(); bool checkLinked = !fGpu->ctxInfo().isChromium();
@ -252,80 +440,78 @@ bool GrGLProgramBuilder::finish() {
checkLinked = true; checkLinked = true;
#endif #endif
if (checkLinked) { if (checkLinked) {
GrGLint linked = GR_GL_INIT_ZERO; checkLinkStatus(programID);
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;
}
} }
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) { if (!usingBindUniform) {
int count = fUniforms.count(); this->resolveUniformLocations(programID);
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location,
GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = location;
}
} }
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) { for (int i = 0; i < count; ++i) {
GrGLint location; GrGLint location;
GL_CALL_RET(location, GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
GetProgramResourceLocation(programId, fUniforms[i].fLocation = location;
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
} }
} }
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
return fGpu->ctxInfo(); 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 #ifndef GrGLProgramBuilder_DEFINED
#define GrGLProgramBuilder_DEFINED #define GrGLProgramBuilder_DEFINED
#include "GrAllocator.h"
#include "GrBackendProcessorFactory.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrGLFragmentShaderBuilder.h" #include "GrGLFragmentShaderBuilder.h"
#include "GrGLGeometryShaderBuilder.h" #include "GrGLGeometryShaderBuilder.h"
#include "GrGLVertexShaderBuilder.h" #include "GrGLVertexShaderBuilder.h"
#include "SkTypes.h" #include "../GrGLProgramDataManager.h"
#include "gl/GrGLProcessor.h" #include "../GrGLUniformHandle.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h"
#include <stdarg.h> class GrGLInstalledProcessors;
class GrGLContextInfo; /*
class GrProcessorStage; * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
class GrGLProgramDesc; * NO data members because it is used in multiple interface inheritance.
* Heirarchy:
/** * GrGLUniformBuilder
Contains all the incremental state of a shader as it is being built,as well as helpers to * / \
manipulate that state. * GrGLFPBuilder GrGLGPBuilder
*/ * \ /
class GrGLProgramBuilder { * GrGLProgramBuilder(internal use only)
*/
class GrGLUniformBuilder {
public: public:
enum ShaderVisibility { enum ShaderVisibility {
kVertex_Visibility = 0x1, kVertex_Visibility = 0x1,
@ -40,8 +34,127 @@ public:
kFragment_Visibility = 0x4, kFragment_Visibility = 0x4,
}; };
virtual ~GrGLUniformBuilder() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle; 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) // Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles { struct BuiltinUniformHandles {
@ -60,277 +173,168 @@ public:
UniformHandle fDstCopySamplerUni; 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: protected:
typedef GrTAllocator<GrGLShaderVar> VarArray; static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
const GrOptDrawState&,
GrGpu::DrawType,
bool hasGeometryProcessor,
GrGpuGL*);
GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&); GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
const GrOptDrawState& optState() const { return fOptState; } const GrOptDrawState& optState() const { return fOptState; }
const GrGLProgramDesc& desc() const { return fDesc; } const GrGLProgramDesc& desc() const { return fDesc; }
const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
// 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);
// Generates a name for a variable. The generated string will be name prefixed by the prefix // 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 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
// generating stage code. // generating stage code.
void nameVariable(SkString* out, char prefix, const char* name); 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 cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
void resolveProgramLocations(GrGLuint programId); 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; 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: public:
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {} AutoStageRestore(GrGLProgramBuilder* pb)
: fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
bool inStageCode() const { ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
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;
};
private: private:
void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); } GrGLProgramBuilder* fPB;
int fNextIndex; bool fOutOfStage;
int fCurrentIndex; };
const GrProcessorStage* fEffectStage; 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;
}; };
class GrGLProcessorEmitterInterface { class ShaderVarHandle {
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 {
public: public:
GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder) bool isValid() const { return fHandle > -1; }
: fBuilder(builder) ShaderVarHandle() : fHandle(-1) {}
, fFragmentProcessor(NULL) ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
, fGLFragmentProcessor(NULL) {} int handle() const { SkASSERT(this->isValid()); return fHandle; }
virtual ~GrGLFragmentProcessorEmitter() {} UniformHandle convertToUniformHandle() {
void set(const GrFragmentProcessor* fp) { SkASSERT(this->isValid());
SkASSERT(NULL == fFragmentProcessor); return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
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;
} }
private: private:
GrGLProgramBuilder* fBuilder; int fHandle;
const GrFragmentProcessor* fFragmentProcessor;
GrGLFragmentProcessor* fGLFragmentProcessor;
}; };
GrGLProcessorEmitterInterface* fEffectEmitter; struct Transform {
CodeStage fCodeStage; Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor; ShaderVarHandle fHandle;
SkAutoTUnref<GrGLProgramEffects> fColorEffects; SkMatrix fCurrentValue;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects; GrSLType fType;
BuiltinUniformHandles fUniformHandles; };
bool fFragOnly;
int fTexCoordSetCnt;
GrGLuint fProgramID;
GrGLFragmentShaderBuilder fFS;
SeparableVaryingInfoArray fSeparableVaryingInfos;
private: void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor, SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
const GrFragmentStage* colorStages[], SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
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;
/* SkTArray<GrGLProcessor*> fGLProcessors;
* Because we have fragment only builders, and those builders need to implement a subclass SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
* of program effects, we have to have base classes overload the program effects here SkTArray<SkSTArray<2, Transform, true> > fTransforms;
*/ bool fHasExplicitLocalCoords;
virtual GrGLProgramEffects* getProgramEffects() = 0;
/**
* Compiles all the shaders, links them into a program, and writes the program id to the output
* struct.
**/
bool finish();
GrGLFragmentProcessorEmitter fGrProcessorEmitter;
const GrOptDrawState& fOptState;
const GrGLProgramDesc& fDesc;
GrGpuGL* fGpu;
UniformInfoArray fUniforms;
friend class GrGLShaderBuilder; friend class GrGLShaderBuilder;
friend class GrGLVertexShaderBuilder; friend class GrGLVertexShaderBuilder;

View File

@ -6,7 +6,7 @@
*/ */
#include "GrGLShaderBuilder.h" #include "GrGLShaderBuilder.h"
#include "GrGLFullProgramBuilder.h" #include "GrGLProgramBuilder.h"
#include "GrGLProgramBuilder.h" #include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h" #include "../GrGpuGL.h"
#include "../GrGLShaderVar.h" #include "../GrGLShaderVar.h"
@ -53,13 +53,12 @@ void append_texture_lookup(SkString* out,
out->appendf(".%s", swizzle); out->appendf(".%s", swizzle);
} }
} }
static const int kVarsPerBlock = 8;
} }
GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program) GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
: fProgramBuilder(program) : fProgramBuilder(program)
, fInputs(kVarsPerBlock) , fInputs(GrGLProgramBuilder::kVarsPerBlock)
, fOutputs(kVarsPerBlock) , fOutputs(GrGLProgramBuilder::kVarsPerBlock)
, fFeaturesAddedMask(0) { , 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, void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
const char* coordName, const char* coordName,
uint32_t configComponentMask, uint32_t configComponentMask,
@ -155,8 +161,3 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
swizzle, swizzle,
kVec2f_GrSLType); kVec2f_GrSLType);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////
GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program)
: INHERITED(program)
, fFullProgramBuilder(program) {}

View File

@ -9,21 +9,12 @@
#define GrGLShaderBuilder_DEFINED #define GrGLShaderBuilder_DEFINED
#include "gl/GrGLProgramDesc.h" #include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h" #include "gl/GrGLProgramDataManager.h"
#include "GrBackendProcessorFactory.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "SkTypes.h"
#include <stdarg.h> #include <stdarg.h>
class GrGLContextInfo; class GrGLContextInfo;
class GrProcessorStage;
class GrGLProgramDesc;
class GrGLProgramBuilder; class GrGLProgramBuilder;
class GrGLFullProgramBuilder;
/** /**
base class for all shaders builders base class for all shaders builders
@ -32,6 +23,7 @@ class GrGLShaderBuilder {
public: public:
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray; typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
typedef GrGLProcessor::TextureSampler TextureSampler; typedef GrGLProcessor::TextureSampler TextureSampler;
GrGLShaderBuilder(GrGLProgramBuilder* program); GrGLShaderBuilder(GrGLProgramBuilder* program);
void addInput(GrGLShaderVar i) { fInputs.push_back(i); } void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
@ -112,7 +104,7 @@ public:
GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; } 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 { class ShaderBlock {
public: public:
@ -127,7 +119,10 @@ public:
private: private:
GrGLShaderBuilder* fBuilder; GrGLShaderBuilder* fBuilder;
}; };
protected: 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 * 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); void addFeature(uint32_t featureBit, const char* extensionName);
typedef GrTAllocator<GrGLShaderVar> VarArray;
GrGLProgramBuilder* fProgramBuilder; GrGLProgramBuilder* fProgramBuilder;
SkString fCode; SkString fCode;
@ -154,21 +147,4 @@ protected:
VarArray fOutputs; VarArray fOutputs;
uint32_t fFeaturesAddedMask; 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 #endif

View File

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

View File

@ -7,26 +7,22 @@
#ifndef GrGLVertexShader_DEFINED #ifndef GrGLVertexShader_DEFINED
#define GrGLVertexShader_DEFINED #define GrGLVertexShader_DEFINED
#include "GrGLShaderBuilder.h" #include "GrGLShaderBuilder.h"
class GrGLProgramBuilder; 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: public:
GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program); GrGLVertexBuilder(GrGLProgramBuilder* program);
/*
* this call is only for GrGLProgramEffects' internal use
*/
void emitAttributes(const GrGeometryProcessor& gp);
/** /**
* Are explicit local coordinates provided as input to the vertex shader. * Are explicit local coordinates provided as input to the vertex shader.
*/ */
bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } 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 /** 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 as positionAttribute() or it may not be. It depends upon whether the rendering code
specified explicit local coords or not in the GrDrawState. */ specified explicit local coords or not in the GrDrawState. */
@ -37,28 +33,25 @@ public:
*/ */
const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
private:
/* /*
* Add attribute will push a new attribute onto the end. It will also assert if there is * Internal call for GrGLProgramBuilder.addVarying
* a duplicate attribute
*/ */
bool addAttribute(const GrShaderVar& var); SkString* addVarying(GrSLType type, const char* name, const char** vsOutName);
/*
* Internal call for GrGLFullProgramBuilder.addVarying
*/
void addVarying(GrSLType type,
const char* name,
const char** vsOutName);
/* /*
* private helpers for compilation by GrGLProgramBuilder * 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; 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 { struct AttributePair {
void set(int index, const SkString& name) { void set(int index, const SkString& name) {
fIndex = index; fName = name; fIndex = index; fName = name;
@ -71,9 +64,7 @@ private:
GrGLShaderVar* fLocalCoordsVar; GrGLShaderVar* fLocalCoordsVar;
int fEffectAttribOffset; int fEffectAttribOffset;
friend class GrGLFullProgramBuilder; typedef GrGLShaderBuilder INHERITED;
typedef GrGLFullShaderBuilder INHERITED;
}; };
#endif #endif

View File

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