Cleanup of shader building system
this is a huge refactor and cleanup of the gl shader building system in Skia. The entire shader building pipeline is now part of GrGLProgramCreator, which takes a gp, and some fps, and creates a program. I added some subclasses of GrGLProgram to handle the eccentricities of Nvpr/Nvpres. Outside of the builders folder and GrGLPrograms, this change is basically just a rename solo gp BUG=skia: Committed: https://skia.googlesource.com/skia/+/fe1233c3f12f81bb675718516bbb32f72af726ec Review URL: https://codereview.chromium.org/611653002
This commit is contained in:
parent
e6efd39a33
commit
47bb382830
16
gyp/gpu.gypi
16
gyp/gpu.gypi
@ -232,8 +232,6 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgram.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramEffects.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramEffects.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLRenderTarget.cpp',
|
||||
@ -258,17 +256,17 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGpuGL_program.cpp',
|
||||
|
||||
# Files for building GLSL shaders
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.h',
|
||||
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp',
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
if (!fp->willUseInputColor()) {
|
||||
fColorStages.reset();
|
||||
}
|
||||
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrProcessorStage, (fp));
|
||||
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp));
|
||||
return fp;
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ public:
|
||||
if (!fp->willUseInputColor()) {
|
||||
fCoverageStages.reset();
|
||||
}
|
||||
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrProcessorStage, (fp));
|
||||
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp));
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,8 @@ public:
|
||||
fCoordChangeMatrixSet = false;
|
||||
}
|
||||
|
||||
virtual ~GrProcessorStage() {}
|
||||
|
||||
GrProcessorStage(const GrProcessorStage& other) {
|
||||
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
|
||||
if (other.fCoordChangeMatrixSet) {
|
||||
@ -147,11 +149,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const GrProcessor* getProcessor() const { return fProc.get(); }
|
||||
virtual const GrProcessor* getProcessor() const = 0;
|
||||
|
||||
void convertToPendingExec() { fProc.convertToPendingExec(); }
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool fCoordChangeMatrixSet;
|
||||
SkMatrix fCoordChangeMatrix;
|
||||
GrProgramElementRef<const GrProcessor> fProc;
|
||||
@ -161,18 +163,24 @@ class GrFragmentStage : public GrProcessorStage {
|
||||
public:
|
||||
GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
|
||||
|
||||
const GrFragmentProcessor* getFragmentProcessor() const {
|
||||
return static_cast<const GrFragmentProcessor*>(this->getProcessor());
|
||||
virtual const GrFragmentProcessor* getProcessor() const {
|
||||
return static_cast<const GrFragmentProcessor*>(fProc.get());
|
||||
}
|
||||
|
||||
typedef GrFragmentProcessor Processor;
|
||||
typedef GrGLFragmentProcessor GLProcessor;
|
||||
};
|
||||
|
||||
class GrGeometryStage : public GrProcessorStage {
|
||||
public:
|
||||
GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
|
||||
|
||||
const GrGeometryProcessor* getGeometryProcessor() const {
|
||||
return static_cast<const GrGeometryProcessor*>(this->getProcessor());
|
||||
virtual const GrGeometryProcessor* getProcessor() const {
|
||||
return static_cast<const GrGeometryProcessor*>(fProc.get());
|
||||
}
|
||||
|
||||
typedef GrGeometryProcessor Processor;
|
||||
typedef GrGLGeometryProcessor GLProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,6 @@
|
||||
#define GrTBackendProcessorFactory_DEFINED
|
||||
|
||||
#include "GrBackendProcessorFactory.h"
|
||||
#include "gl/GrGLProgramEffects.h"
|
||||
|
||||
/**
|
||||
* Implements GrBackendEffectFactory for a GrProcessor subclass as a singleton. This can be used by
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "SkStrokeRec.h"
|
||||
#include "SkTraceEvent.h"
|
||||
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
@ -528,7 +528,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -538,7 +538,7 @@ public:
|
||||
const char *vsName, *fsName;
|
||||
builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
@ -565,7 +565,7 @@ public:
|
||||
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
|
||||
|
||||
const GrShaderVar& inQuadEdge = geometryProcessor.cast<QuadEdgeEffect>().inQuadEdge();
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, inQuadEdge.c_str());
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "GrAARectRenderer.h"
|
||||
#include "GrGpu.h"
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
#include "GrTBackendProcessorFactory.h"
|
||||
@ -41,7 +41,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -55,10 +55,10 @@ public:
|
||||
builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
|
||||
|
||||
const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
// TODO: compute all these offsets, spans, and scales in the VS
|
||||
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
|
||||
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
|
||||
@ -167,7 +167,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -181,7 +181,7 @@ public:
|
||||
&vsRectEdgeName, &fsRectEdgeName);
|
||||
|
||||
const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
|
||||
|
||||
// setup the varying for width/2+.5 and height/2+.5
|
||||
@ -192,7 +192,7 @@ public:
|
||||
vsWidthHeightName,
|
||||
rectEffect.inWidthHeight().c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
// TODO: compute all these offsets, spans, and scales in the VS
|
||||
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
|
||||
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
|
||||
|
@ -266,7 +266,7 @@ bool GrDrawState::validateVertexAttribs() const {
|
||||
|
||||
if (this->hasGeometryProcessor()) {
|
||||
const GrGeometryStage& stage = *this->getGeometryProcessor();
|
||||
const GrGeometryProcessor* gp = stage.getGeometryProcessor();
|
||||
const GrGeometryProcessor* gp = stage.getProcessor();
|
||||
SkASSERT(gp);
|
||||
// make sure that any attribute indices have the correct binding type, that the attrib
|
||||
// type and effect's shader lang type are compatible, and that attributes shared by
|
||||
@ -410,7 +410,7 @@ bool GrDrawState::hasSolidCoverage() const {
|
||||
|
||||
// Run through the coverage stages and see if the coverage will be all ones at the end.
|
||||
if (this->hasGeometryProcessor()) {
|
||||
const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
|
||||
const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
|
||||
gp->computeInvariantOutput(&inout);
|
||||
}
|
||||
for (int s = 0; s < this->numCoverageStages(); ++s) {
|
||||
@ -436,13 +436,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
|
||||
bool GrDrawState::willEffectReadDstColor() const {
|
||||
if (!this->isColorWriteDisabled()) {
|
||||
for (int s = 0; s < this->numColorStages(); ++s) {
|
||||
if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
|
||||
if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int s = 0; s < this->numCoverageStages(); ++s) {
|
||||
if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
|
||||
if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
|
||||
SkASSERT(drawState.getRenderTarget());
|
||||
|
||||
if (drawState.hasGeometryProcessor()) {
|
||||
const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor();
|
||||
const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
|
||||
int numTextures = gp->numTextures();
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
GrTexture* texture = gp->texture(t);
|
||||
|
@ -222,7 +222,7 @@ void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < ds.numColorStages(); ++i) {
|
||||
const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
|
||||
const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
|
||||
if (!fp->willUseInputColor()) {
|
||||
firstColorStage = i;
|
||||
fInputColorIsUsed = false;
|
||||
@ -270,10 +270,10 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
|
||||
}
|
||||
|
||||
static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
|
||||
if (stage.getFragmentProcessor()->willReadDstColor()) {
|
||||
if (stage.getProcessor()->willReadDstColor()) {
|
||||
*readsDst = true;
|
||||
}
|
||||
if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
|
||||
if (stage.getProcessor()->willReadFragmentPosition()) {
|
||||
*readsFragPosition = true;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "GrOvalRenderer.h"
|
||||
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
@ -92,7 +92,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -103,10 +103,10 @@ public:
|
||||
const char *vsName, *fsName;
|
||||
builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();;
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();;
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, circleEffect.inCircleEdge().c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName);
|
||||
fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
|
||||
if (circleEffect.isStroked()) {
|
||||
@ -210,7 +210,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -224,7 +224,7 @@ public:
|
||||
|
||||
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsOffsetName,
|
||||
ellipseEffect.inEllipseOffset().c_str());
|
||||
|
||||
@ -232,7 +232,7 @@ public:
|
||||
vsBuilder->codeAppendf("%s = %s;", vsRadiiName, ellipseEffect.inEllipseRadii().c_str());
|
||||
|
||||
// for outer curve
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName);
|
||||
fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
|
||||
fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
|
||||
@ -359,7 +359,7 @@ public:
|
||||
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -373,7 +373,7 @@ public:
|
||||
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0",
|
||||
&vsOffsetName0, &fsOffsetName0);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsOffsetName0,
|
||||
ellipseEffect.inEllipseOffsets0().c_str());
|
||||
const char *vsOffsetName1, *fsOffsetName1;
|
||||
@ -382,7 +382,7 @@ public:
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1,
|
||||
ellipseEffect.inEllipseOffsets1().c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
// for outer curve
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "GrBezierEffect.h"
|
||||
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
@ -17,7 +17,7 @@ class GrGLConicEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GrGLConicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -42,7 +42,7 @@ GrGLConicEffect::GrGLConicEffect(const GrBackendProcessorFactory& factory,
|
||||
fEdgeType = ce.getEdgeType();
|
||||
}
|
||||
|
||||
void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
void GrGLConicEffect::emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -55,10 +55,10 @@ void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
&vsName, &fsName);
|
||||
|
||||
const GrShaderVar& inConicCoeffs = geometryProcessor.cast<GrConicEffect>().inConicCoeffs();
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsName, inConicCoeffs.c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppend("float edgeAlpha;");
|
||||
|
||||
switch (fEdgeType) {
|
||||
@ -171,7 +171,7 @@ class GrGLQuadEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GrGLQuadEffect(const GrBackendProcessorFactory&, const GrProcessor&);
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -196,7 +196,7 @@ GrGLQuadEffect::GrGLQuadEffect(const GrBackendProcessorFactory& factory,
|
||||
fEdgeType = ce.getEdgeType();
|
||||
}
|
||||
|
||||
void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
void GrGLQuadEffect::emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -206,11 +206,11 @@ void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
const char *vsName, *fsName;
|
||||
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
const GrShaderVar& inHairQuadEdge = geometryProcessor.cast<GrQuadEffect>().inHairQuadEdge();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsName, inHairQuadEdge.c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("float edgeAlpha;");
|
||||
|
||||
switch (fEdgeType) {
|
||||
@ -309,7 +309,7 @@ class GrGLCubicEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GrGLCubicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -334,7 +334,7 @@ GrGLCubicEffect::GrGLCubicEffect(const GrBackendProcessorFactory& factory,
|
||||
fEdgeType = ce.getEdgeType();
|
||||
}
|
||||
|
||||
void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
void GrGLCubicEffect::emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -346,11 +346,11 @@ void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
|
||||
&vsName, &fsName, GrGLShaderVar::kHigh_Precision);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
const GrShaderVar& inCubicCoeffs = geometryProcessor.cast<GrCubicEffect>().inCubicCoeffs();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsName, inCubicCoeffs.c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
|
||||
GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
|
||||
GrGLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "GrCustomCoordsTextureEffect.h"
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLTexture.h"
|
||||
@ -19,7 +19,7 @@ public:
|
||||
GrGLCustomCoordsTextureEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
|
||||
: INHERITED (factory) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -36,11 +36,11 @@ public:
|
||||
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
|
||||
fsCoordName = fsVaryingNamePtr;
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, inTextureCoords.c_str());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("\t%s = ", outputColor);
|
||||
fsBuilder->appendTextureLookupAndModulate(inputColor,
|
||||
samplers[0],
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "../GrAARectRenderer.h"
|
||||
|
||||
#include "GrGeometryProcessor.h"
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
@ -482,7 +482,7 @@ class GLDashingCircleEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GLDashingCircleEffect(const GrBackendProcessorFactory&, const GrProcessor&);
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -510,7 +510,7 @@ GLDashingCircleEffect::GLDashingCircleEffect(const GrBackendProcessorFactory& fa
|
||||
fPrevIntervalLength = SK_ScalarMax;
|
||||
}
|
||||
|
||||
void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
void GLDashingCircleEffect::emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -529,11 +529,11 @@ void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
const char *vsCoordName, *fsCoordName;
|
||||
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dce.inCoord().c_str());
|
||||
|
||||
// transforms all points so that we can compare them to our test circle
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
|
||||
fsCoordName, fsCoordName, paramName, paramName);
|
||||
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
|
||||
@ -694,7 +694,7 @@ class GLDashingLineEffect : public GrGLGeometryProcessor {
|
||||
public:
|
||||
GLDashingLineEffect(const GrBackendProcessorFactory&, const GrProcessor&);
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -721,7 +721,7 @@ GLDashingLineEffect::GLDashingLineEffect(const GrBackendProcessorFactory& factor
|
||||
fPrevIntervalLength = SK_ScalarMax;
|
||||
}
|
||||
|
||||
void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
void GLDashingLineEffect::emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -745,11 +745,11 @@ void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
|
||||
|
||||
const char *vsCoordName, *fsCoordName;
|
||||
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, de.inCoord().c_str());
|
||||
|
||||
// transforms all points so that we can compare them to our test rect
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
|
||||
fsCoordName, fsCoordName, intervalName, intervalName);
|
||||
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "GrDistanceFieldTextureEffect.h"
|
||||
#include "gl/builders/GrGLFullProgramBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLTexture.h"
|
||||
@ -40,7 +40,7 @@ public:
|
||||
#endif
|
||||
{}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -51,7 +51,7 @@ public:
|
||||
geometryProcessor.cast<GrDistanceFieldTextureEffect>();
|
||||
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
||||
@ -61,7 +61,7 @@ public:
|
||||
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
|
||||
fsCoordName = fsCoordNamePtr;
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
|
||||
|
||||
const char* textureSizeUniName = NULL;
|
||||
@ -267,7 +267,7 @@ public:
|
||||
: INHERITED(factory)
|
||||
, fTextureSize(SkISize::Make(-1, -1)) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& effect,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -278,7 +278,7 @@ public:
|
||||
effect.cast<GrDistanceFieldNoGammaTextureEffect>();
|
||||
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
||||
@ -288,7 +288,7 @@ public:
|
||||
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
|
||||
fsCoordName = fsCoordNamePtr;
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoords().c_str());
|
||||
|
||||
const char* textureSizeUniName = NULL;
|
||||
@ -439,7 +439,7 @@ public:
|
||||
, fTextureSize(SkISize::Make(-1,-1))
|
||||
, fTextColor(GrColor_ILLEGAL) {}
|
||||
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
@ -456,7 +456,7 @@ public:
|
||||
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
|
||||
fsCoordName = fsCoordNamePtr;
|
||||
|
||||
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
|
||||
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
|
||||
|
||||
const char* textureSizeUniName = NULL;
|
||||
@ -465,7 +465,7 @@ public:
|
||||
kVec3f_GrSLType, "TextureSize",
|
||||
&textureSizeUniName);
|
||||
|
||||
GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
||||
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
* This is similar to emitCode() in the base class, except it takes a full shader builder.
|
||||
* This allows the effect subclass to emit vertex code.
|
||||
*/
|
||||
virtual void emitCode(GrGLFullProgramBuilder* builder,
|
||||
virtual void emitCode(GrGLGPBuilder* builder,
|
||||
const GrGeometryProcessor& geometryProcessor,
|
||||
const GrProcessorKey& key,
|
||||
const char* outputColor,
|
||||
|
@ -9,9 +9,8 @@
|
||||
#define GrGLProcessor_DEFINED
|
||||
|
||||
#include "GrBackendProcessorFactory.h"
|
||||
#include "GrGLProgramEffects.h"
|
||||
#include "GrGLShaderVar.h"
|
||||
#include "GrGLSL.h"
|
||||
#include "GrGLProgramDataManager.h"
|
||||
#include "GrTextureAccess.h"
|
||||
|
||||
/** @file
|
||||
This file contains specializations for OpenGL of the shader stages declared in
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "GrGLProgram.h"
|
||||
|
||||
#include "builders/GrGLFullProgramBuilder.h"
|
||||
#include "builders/GrGLFragmentOnlyProgramBuilder.h"
|
||||
#include "GrAllocator.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrCoordTransform.h"
|
||||
@ -23,45 +21,58 @@
|
||||
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
|
||||
|
||||
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
|
||||
const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc,
|
||||
const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[]) {
|
||||
SkAutoTDelete<GrGLProgramBuilder> builder;
|
||||
if (desc.getHeader().fUseFragShaderOnly) {
|
||||
SkASSERT(gpu->glCaps().pathRenderingSupport());
|
||||
SkASSERT(gpu->glPathRendering()->texturingMode() ==
|
||||
GrGLPathRendering::FixedFunction_TexturingMode);
|
||||
SkASSERT(NULL == geometryProcessor);
|
||||
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc)));
|
||||
/**
|
||||
* Retrieves the final matrix that a transform needs to apply to its source coords.
|
||||
*/
|
||||
static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
|
||||
bool useExplicitLocalCoords,
|
||||
int transformIdx) {
|
||||
const GrCoordTransform& coordTransform =
|
||||
processorStage.getProcessor()->coordTransform(transformIdx);
|
||||
SkMatrix combined;
|
||||
|
||||
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
|
||||
// If we have explicit local coords then we shouldn't need a coord change.
|
||||
const SkMatrix& ccm =
|
||||
useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
|
||||
combined.setConcat(coordTransform.getMatrix(), ccm);
|
||||
} else {
|
||||
builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc)));
|
||||
combined = coordTransform.getMatrix();
|
||||
}
|
||||
if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
|
||||
SkASSERT(0 != builder->getProgramID());
|
||||
return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
|
||||
if (coordTransform.reverseY()) {
|
||||
// combined.postScale(1,-1);
|
||||
// combined.postTranslate(0,1);
|
||||
combined.set(SkMatrix::kMSkewY,
|
||||
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
|
||||
combined.set(SkMatrix::kMScaleY,
|
||||
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
|
||||
combined.set(SkMatrix::kMTransY,
|
||||
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
|
||||
}
|
||||
return NULL;
|
||||
return combined;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLProgram::GrGLProgram(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const GrGLProgramBuilder& builder)
|
||||
const BuiltinUniformHandles& builtinUniforms,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray& uniforms,
|
||||
GrGLInstalledProcessors* geometryProcessor,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors)
|
||||
: fColor(GrColor_ILLEGAL)
|
||||
, fCoverage(GrColor_ILLEGAL)
|
||||
, fDstCopyTexUnit(-1)
|
||||
, fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
|
||||
, fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
|
||||
, fColorEffects(SkRef(builder.getColorEffects()))
|
||||
, fCoverageEffects(SkRef(builder.getCoverageEffects()))
|
||||
, fProgramID(builder.getProgramID())
|
||||
, fHasVertexShader(builder.hasVertexShader())
|
||||
, fTexCoordSetCnt(builder.getTexCoordSetCount())
|
||||
, fBuiltinUniformHandles(builtinUniforms)
|
||||
, fProgramID(programID)
|
||||
, fGeometryProcessor(SkSafeRef(geometryProcessor))
|
||||
, fColorEffects(SkRef(colorProcessors))
|
||||
, fCoverageEffects(SkRef(coverageProcessors))
|
||||
, fDesc(desc)
|
||||
, fGpu(gpu)
|
||||
, fProgramDataManager(gpu, this, builder) {
|
||||
, fProgramDataManager(gpu, uniforms) {
|
||||
this->initSamplerUniforms();
|
||||
}
|
||||
|
||||
@ -83,12 +94,42 @@ void GrGLProgram::initSamplerUniforms() {
|
||||
fDstCopyTexUnit = texUnitIdx++;
|
||||
}
|
||||
if (fGeometryProcessor.get()) {
|
||||
fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
|
||||
}
|
||||
fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
|
||||
this->initSamplers(fColorEffects.get(), &texUnitIdx);
|
||||
this->initSamplers(fCoverageEffects.get(), &texUnitIdx);
|
||||
}
|
||||
|
||||
void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) {
|
||||
int numEffects = ip->fGLProcessors.count();
|
||||
SkASSERT(numEffects == ip->fSamplers.count());
|
||||
for (int e = 0; e < numEffects; ++e) {
|
||||
SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e];
|
||||
int numSamplers = samplers.count();
|
||||
for (int s = 0; s < numSamplers; ++s) {
|
||||
SkASSERT(samplers[s].fUniform.isValid());
|
||||
fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
|
||||
samplers[s].fTextureUnit = (*texUnitIdx)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip,
|
||||
const GrProcessor& processor,
|
||||
int effectIdx) {
|
||||
const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx];
|
||||
int numSamplers = samplers.count();
|
||||
SkASSERT(numSamplers == processor.numTextures());
|
||||
for (int s = 0; s < numSamplers; ++s) {
|
||||
SkASSERT(samplers[s].fTextureUnit >= 0);
|
||||
const GrTextureAccess& textureAccess = processor.textureAccess(s);
|
||||
fGpu->bindTexture(samplers[s].fTextureUnit,
|
||||
textureAccess.getParams(),
|
||||
static_cast<GrGLTexture*>(textureAccess.getTexture()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLProgram::setData(const GrOptDrawState& optState,
|
||||
@ -126,19 +167,37 @@ void GrGLProgram::setData(const GrOptDrawState& optState,
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
|
||||
}
|
||||
|
||||
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
|
||||
// of GLProgram determine how to set coord transforms
|
||||
if (fGeometryProcessor.get()) {
|
||||
SkASSERT(geometryProcessor);
|
||||
fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
|
||||
this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
|
||||
}
|
||||
fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
|
||||
fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
|
||||
this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
|
||||
this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
|
||||
|
||||
// PathTexGen state applies to the the fixed function vertex shader. For
|
||||
// custom shaders, it's ignored, so we don't need to change the texgen
|
||||
// settings in that case.
|
||||
if (!fHasVertexShader) {
|
||||
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
|
||||
// Some of GrGLProgram subclasses need to update state here
|
||||
this->didSetData(drawType);
|
||||
}
|
||||
|
||||
void GrGLProgram::setTransformData(const GrProcessorStage& processor,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors* ip) {
|
||||
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
|
||||
int numTransforms = transforms.count();
|
||||
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(transforms[t].fHandle.isValid());
|
||||
const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
|
||||
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
|
||||
fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
|
||||
transforms[t].fCurrentValue = matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
|
||||
SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
|
||||
}
|
||||
|
||||
void GrGLProgram::setColor(const GrOptDrawState& optState,
|
||||
@ -220,20 +279,23 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState,
|
||||
|
||||
void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
|
||||
const GrOptDrawState& optState) {
|
||||
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
|
||||
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
|
||||
fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->height()) {
|
||||
fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
|
||||
SkIntToScalar(optState.getRenderTarget()->height()));
|
||||
}
|
||||
|
||||
// call subclasses to set the actual view matrix
|
||||
this->onSetMatrixAndRenderTargetHeight(drawType, optState);
|
||||
}
|
||||
|
||||
void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
|
||||
const GrOptDrawState& optState) {
|
||||
const GrRenderTarget* rt = optState.getRenderTarget();
|
||||
SkISize size;
|
||||
size.set(rt->width(), rt->height());
|
||||
|
||||
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
|
||||
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
|
||||
fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
|
||||
fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
|
||||
SkIntToScalar(size.fHeight));
|
||||
}
|
||||
|
||||
if (GrGpu::IsPathRenderingDrawType(drawType)) {
|
||||
fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
|
||||
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
|
||||
if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
|
||||
fMatrixState.fRenderTargetSize != size ||
|
||||
!fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
|
||||
SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
|
||||
@ -251,3 +313,115 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
|
||||
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const BuiltinUniformHandles& builtinUniforms,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray& uniforms,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors)
|
||||
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors,
|
||||
coverageProcessors) {
|
||||
}
|
||||
|
||||
void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
|
||||
const GrOptDrawState& optState) {
|
||||
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
|
||||
const GrRenderTarget* rt = optState.getRenderTarget();
|
||||
SkISize size;
|
||||
size.set(rt->width(), rt->height());
|
||||
fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const BuiltinUniformHandles& builtinUniforms,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray& uniforms,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors,
|
||||
const SeparableVaryingInfoArray& separableVaryings)
|
||||
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
|
||||
coverageProcessors) {
|
||||
int count = separableVaryings.count();
|
||||
fVaryings.push_back_n(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Varying& varying = fVaryings[i];
|
||||
const SeparableVaryingInfo& builderVarying = separableVaryings[i];
|
||||
SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
|
||||
SkDEBUGCODE(
|
||||
varying.fType = builderVarying.fVariable.getType();
|
||||
);
|
||||
varying.fLocation = builderVarying.fLocation;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
|
||||
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
|
||||
}
|
||||
|
||||
void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors* ip) {
|
||||
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
|
||||
int numTransforms = transforms.count();
|
||||
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(transforms[t].fHandle.isValid());
|
||||
const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
|
||||
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
|
||||
continue;
|
||||
}
|
||||
transforms[t].fCurrentValue = transform;
|
||||
const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()];
|
||||
SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType);
|
||||
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
|
||||
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
|
||||
fragmentInput.fLocation,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
transform);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const BuiltinUniformHandles& builtinUniforms,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray& uniforms,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors,
|
||||
int texCoordSetCnt)
|
||||
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
|
||||
coverageProcessors)
|
||||
, fTexCoordSetCnt(texCoordSetCnt) {
|
||||
}
|
||||
|
||||
void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
|
||||
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
|
||||
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
|
||||
}
|
||||
|
||||
void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors* ip) {
|
||||
// We've hidden the texcoord index in the first entry of the transforms array for each effect
|
||||
int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle();
|
||||
int numTransforms = processorStage.getProcessor()->numTransforms();
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
const SkMatrix& transform = get_transform_matrix(processorStage, false, t);
|
||||
GrGLPathRendering::PathTexGenComponents components =
|
||||
GrGLPathRendering::kST_PathTexGenComponents;
|
||||
if (processorStage.isPerspectiveCoordTransform(t, false)) {
|
||||
components = GrGLPathRendering::kSTR_PathTexGenComponents;
|
||||
}
|
||||
fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define GrGLProgram_DEFINED
|
||||
|
||||
#include "builders/GrGLProgramBuilder.h"
|
||||
#include "builders/GrGLNvprProgramBuilder.h"
|
||||
#include "GrDrawState.h"
|
||||
#include "GrGLContext.h"
|
||||
#include "GrGLProgramDesc.h"
|
||||
@ -21,7 +22,7 @@
|
||||
#include "SkXfermode.h"
|
||||
|
||||
class GrGLProcessor;
|
||||
class GrGLProgramEffects;
|
||||
class GrGLInstalledProcessors;
|
||||
class GrGLProgramBuilder;
|
||||
|
||||
/**
|
||||
@ -39,13 +40,6 @@ public:
|
||||
|
||||
typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles;
|
||||
|
||||
static GrGLProgram* Create(GrGpuGL* gpu,
|
||||
const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc,
|
||||
const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[]);
|
||||
|
||||
virtual ~GrGLProgram();
|
||||
|
||||
/**
|
||||
@ -60,7 +54,10 @@ public:
|
||||
*/
|
||||
GrGLuint programID() const { return fProgramID; }
|
||||
|
||||
bool hasVertexShader() const { return fHasVertexShader; }
|
||||
/*
|
||||
* The base class always has a vertex shader, only the NVPR variants may omit a vertex shader
|
||||
*/
|
||||
virtual bool hasVertexShader() const { return true; }
|
||||
|
||||
/**
|
||||
* Some GL state that is relevant to programs is not stored per-program. In particular color
|
||||
@ -161,15 +158,22 @@ public:
|
||||
const GrDeviceCoordTexture* dstCopy, // can be NULL
|
||||
SharedGLState*);
|
||||
|
||||
private:
|
||||
protected:
|
||||
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
||||
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
|
||||
|
||||
GrGLProgram(GrGpuGL*,
|
||||
const GrGLProgramDesc&,
|
||||
const GrGLProgramBuilder&);
|
||||
const BuiltinUniformHandles&,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray&,
|
||||
GrGLInstalledProcessors* geometryProcessor,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors);
|
||||
|
||||
// Sets the texture units for samplers.
|
||||
void initSamplerUniforms();
|
||||
void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
|
||||
|
||||
// Helper for setData(). Makes GL calls to specify the initial color when there is not
|
||||
// per-vertex colors.
|
||||
@ -179,29 +183,134 @@ private:
|
||||
// per-vertex coverages.
|
||||
void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
|
||||
|
||||
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
|
||||
template <class ProcessorStage>
|
||||
void setData(const ProcessorStage* effectStages[],
|
||||
GrGLInstalledProcessors* installedProcessors) {
|
||||
int numEffects = installedProcessors->fGLProcessors.count();
|
||||
SkASSERT(numEffects == installedProcessors->fTransforms.count());
|
||||
SkASSERT(numEffects == installedProcessors->fSamplers.count());
|
||||
for (int e = 0; e < numEffects; ++e) {
|
||||
const GrProcessor& effect = *effectStages[e]->getProcessor();
|
||||
installedProcessors->fGLProcessors[e]->setData(fProgramDataManager, effect);
|
||||
this->setTransformData(*effectStages[e], e, installedProcessors);
|
||||
this->bindTextures(installedProcessors, effect, e);
|
||||
}
|
||||
}
|
||||
virtual void setTransformData(const GrProcessorStage& effectStage,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors* pe);
|
||||
void bindTextures(const GrGLInstalledProcessors*, const GrProcessor&, int effectIdx);
|
||||
|
||||
/*
|
||||
* Legacy NVPR needs a hook here to flush path tex gen settings.
|
||||
* TODO when legacy nvpr is removed, remove this call.
|
||||
*/
|
||||
virtual void didSetData(GrGpu::DrawType);
|
||||
|
||||
// Helper for setData() that sets the view matrix and loads the render target height uniform
|
||||
void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&);
|
||||
void setMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
|
||||
virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
|
||||
|
||||
// these reflect the current values of uniforms (GL uniform values travel with program)
|
||||
MatrixState fMatrixState;
|
||||
GrColor fColor;
|
||||
GrColor fCoverage;
|
||||
int fDstCopyTexUnit;
|
||||
|
||||
BuiltinUniformHandles fBuiltinUniformHandles;
|
||||
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
|
||||
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
|
||||
GrGLuint fProgramID;
|
||||
bool fHasVertexShader;
|
||||
int fTexCoordSetCnt;
|
||||
|
||||
// the installed effects
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
|
||||
|
||||
GrGLProgramDesc fDesc;
|
||||
GrGpuGL* fGpu;
|
||||
|
||||
GrGLProgramDataManager fProgramDataManager;
|
||||
|
||||
friend class GrGLProgramBuilder;
|
||||
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
/*
|
||||
* Below are slight specializations of the program object for the different types of programs
|
||||
* The default GrGL programs consist of at the very least a vertex and fragment shader.
|
||||
* Legacy Nvpr only has a fragment shader, 1.3+ Nvpr ignores the vertex shader, but both require
|
||||
* specialized methods for setting transform data. Both types of NVPR also require setting the
|
||||
* projection matrix through a special function call
|
||||
*/
|
||||
class GrGLNvprProgramBase : public GrGLProgram {
|
||||
protected:
|
||||
GrGLNvprProgramBase(GrGpuGL*,
|
||||
const GrGLProgramDesc&,
|
||||
const BuiltinUniformHandles&,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray&,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors);
|
||||
virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
|
||||
|
||||
typedef GrGLProgram INHERITED;
|
||||
};
|
||||
|
||||
class GrGLNvprProgram : public GrGLNvprProgramBase {
|
||||
public:
|
||||
virtual bool hasVertexShader() const SK_OVERRIDE { return true; }
|
||||
|
||||
private:
|
||||
typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo;
|
||||
typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray;
|
||||
GrGLNvprProgram(GrGpuGL*,
|
||||
const GrGLProgramDesc&,
|
||||
const BuiltinUniformHandles&,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray&,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors,
|
||||
const SeparableVaryingInfoArray& separableVaryings);
|
||||
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
|
||||
virtual void setTransformData(const GrProcessorStage&,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors*) SK_OVERRIDE;
|
||||
|
||||
struct Varying {
|
||||
GrGLint fLocation;
|
||||
SkDEBUGCODE(
|
||||
GrSLType fType;
|
||||
);
|
||||
};
|
||||
SkTArray<Varying, true> fVaryings;
|
||||
|
||||
friend class GrGLNvprProgramBuilder;
|
||||
|
||||
typedef GrGLNvprProgramBase INHERITED;
|
||||
};
|
||||
|
||||
class GrGLLegacyNvprProgram : public GrGLNvprProgramBase {
|
||||
public:
|
||||
virtual bool hasVertexShader() const SK_OVERRIDE { return false; }
|
||||
|
||||
private:
|
||||
GrGLLegacyNvprProgram(GrGpuGL* gpu,
|
||||
const GrGLProgramDesc& desc,
|
||||
const BuiltinUniformHandles&,
|
||||
GrGLuint programID,
|
||||
const UniformInfoArray&,
|
||||
GrGLInstalledProcessors* colorProcessors,
|
||||
GrGLInstalledProcessors* coverageProcessors,
|
||||
int texCoordSetCnt);
|
||||
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
|
||||
virtual void setTransformData(const GrProcessorStage&,
|
||||
int effectIdx,
|
||||
GrGLInstalledProcessors*) SK_OVERRIDE;
|
||||
|
||||
int fTexCoordSetCnt;
|
||||
|
||||
friend class GrGLLegacyNvprProgramBuilder;
|
||||
|
||||
typedef GrGLNvprProgramBase INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -5,9 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLPathRendering.h"
|
||||
#include "gl/GrGLProgram.h"
|
||||
#include "gl/GrGLUniformHandle.h"
|
||||
#include "gl/GrGpuGL.h"
|
||||
#include "SkMatrix.h"
|
||||
@ -16,16 +14,13 @@
|
||||
SkASSERT(arrayCount <= uni.fArrayCount || \
|
||||
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
|
||||
|
||||
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
|
||||
GrGLProgram* program,
|
||||
const GrGLProgramBuilder& builder)
|
||||
: fGpu(gpu),
|
||||
fProgram(program) {
|
||||
int count = builder.getUniformInfos().count();
|
||||
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoArray& uniforms)
|
||||
: fGpu(gpu) {
|
||||
int count = uniforms.count();
|
||||
fUniforms.push_back_n(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Uniform& uniform = fUniforms[i];
|
||||
const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i];
|
||||
const UniformInfo& builderUniform = uniforms[i];
|
||||
SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
|
||||
builderUniform.fVariable.getArrayCount() > 0);
|
||||
SkDEBUGCODE(
|
||||
@ -45,19 +40,6 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
|
||||
uniform.fFSLocation = kUnusedUniform;
|
||||
}
|
||||
}
|
||||
|
||||
count = builder.getSeparableVaryingInfos().count();
|
||||
fVaryings.push_back_n(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Varying& varying = fVaryings[i];
|
||||
const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
|
||||
builder.getSeparableVaryingInfos()[i];
|
||||
SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
|
||||
SkDEBUGCODE(
|
||||
varying.fType = builderVarying.fVariable.getType();
|
||||
);
|
||||
varying.fLocation = builderVarying.fLocation;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
|
||||
@ -276,14 +258,3 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix
|
||||
};
|
||||
this->setMatrix3f(u, mt);
|
||||
}
|
||||
|
||||
void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
|
||||
unsigned components,
|
||||
const SkMatrix& matrix) const {
|
||||
const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
|
||||
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
|
||||
fragmentInput.fLocation,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
matrix);
|
||||
}
|
||||
|
@ -56,22 +56,18 @@ public:
|
||||
friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
|
||||
};
|
||||
|
||||
class VaryingHandle : public ShaderResourceHandle {
|
||||
public:
|
||||
/** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder.
|
||||
* The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/
|
||||
static VaryingHandle CreateFromSeparableVaryingIndex(int i) {
|
||||
return VaryingHandle(i);
|
||||
}
|
||||
VaryingHandle() { }
|
||||
bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; }
|
||||
private:
|
||||
VaryingHandle(int value) : ShaderResourceHandle(value) { }
|
||||
int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
|
||||
friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
|
||||
struct UniformInfo {
|
||||
GrGLShaderVar fVariable;
|
||||
uint32_t fVisibility;
|
||||
GrGLint fLocation;
|
||||
};
|
||||
|
||||
GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&);
|
||||
// This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
|
||||
// after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
|
||||
// name strings. Otherwise, we'd have to hand out copies.
|
||||
typedef GrTAllocator<UniformInfo> UniformInfoArray;
|
||||
|
||||
GrGLProgramDataManager(GrGpuGL*, const UniformInfoArray&);
|
||||
|
||||
/** Functions for uploading uniform values. The varities ending in v can be used to upload to an
|
||||
* array of uniforms. arrayCount must be <= the array count of the uniform.
|
||||
@ -95,10 +91,6 @@ public:
|
||||
// convenience method for uploading a SkMatrix to a 3x3 matrix uniform
|
||||
void setSkMatrix(UniformHandle, const SkMatrix&) const;
|
||||
|
||||
void setProgramPathFragmentInputTransform(VaryingHandle i,
|
||||
unsigned components,
|
||||
const SkMatrix& matrix) const;
|
||||
|
||||
private:
|
||||
enum {
|
||||
kUnusedUniform = -1,
|
||||
@ -112,19 +104,10 @@ private:
|
||||
int fArrayCount;
|
||||
);
|
||||
};
|
||||
struct Varying {
|
||||
GrGLint fLocation;
|
||||
SkDEBUGCODE(
|
||||
GrSLType fType;
|
||||
);
|
||||
};
|
||||
|
||||
SkTArray<Uniform, true> fUniforms;
|
||||
SkTArray<Varying, true> fVaryings;
|
||||
GrGpuGL* fGpu;
|
||||
GrGLProgram* fProgram;
|
||||
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/builders/GrGLFragmentShaderBuilder.h"
|
||||
#include "GrGLProgramDesc.h"
|
||||
#include "GrBackendProcessorFactory.h"
|
||||
#include "GrProcessor.h"
|
||||
@ -178,7 +178,7 @@ bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
|
||||
if (NULL == key) {
|
||||
return false;
|
||||
}
|
||||
uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor());
|
||||
uint32_t attribKey = gen_attrib_key(stage.getProcessor());
|
||||
|
||||
// Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
|
||||
// don't fit.
|
||||
@ -355,8 +355,9 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
|
||||
}
|
||||
|
||||
if (optState.readsFragPosition()) {
|
||||
header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
|
||||
optState.getRenderTarget(), gpu->glCaps());
|
||||
header->fFragPosKey =
|
||||
GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
|
||||
gpu->glCaps());
|
||||
} else {
|
||||
header->fFragPosKey = 0;
|
||||
}
|
||||
|
@ -247,11 +247,10 @@ private:
|
||||
// visible to GrGLProcessors. Then make public accessors as necessary and remove friends.
|
||||
friend class GrGLProgram;
|
||||
friend class GrGLProgramBuilder;
|
||||
friend class GrGLFullProgramBuilder;
|
||||
friend class GrGLFragmentOnlyProgramBuilder;
|
||||
friend class GrGLVertexShaderBuilder;
|
||||
friend class GrGLLegacyNvprProgramBuilder;
|
||||
friend class GrGLVertexBuilder;
|
||||
friend class GrGLFragmentShaderBuilder;
|
||||
friend class GrGLGeometryShaderBuilder;
|
||||
friend class GrGLGeometryBuilder;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -179,8 +179,9 @@ private:
|
||||
~ProgramCache();
|
||||
|
||||
void abandon();
|
||||
GrGLProgram* getProgram(const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc,
|
||||
GrGLProgram* getProgram(const GrOptDrawState&,
|
||||
const GrGLProgramDesc&,
|
||||
DrawType,
|
||||
const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[]);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "GrGpuGL.h"
|
||||
|
||||
#include "builders/GrGLProgramBuilder.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrGLProcessor.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
@ -92,6 +93,7 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
|
||||
|
||||
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc,
|
||||
DrawType type,
|
||||
const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[]) {
|
||||
@ -129,8 +131,9 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
++fCacheMisses;
|
||||
#endif
|
||||
GrGLProgram* program = GrGLProgram::Create(fGpu, optState, desc, geometryProcessor,
|
||||
colorStages, coverageStages);
|
||||
GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
|
||||
geometryProcessor, colorStages,
|
||||
coverageStages, fGpu);
|
||||
if (NULL == program) {
|
||||
return NULL;
|
||||
}
|
||||
@ -254,6 +257,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
|
||||
|
||||
fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
|
||||
desc,
|
||||
type,
|
||||
geometryProcessor,
|
||||
colorStages.begin(),
|
||||
coverageStages.begin()));
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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
|
@ -10,15 +10,15 @@
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "../GrGpuGL.h"
|
||||
|
||||
namespace {
|
||||
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
|
||||
#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
|
||||
|
||||
// ES2 FS only guarantees mediump and lowp support
|
||||
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
|
||||
static const char kDstCopyColorName[] = "_dstColor";
|
||||
inline const char* declared_color_output_name() { return "fsColorOut"; }
|
||||
inline const char* dual_source_output_name() { return "dualSourceOut"; }
|
||||
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
|
||||
const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
|
||||
static const char* declared_color_output_name() { return "fsColorOut"; }
|
||||
static const char* dual_source_output_name() { return "dualSourceOut"; }
|
||||
static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
|
||||
GrGLStandard standard,
|
||||
SkString* str) {
|
||||
// Desktop GLSL has added precision qualifiers but they don't do anything.
|
||||
@ -40,10 +40,10 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
|
||||
const GrTexture* dstCopy, const GrGLCaps& caps) {
|
||||
GrGLFragmentShaderBuilder::DstReadKey
|
||||
GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
|
||||
const GrGLCaps& caps) {
|
||||
uint32_t key = kYesDstRead_DstReadKeyBit;
|
||||
if (caps.fbFetchSupport()) {
|
||||
return key;
|
||||
@ -60,8 +60,9 @@ GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
|
||||
return static_cast<DstReadKey>(key);
|
||||
}
|
||||
|
||||
GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
|
||||
const GrRenderTarget* dst, const GrGLCaps&) {
|
||||
GrGLFragmentShaderBuilder::FragPosKey
|
||||
GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
|
||||
const GrGLCaps&) {
|
||||
if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
|
||||
return kTopLeftFragPosRead_FragPosKey;
|
||||
} else {
|
||||
@ -75,33 +76,9 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
|
||||
, fHasCustomColorOutput(false)
|
||||
, fHasSecondaryOutput(false)
|
||||
, fSetupFragPosition(false)
|
||||
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
|
||||
}
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::dstColor() {
|
||||
if (fProgramBuilder->fCodeStage.inStageCode()) {
|
||||
const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor();
|
||||
// TODO GPs can't read dst color, and full program builder only returns a pointer to the
|
||||
// base fragment shader builder which does not have this function. Unfortunately,
|
||||
// the code stage class only has a GrProcessor pointer so this is required for the time
|
||||
// being
|
||||
if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) {
|
||||
SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor "
|
||||
"did not request access.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
if (gpu->glCaps().fbFetchSupport()) {
|
||||
this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
|
||||
gpu->glCaps().fbFetchExtensionString());
|
||||
return gpu->glCaps().fbFetchColorName();
|
||||
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
|
||||
return kDstCopyColorName;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
|
||||
, fHasReadDstColor(false)
|
||||
, fHasReadFragmentPosition(false) {
|
||||
}
|
||||
|
||||
bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
|
||||
@ -140,15 +117,7 @@ SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
|
||||
}
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::fragmentPosition() {
|
||||
GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
|
||||
if (cs->inStageCode()) {
|
||||
const GrProcessor* effect = cs->effectStage()->getProcessor();
|
||||
if (!effect->willReadFragmentPosition()) {
|
||||
SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor "
|
||||
"did not request access.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
fHasReadFragmentPosition = true;
|
||||
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
|
||||
@ -175,8 +144,7 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
|
||||
static const char* kCoordName = "fragCoordYDown";
|
||||
if (!fSetupFragPosition) {
|
||||
// temporarily change the stage index because we're inserting non-stage code.
|
||||
GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
|
||||
|
||||
GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
|
||||
SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
|
||||
const char* rtHeightName;
|
||||
|
||||
@ -198,69 +166,28 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** fsInName,
|
||||
GrGLShaderVar::Precision fsPrecision) {
|
||||
fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
|
||||
if (fsInName) {
|
||||
*fsInName = name;
|
||||
const char* GrGLFragmentShaderBuilder::dstColor() {
|
||||
fHasReadDstColor = true;
|
||||
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
if (gpu->glCaps().fbFetchSupport()) {
|
||||
this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
|
||||
gpu->glCaps().fbFetchExtensionString());
|
||||
return gpu->glCaps().fbFetchColorName();
|
||||
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
|
||||
return kDstCopyColorName;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
if (fHasCustomColorOutput) {
|
||||
GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
|
||||
}
|
||||
if (fHasSecondaryOutput) {
|
||||
GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) const {
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo()));
|
||||
fragShaderSrc.append(fExtensions);
|
||||
append_default_precision_qualifier(kDefaultFragmentPrecision,
|
||||
gpu->glStandard(),
|
||||
&fragShaderSrc);
|
||||
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
|
||||
fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
|
||||
// We shouldn't have declared outputs on 1.10
|
||||
SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
|
||||
fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
|
||||
fragShaderSrc.append(fFunctions);
|
||||
fragShaderSrc.append("void main() {\n");
|
||||
fragShaderSrc.append(fCode);
|
||||
fragShaderSrc.append("}\n");
|
||||
|
||||
GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId,
|
||||
GR_GL_FRAGMENT_SHADER, fragShaderSrc,
|
||||
gpu->gpuStats());
|
||||
if (!fragShaderId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*shaderIds->append() = fragShaderId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
|
||||
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// emit code to read the dst copy texture, if necessary
|
||||
if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
|
||||
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
|
||||
void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
|
||||
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
|
||||
const char* dstCopyTopLeftName;
|
||||
const char* dstCopyCoordScaleName;
|
||||
const char* dstCopySamplerName;
|
||||
uint32_t configMask;
|
||||
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
|
||||
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) {
|
||||
configMask = kA_GrColorComponentFlag;
|
||||
} else {
|
||||
configMask = kRGBA_GrColorComponentFlags;
|
||||
@ -280,7 +207,7 @@ void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
|
||||
kVec2f_GrSLType,
|
||||
"DstCopyCoordScale",
|
||||
&dstCopyCoordScaleName);
|
||||
const char* fragPos = fragmentPosition();
|
||||
const char* fragPos = this->fragmentPosition();
|
||||
|
||||
this->codeAppend("// Read color from copy of the destination.\n");
|
||||
this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
|
||||
@ -288,31 +215,43 @@ void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
|
||||
if (!topDown) {
|
||||
this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
|
||||
}
|
||||
this->codeAppendf("vec4 %s = ", kDstCopyColorName);
|
||||
this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName);
|
||||
this->appendTextureLookup(dstCopySamplerName,
|
||||
"_dstTexCoord",
|
||||
configMask,
|
||||
"rgba");
|
||||
this->codeAppend(";");
|
||||
}
|
||||
}
|
||||
|
||||
if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
|
||||
void GrGLFragmentShaderBuilder::enableCustomOutput() {
|
||||
SkASSERT(!fHasCustomColorOutput);
|
||||
fHasCustomColorOutput = true;
|
||||
fOutputs.push_back().set(kVec4f_GrSLType,
|
||||
GrGLShaderVar::kOut_TypeModifier,
|
||||
declared_color_output_name());
|
||||
fHasCustomColorOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
|
||||
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
||||
void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
|
||||
SkASSERT(!fHasSecondaryOutput);
|
||||
fHasSecondaryOutput = true;
|
||||
fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
|
||||
dual_source_output_name());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// write the secondary color output if necessary
|
||||
if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
|
||||
const char* secondaryOutputName = this->enableSecondaryOutput();
|
||||
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 (header.fSecondaryOutputType) {
|
||||
switch (fProgramBuilder->header().fSecondaryOutputType) {
|
||||
case GrOptDrawState::kCoverage_SecondaryOutputType:
|
||||
break;
|
||||
case GrOptDrawState::kCoverageISA_SecondaryOutputType:
|
||||
@ -327,42 +266,80 @@ void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputCol
|
||||
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());
|
||||
}
|
||||
this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// combine color and coverage as frag color
|
||||
|
||||
// Get "color * coverage" into fragColor
|
||||
void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor,
|
||||
const GrGLSLExpr4& inputCoverage) {
|
||||
GrGLSLExpr4 fragColor = inputColor * inputCoverage;
|
||||
switch (header.fPrimaryOutputType) {
|
||||
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(dstColor());
|
||||
GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->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;
|
||||
// On any post 1.10 GLSL supporting GPU, we declare custom output
|
||||
if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) {
|
||||
this->enableCustomOutput();
|
||||
}
|
||||
return dual_source_output_name();
|
||||
|
||||
this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str());
|
||||
}
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
|
||||
return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
|
||||
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) const {
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo()));
|
||||
fragShaderSrc.append(fExtensions);
|
||||
append_default_precision_qualifier(kDefaultFragmentPrecision,
|
||||
gpu->glStandard(),
|
||||
&fragShaderSrc);
|
||||
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
|
||||
this->appendDecls(fInputs, &fragShaderSrc);
|
||||
// We shouldn't have declared outputs on 1.10
|
||||
SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
|
||||
this->appendDecls(fOutputs, &fragShaderSrc);
|
||||
fragShaderSrc.append(fFunctions);
|
||||
fragShaderSrc.append("void main() {\n");
|
||||
fragShaderSrc.append(fCode);
|
||||
fragShaderSrc.append("}\n");
|
||||
|
||||
GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId,
|
||||
GR_GL_FRAGMENT_SHADER, fragShaderSrc,
|
||||
gpu->gpuStats());
|
||||
if (!fragShaderId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*shaderIds->append() = fragShaderId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
|
||||
if (fHasCustomColorOutput) {
|
||||
GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
|
||||
}
|
||||
if (fHasSecondaryOutput) {
|
||||
GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** fsInName,
|
||||
GrGLShaderVar::Precision fsPrecision) {
|
||||
fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
|
||||
if (fsInName) {
|
||||
*fsInName = name;
|
||||
}
|
||||
}
|
||||
|
@ -7,18 +7,16 @@
|
||||
|
||||
#ifndef GrGLFragmentShaderBuilder_DEFINED
|
||||
#define GrGLFragmentShaderBuilder_DEFINED
|
||||
|
||||
#include "GrGLShaderBuilder.h"
|
||||
|
||||
class GrGLProgramBuilder;
|
||||
|
||||
/*
|
||||
* This base class encapsulates the functionality which all GrProcessors are allowed to use in their
|
||||
* fragment shader
|
||||
* This base class encapsulates the functionality which the GP uses to build fragment shaders
|
||||
*/
|
||||
class GrGLProcessorFragmentShaderBuilder : public GrGLShaderBuilder {
|
||||
class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
|
||||
public:
|
||||
GrGLProcessorFragmentShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
|
||||
virtual ~GrGLProcessorFragmentShaderBuilder() {}
|
||||
GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
|
||||
virtual ~GrGLGPFragmentBuilder() {}
|
||||
/**
|
||||
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile
|
||||
* if code is added that uses one of these features without calling enableFeature()
|
||||
@ -53,20 +51,23 @@ private:
|
||||
|
||||
/*
|
||||
* Fragment processor's, in addition to all of the above, may need to use dst color so they use
|
||||
* this builder to create their shader
|
||||
* this builder to create their shader. Because this is the only shader builder the FP sees, we
|
||||
* just call it FPShaderBuilder
|
||||
*/
|
||||
class GrGLFragmentProcessorShaderBuilder : public GrGLProcessorFragmentShaderBuilder {
|
||||
class GrGLFPFragmentBuilder : public GrGLGPFragmentBuilder {
|
||||
public:
|
||||
GrGLFragmentProcessorShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
|
||||
GrGLFPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
|
||||
|
||||
/** Returns the variable name that holds the color of the destination pixel. This may be NULL if
|
||||
no effect advertised that it will read the destination. */
|
||||
virtual const char* dstColor() = 0;
|
||||
|
||||
private:
|
||||
typedef GrGLProcessorFragmentShaderBuilder INHERITED;
|
||||
typedef GrGLGPFragmentBuilder INHERITED;
|
||||
};
|
||||
|
||||
class GrGLFragmentShaderBuilder : public GrGLFragmentProcessorShaderBuilder {
|
||||
// TODO rename to Fragment Builder
|
||||
class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
|
||||
public:
|
||||
typedef uint8_t DstReadKey;
|
||||
typedef uint8_t FragPosKey;
|
||||
@ -83,39 +84,42 @@ public:
|
||||
|
||||
GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc);
|
||||
|
||||
virtual const char* dstColor() SK_OVERRIDE;
|
||||
|
||||
// true public interface, defined explicitly in the abstract interfaces above
|
||||
virtual bool enableFeature(GLSLFeature) SK_OVERRIDE;
|
||||
|
||||
virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
|
||||
int index) SK_OVERRIDE;
|
||||
|
||||
virtual const char* fragmentPosition() SK_OVERRIDE;
|
||||
virtual const char* dstColor() SK_OVERRIDE;
|
||||
|
||||
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
|
||||
void emitCodeToReadDstTexture();
|
||||
void enableCustomOutput();
|
||||
void enableSecondaryOutput();
|
||||
const char* getPrimaryColorOutputName() const;
|
||||
const char* getSecondaryColorOutputName() const;
|
||||
void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
|
||||
void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
|
||||
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
|
||||
void bindFragmentShaderLocations(GrGLuint programID);
|
||||
|
||||
private:
|
||||
/*
|
||||
* An internal call for GrGLFullProgramBuilder to use to add varyings to the vertex shader
|
||||
* An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
|
||||
*/
|
||||
void addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** fsInName,
|
||||
GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision);
|
||||
|
||||
/*
|
||||
* Private functions used by GrGLProgramBuilder for compilation
|
||||
*/
|
||||
void bindProgramLocations(GrGLuint programId);
|
||||
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
|
||||
void emitCodeBeforeEffects();
|
||||
void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
|
||||
|
||||
/** Enables using the secondary color output and returns the name of the var in which it is
|
||||
to be stored */
|
||||
const char* enableSecondaryOutput();
|
||||
|
||||
/** Gets the name of the primary color output. */
|
||||
const char* getColorOutputName() const;
|
||||
// As GLProcessors emit code, there are some conditions we need to verify. We use the below
|
||||
// state to track this. The reset call is called per processor emitted.
|
||||
bool hasReadDstColor() const { return fHasReadDstColor; }
|
||||
bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
|
||||
void reset() {
|
||||
fHasReadDstColor = false;
|
||||
fHasReadFragmentPosition = false;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Features that should only be enabled by GrGLFragmentShaderBuilder itself.
|
||||
*/
|
||||
@ -132,21 +136,29 @@ private:
|
||||
kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
|
||||
};
|
||||
|
||||
// Interpretation of FragPosKey when generating code
|
||||
enum {
|
||||
kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
|
||||
kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
|
||||
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
|
||||
};
|
||||
|
||||
static const char* kDstCopyColorName;
|
||||
|
||||
bool fHasCustomColorOutput;
|
||||
bool fHasSecondaryOutput;
|
||||
bool fSetupFragPosition;
|
||||
bool fTopLeftFragPosRead;
|
||||
|
||||
friend class GrGLProgramBuilder;
|
||||
friend class GrGLFullProgramBuilder;
|
||||
// some state to verify shaders and effects are consistent, this is reset between effects by
|
||||
// the program creator
|
||||
bool fHasReadDstColor;
|
||||
bool fHasReadFragmentPosition;
|
||||
|
||||
typedef GrGLFragmentProcessorShaderBuilder INHERITED;
|
||||
friend class GrGLNvprProgramBuilder;
|
||||
friend class GrGLProgramBuilder;
|
||||
|
||||
typedef GrGLFPFragmentBuilder INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -10,12 +10,12 @@
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "../GrGpuGL.h"
|
||||
|
||||
GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program)
|
||||
GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
|
||||
: INHERITED(program) {
|
||||
|
||||
}
|
||||
|
||||
void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
|
||||
void GrGLGeometryBuilder::addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** gsOutName) {
|
||||
// if we have a GS take each varying in as an array
|
||||
@ -35,15 +35,15 @@ void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
|
||||
}
|
||||
|
||||
|
||||
bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) const {
|
||||
const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext();
|
||||
SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
|
||||
SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()));
|
||||
geomShaderSrc.append("layout(triangles) in;\n"
|
||||
"layout(triangle_strip, max_vertices = 6) out;\n");
|
||||
fProgramBuilder->appendDecls(fInputs, &geomShaderSrc);
|
||||
fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc);
|
||||
this->appendDecls(fInputs, &geomShaderSrc);
|
||||
this->appendDecls(fOutputs, &geomShaderSrc);
|
||||
geomShaderSrc.append("void main() {\n");
|
||||
geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
|
||||
"\t\tgl_Position = gl_in[i].gl_Position;\n");
|
||||
|
@ -10,12 +10,9 @@
|
||||
|
||||
#include "GrGLShaderBuilder.h"
|
||||
|
||||
class GrGLProgramBuilder;
|
||||
|
||||
class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder {
|
||||
class GrGLGeometryBuilder : public GrGLShaderBuilder {
|
||||
public:
|
||||
GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program);
|
||||
private:
|
||||
GrGLGeometryBuilder(GrGLProgramBuilder* program);
|
||||
/*
|
||||
* an internal call for GrGLFullProgramBuilder to add varyings
|
||||
*/
|
||||
@ -25,8 +22,7 @@ private:
|
||||
|
||||
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
|
||||
|
||||
friend class GrGLFullProgramBuilder;
|
||||
typedef GrGLFullShaderBuilder INHERITED;
|
||||
typedef GrGLShaderBuilder INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
55
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
Normal file
55
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
Normal 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));
|
||||
}
|
30
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
Normal file
30
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
Normal 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
|
84
src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
Normal file
84
src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
Normal 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));
|
||||
}
|
56
src/gpu/gl/builders/GrGLNvprProgramBuilder.h
Normal file
56
src/gpu/gl/builders/GrGLNvprProgramBuilder.h
Normal 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
|
@ -5,110 +5,151 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
#include "gl/GrGLProgram.h"
|
||||
#include "gl/GrGLSLPrettyPrint.h"
|
||||
#include "gl/GrGLUniformHandle.h"
|
||||
#include "GrCoordTransform.h"
|
||||
#include "../GrGpuGL.h"
|
||||
#include "GrGLFragmentShaderBuilder.h"
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrGLLegacyNvprProgramBuilder.h"
|
||||
#include "GrGLNvprProgramBuilder.h"
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrGLVertexShaderBuilder.h"
|
||||
#include "SkRTConf.h"
|
||||
#include "SkTraceEvent.h"
|
||||
|
||||
namespace {
|
||||
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
|
||||
|
||||
// number of each input/output type in a single allocation block
|
||||
static const int kVarsPerBlock = 8;
|
||||
|
||||
// ES2 FS only guarantees mediump and lowp support
|
||||
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[]) {
|
||||
const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
|
||||
|
||||
fFS.emitCodeBeforeEffects();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// get the initial color and coverage to feed into the first effect in each effect chain
|
||||
|
||||
GrGLSLExpr4 inputColor;
|
||||
GrGLSLExpr4 inputCoverage;
|
||||
|
||||
if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
|
||||
const char* name;
|
||||
fUniformHandles.fColorUni =
|
||||
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"Color",
|
||||
&name);
|
||||
inputColor = GrGLSLExpr4(name);
|
||||
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
|
||||
inputColor = GrGLSLExpr4(1);
|
||||
}
|
||||
|
||||
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
|
||||
const char* name;
|
||||
fUniformHandles.fCoverageUni =
|
||||
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"Coverage",
|
||||
&name);
|
||||
inputCoverage = GrGLSLExpr4(name);
|
||||
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
|
||||
inputCoverage = GrGLSLExpr4(1);
|
||||
}
|
||||
|
||||
// Subclasses drive effect emitting
|
||||
this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor,
|
||||
&inputCoverage);
|
||||
|
||||
fFS.emitCodeAfterEffects(inputColor, inputCoverage);
|
||||
|
||||
if (!this->finish()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const int GrGLProgramBuilder::kVarsPerBlock = 8;
|
||||
|
||||
GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc,
|
||||
GrGpu::DrawType drawType,
|
||||
const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[],
|
||||
GrGpuGL* gpu) {
|
||||
// create a builder. This will be handed off to effects so they can use it to add
|
||||
// uniforms, varyings, textures, etc
|
||||
SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
|
||||
optState,
|
||||
drawType,
|
||||
SkToBool(geometryProcessor),
|
||||
gpu));
|
||||
|
||||
GrGLProgramBuilder* pb = builder.get();
|
||||
const GrGLProgramDesc::KeyHeader& header = pb->header();
|
||||
|
||||
// emit code to read the dst copy texture, if necessary
|
||||
if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
|
||||
&& !gpu->glCaps().fbFetchSupport()) {
|
||||
pb->fFS.emitCodeToReadDstTexture();
|
||||
}
|
||||
|
||||
// get the initial color and coverage to feed into the first effect in each effect chain
|
||||
GrGLSLExpr4 inputColor, inputCoverage;
|
||||
pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
|
||||
|
||||
// if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
|
||||
// to setup a few more things like builtin vertex attributes
|
||||
bool hasVertexShader = !header.fUseFragShaderOnly;
|
||||
if (hasVertexShader) {
|
||||
pb->fVS.setupLocalCoords();
|
||||
pb->fVS.transformGLToSkiaCoords();
|
||||
if (header.fEmitsPointSize) {
|
||||
pb->fVS.codeAppend("gl_PointSize = 1.0;");
|
||||
}
|
||||
if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
|
||||
pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
|
||||
}
|
||||
if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
|
||||
pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
|
||||
&inputCoverage);
|
||||
|
||||
if (hasVertexShader) {
|
||||
pb->fVS.transformSkiaToGLCoords();
|
||||
}
|
||||
|
||||
// write the secondary color output if necessary
|
||||
if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
|
||||
pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
|
||||
}
|
||||
|
||||
pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
|
||||
|
||||
return pb->finalize();
|
||||
}
|
||||
|
||||
GrGLProgramBuilder*
|
||||
GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
|
||||
const GrOptDrawState& optState,
|
||||
GrGpu::DrawType drawType,
|
||||
bool hasGeometryProcessor,
|
||||
GrGpuGL* gpu) {
|
||||
if (desc.getHeader().fUseFragShaderOnly) {
|
||||
SkASSERT(gpu->glCaps().pathRenderingSupport());
|
||||
SkASSERT(gpu->glPathRendering()->texturingMode() ==
|
||||
GrGLPathRendering::FixedFunction_TexturingMode);
|
||||
SkASSERT(!hasGeometryProcessor);
|
||||
return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
|
||||
} else if (GrGpu::IsPathRenderingDrawType(drawType)) {
|
||||
SkASSERT(gpu->glCaps().pathRenderingSupport());
|
||||
SkASSERT(gpu->glPathRendering()->texturingMode() ==
|
||||
GrGLPathRendering::SeparableShaders_TexturingMode);
|
||||
SkASSERT(!hasGeometryProcessor);
|
||||
return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
|
||||
} else {
|
||||
return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
|
||||
const GrGLProgramDesc& desc)
|
||||
: fEffectEmitter(NULL)
|
||||
, fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly))
|
||||
, fTexCoordSetCnt(0)
|
||||
, fProgramID(0)
|
||||
: fVS(this)
|
||||
, fGS(this)
|
||||
, fFS(this, desc)
|
||||
, fSeparableVaryingInfos(kVarsPerBlock)
|
||||
, fGrProcessorEmitter(this)
|
||||
, fOutOfStage(true)
|
||||
, fStageIndex(-1)
|
||||
, fOptState(optState)
|
||||
, fDesc(desc)
|
||||
, fGpu(gpu)
|
||||
, fUniforms(kVarsPerBlock) {
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** vsOutName,
|
||||
const char** fsInName,
|
||||
GrGLShaderVar::Precision fsPrecision) {
|
||||
SkString* fsInputName = fVS.addVarying(type, name, vsOutName);
|
||||
fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
|
||||
if ('\0' == prefix) {
|
||||
*out = name;
|
||||
} else {
|
||||
out->printf("%c%s", prefix, name);
|
||||
}
|
||||
if (fCodeStage.inStageCode()) {
|
||||
if (!fOutOfStage) {
|
||||
if (out->endsWith('_')) {
|
||||
// Names containing "__" are reserved.
|
||||
out->append("x");
|
||||
}
|
||||
out->appendf("_Stage%d", fCodeStage.stageIndex());
|
||||
out->appendf("_Stage%d", fStageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,13 +184,6 @@ GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
|
||||
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
|
||||
for (int i = 0; i < vars.count(); ++i) {
|
||||
vars[i].appendDecl(this->ctxInfo(), out);
|
||||
out->append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
|
||||
SkString* out) const {
|
||||
for (int i = 0; i < fUniforms.count(); ++i) {
|
||||
@ -160,20 +194,129 @@ void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[],
|
||||
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
|
||||
return fGpu->ctxInfo();
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
|
||||
GrGLSLExpr4* inputCoverage) {
|
||||
const GrGLProgramDesc::KeyHeader& header = this->header();
|
||||
if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
|
||||
const char* name;
|
||||
fUniformHandles.fColorUni =
|
||||
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"Color",
|
||||
&name);
|
||||
*inputColor = GrGLSLExpr4(name);
|
||||
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
|
||||
*inputColor = GrGLSLExpr4(1);
|
||||
}
|
||||
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
|
||||
const char* name;
|
||||
fUniformHandles.fCoverageUni =
|
||||
this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"Coverage",
|
||||
&name);
|
||||
*inputCoverage = GrGLSLExpr4(name);
|
||||
} else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
|
||||
*inputCoverage = GrGLSLExpr4(1);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[],
|
||||
GrGLSLExpr4* inputColor,
|
||||
GrGLSLExpr4* inputCoverage) {
|
||||
bool useLocalCoords = fVS.hasExplicitLocalCoords();
|
||||
|
||||
EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType);
|
||||
int numColorEffects = fDesc.numColorEffects();
|
||||
GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects,
|
||||
useLocalCoords));
|
||||
this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
|
||||
inputColor, ip);
|
||||
fColorEffects.reset(ip);
|
||||
|
||||
if (geometryProcessor) {
|
||||
fVS.emitAttributes(*geometryProcessor->getProcessor());
|
||||
EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType);
|
||||
ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
|
||||
this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider,
|
||||
inputCoverage, ip);
|
||||
fGeometryProcessor.reset(ip);
|
||||
}
|
||||
|
||||
EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType);
|
||||
int numCoverageEffects = fDesc.numCoverageEffects();
|
||||
ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords));
|
||||
this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects,
|
||||
coverageKeyProvider, inputCoverage, ip);
|
||||
fCoverageEffects.reset(ip);
|
||||
}
|
||||
|
||||
template <class ProcessorStage>
|
||||
void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[],
|
||||
int effectCnt,
|
||||
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* fsInOutColor) {
|
||||
const EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* fsInOutColor,
|
||||
GrGLInstalledProcessors* installedProcessors) {
|
||||
bool effectEmitted = false;
|
||||
|
||||
GrGLSLExpr4 inColor = *fsInOutColor;
|
||||
GrGLSLExpr4 outColor;
|
||||
|
||||
for (int e = 0; e < effectCnt; ++e) {
|
||||
fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor());
|
||||
fEffectEmitter = &fGrProcessorEmitter;
|
||||
// calls into the subclass to emit the actual effect into the program effect object
|
||||
this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor);
|
||||
// Program builders have a bit of state we need to clear with each effect
|
||||
AutoStageAdvance adv(this);
|
||||
const ProcessorStage& stage = *processStages[e];
|
||||
SkASSERT(stage.getProcessor());
|
||||
|
||||
if (inColor.isZeros()) {
|
||||
SkString inColorName;
|
||||
|
||||
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
||||
this->nameVariable(&inColorName, '\0', "input");
|
||||
fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
|
||||
inColor = inColorName;
|
||||
}
|
||||
|
||||
// create var to hold stage result
|
||||
SkString outColorName;
|
||||
this->nameVariable(&outColorName, '\0', "output");
|
||||
fFS.codeAppendf("vec4 %s;", outColorName.c_str());
|
||||
outColor = outColorName;
|
||||
|
||||
SkASSERT(installedProcessors);
|
||||
const typename ProcessorStage::Processor& processor = *stage.getProcessor();
|
||||
SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms());
|
||||
SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures());
|
||||
|
||||
this->emitTransforms(stage, &coords, installedProcessors);
|
||||
this->emitSamplers(processor, &samplers, installedProcessors);
|
||||
|
||||
typename ProcessorStage::GLProcessor* glEffect =
|
||||
processor.getFactory().createGLInstance(processor);
|
||||
installedProcessors->addEffect(glEffect);
|
||||
|
||||
// Enclose custom code in a block to avoid namespace conflicts
|
||||
SkString openBrace;
|
||||
openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
|
||||
fFS.codeAppend(openBrace.c_str());
|
||||
fVS.codeAppend(openBrace.c_str());
|
||||
|
||||
glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(),
|
||||
inColor.isOnes() ? NULL : inColor.c_str(), coords, samplers);
|
||||
|
||||
// We have to check that effects and the code they emit are consistent, ie if an effect
|
||||
// asks for dst color, then the emit code needs to follow suit
|
||||
verify(processor);
|
||||
fFS.codeAppend("}");
|
||||
fVS.codeAppend("}");
|
||||
|
||||
inColor = outColor;
|
||||
effectEmitted = true;
|
||||
}
|
||||
|
||||
@ -182,40 +325,77 @@ void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage,
|
||||
int effectIndex,
|
||||
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* inColor,
|
||||
GrGLSLExpr4* outColor) {
|
||||
SkASSERT(effectStage.getProcessor());
|
||||
CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
|
||||
|
||||
if (inColor->isZeros()) {
|
||||
SkString inColorName;
|
||||
|
||||
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
||||
this->nameVariable(&inColorName, '\0', "input");
|
||||
fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str());
|
||||
*inColor = inColorName;
|
||||
}
|
||||
|
||||
// create var to hold stage result
|
||||
SkString outColorName;
|
||||
this->nameVariable(&outColorName, '\0', "output");
|
||||
fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
|
||||
*outColor = outColorName;
|
||||
|
||||
this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(),
|
||||
inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex());
|
||||
|
||||
*inColor = *outColor;
|
||||
void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
|
||||
SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
|
||||
GrGLProcessor::TextureSamplerArray* outSamplers) {
|
||||
SkTArray<GrGLProgramEffects::Sampler, true>& samplers =
|
||||
this->getProgramEffects()->addSamplers();
|
||||
int numTextures = effect.numTextures();
|
||||
void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
|
||||
SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
|
||||
SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
|
||||
GrGLProcessor::TransformedCoordsArray* outCoords,
|
||||
GrGLInstalledProcessors* installedProcessors) {
|
||||
SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
|
||||
installedProcessors->addTransforms();
|
||||
const GrProcessor* effect = effectStage.getProcessor();
|
||||
int numTransforms = effect->numTransforms();
|
||||
transforms.push_back_n(numTransforms);
|
||||
|
||||
for (int t = 0; t < numTransforms; t++) {
|
||||
const char* uniName = "StageMatrix";
|
||||
GrSLType varyingType =
|
||||
effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
|
||||
kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
|
||||
SkString suffixedUniName;
|
||||
if (0 != t) {
|
||||
suffixedUniName.append(uniName);
|
||||
suffixedUniName.appendf("_%i", t);
|
||||
uniName = suffixedUniName.c_str();
|
||||
}
|
||||
transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType,
|
||||
uniName,
|
||||
&uniName).toShaderBuilderIndex();
|
||||
|
||||
const char* varyingName = "MatrixCoord";
|
||||
SkString suffixedVaryingName;
|
||||
if (0 != t) {
|
||||
suffixedVaryingName.append(varyingName);
|
||||
suffixedVaryingName.appendf("_%i", t);
|
||||
varyingName = suffixedVaryingName.c_str();
|
||||
}
|
||||
const char* vsVaryingName;
|
||||
const char* fsVaryingName;
|
||||
this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
|
||||
|
||||
const GrGLShaderVar& coords =
|
||||
kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
|
||||
fVS.positionAttribute() :
|
||||
fVS.localCoordsAttribute();
|
||||
|
||||
// varying = matrix * coords (logically)
|
||||
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
|
||||
vsVaryingName, uniName, coords.c_str());
|
||||
} else {
|
||||
fVS.codeAppendf("%s = %s * vec3(%s, 1);",
|
||||
vsVaryingName, uniName, coords.c_str());
|
||||
}
|
||||
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
|
||||
(SkString(fsVaryingName), varyingType));
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
|
||||
GrGLProcessor::TextureSamplerArray* outSamplers,
|
||||
GrGLInstalledProcessors* installedProcessors) {
|
||||
SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
|
||||
int numTextures = processor.numTextures();
|
||||
samplers.push_back_n(numTextures);
|
||||
SkString name;
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
@ -224,27 +404,37 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
|
||||
kSampler2D_GrSLType,
|
||||
name.c_str());
|
||||
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
|
||||
(samplers[t].fUniform, effect.textureAccess(t)));
|
||||
(samplers[t].fUniform, processor.textureAccess(t)));
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLProgramBuilder::finish() {
|
||||
SkASSERT(0 == fProgramID);
|
||||
GL_CALL_RET(fProgramID, CreateProgram());
|
||||
if (!fProgramID) {
|
||||
return false;
|
||||
GrGLProgram* GrGLProgramBuilder::finalize() {
|
||||
// verify we can get a program id
|
||||
GrGLuint programID;
|
||||
GL_CALL_RET(programID, CreateProgram());
|
||||
if (0 == programID) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// compile shaders and bind attributes / uniforms
|
||||
SkTDArray<GrGLuint> shadersToDelete;
|
||||
|
||||
if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
|
||||
GL_CALL(DeleteProgram(fProgramID));
|
||||
return false;
|
||||
if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
|
||||
this->cleanupProgram(programID, shadersToDelete);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->bindProgramLocations(fProgramID);
|
||||
|
||||
GL_CALL(LinkProgram(fProgramID));
|
||||
if (!this->header().fUseFragShaderOnly) {
|
||||
if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
|
||||
this->cleanupProgram(programID, shadersToDelete);
|
||||
return NULL;
|
||||
}
|
||||
fVS.bindVertexAttributes(programID);
|
||||
}
|
||||
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
|
||||
if (usingBindUniform) {
|
||||
this->bindUniformLocations(programID);
|
||||
}
|
||||
fFS.bindFragmentShaderLocations(programID);
|
||||
GL_CALL(LinkProgram(programID));
|
||||
|
||||
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
|
||||
bool checkLinked = !fGpu->ctxInfo().isChromium();
|
||||
@ -252,80 +442,78 @@ bool GrGLProgramBuilder::finish() {
|
||||
checkLinked = true;
|
||||
#endif
|
||||
if (checkLinked) {
|
||||
checkLinkStatus(programID);
|
||||
}
|
||||
if (!usingBindUniform) {
|
||||
this->resolveUniformLocations(programID);
|
||||
}
|
||||
|
||||
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(fProgramID, GR_GL_LINK_STATUS, &linked));
|
||||
GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
|
||||
if (!linked) {
|
||||
GrGLint infoLen = GR_GL_INIT_ZERO;
|
||||
GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
|
||||
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(fProgramID,
|
||||
GL_CALL(GetProgramInfoLog(programID,
|
||||
infoLen+1,
|
||||
&length,
|
||||
(char*)log.get()));
|
||||
GrPrintf((char*)log.get());
|
||||
}
|
||||
SkDEBUGFAIL("Error linking program");
|
||||
GL_CALL(DeleteProgram(fProgramID));
|
||||
fProgramID = 0;
|
||||
return false;
|
||||
GL_CALL(DeleteProgram(programID));
|
||||
programID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this->resolveProgramLocations(fProgramID);
|
||||
|
||||
for (int i = 0; i < shadersToDelete.count(); ++i) {
|
||||
GL_CALL(DeleteShader(shadersToDelete[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
return SkToBool(linked);
|
||||
}
|
||||
|
||||
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) {
|
||||
void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
|
||||
int count = fUniforms.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
GrGLint location;
|
||||
GL_CALL_RET(location,
|
||||
GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
|
||||
GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
|
||||
fUniforms[i].fLocation = location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
|
||||
GL_CALL(DeleteProgram(programID));
|
||||
cleanupShaders(shaderIDs);
|
||||
}
|
||||
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
|
||||
for (int i = 0; i < shaderIDs.count(); ++i) {
|
||||
GL_CALL(DeleteShader(shaderIDs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
|
||||
return fGpu->ctxInfo();
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -8,31 +8,25 @@
|
||||
#ifndef GrGLProgramBuilder_DEFINED
|
||||
#define GrGLProgramBuilder_DEFINED
|
||||
|
||||
#include "GrAllocator.h"
|
||||
#include "GrBackendProcessorFactory.h"
|
||||
#include "GrColor.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrGLFragmentShaderBuilder.h"
|
||||
#include "GrGLGeometryShaderBuilder.h"
|
||||
#include "GrGLVertexShaderBuilder.h"
|
||||
#include "SkTypes.h"
|
||||
#include "gl/GrGLProcessor.h"
|
||||
#include "gl/GrGLProgramDesc.h"
|
||||
#include "gl/GrGLProgramEffects.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLProgramDataManager.h"
|
||||
#include "../GrGLProgramDataManager.h"
|
||||
#include "../GrGLUniformHandle.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
class GrGLInstalledProcessors;
|
||||
|
||||
class GrGLContextInfo;
|
||||
class GrProcessorStage;
|
||||
class GrGLProgramDesc;
|
||||
|
||||
/**
|
||||
Contains all the incremental state of a shader as it is being built,as well as helpers to
|
||||
manipulate that state.
|
||||
*/
|
||||
class GrGLProgramBuilder {
|
||||
/*
|
||||
* This is the base class for a series of interfaces. This base class *MUST* remain abstract with
|
||||
* NO data members because it is used in multiple interface inheritance.
|
||||
* Heirarchy:
|
||||
* GrGLUniformBuilder
|
||||
* / \
|
||||
* GrGLFPBuilder GrGLGPBuilder
|
||||
* \ /
|
||||
* GrGLProgramBuilder(internal use only)
|
||||
*/
|
||||
class GrGLUniformBuilder {
|
||||
public:
|
||||
enum ShaderVisibility {
|
||||
kVertex_Visibility = 0x1,
|
||||
@ -40,8 +34,127 @@ public:
|
||||
kFragment_Visibility = 0x4,
|
||||
};
|
||||
|
||||
virtual ~GrGLUniformBuilder() {}
|
||||
|
||||
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
||||
typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
|
||||
|
||||
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
|
||||
visibility is a bitfield of ShaderVisibility values indicating from which shaders the
|
||||
uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
|
||||
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
|
||||
it will refer to the final uniform name after return. Use the addUniformArray variant to add
|
||||
an array of uniforms. */
|
||||
virtual UniformHandle addUniform(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
const char** outName = NULL) = 0;
|
||||
virtual UniformHandle addUniformArray(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
int arrayCount,
|
||||
const char** outName = NULL) = 0;
|
||||
|
||||
virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
|
||||
|
||||
/**
|
||||
* Shortcut for getUniformVariable(u).c_str()
|
||||
*/
|
||||
virtual const char* getUniformCStr(UniformHandle u) const = 0;
|
||||
|
||||
virtual const GrGLContextInfo& ctxInfo() const = 0;
|
||||
|
||||
virtual GrGpuGL* gpu() const = 0;
|
||||
|
||||
/*
|
||||
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
|
||||
*/
|
||||
};
|
||||
|
||||
/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
|
||||
class GrGLGPBuilder : public virtual GrGLUniformBuilder {
|
||||
public:
|
||||
virtual void addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** vsOutName = NULL,
|
||||
const char** fsInName = NULL,
|
||||
GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
|
||||
|
||||
// TODO rename getFragmentBuilder
|
||||
virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
|
||||
virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
|
||||
|
||||
/*
|
||||
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
|
||||
*/
|
||||
};
|
||||
|
||||
/* a specializations for FPs. Lets the user add uniforms and FS code */
|
||||
class GrGLFPBuilder : public virtual GrGLUniformBuilder {
|
||||
public:
|
||||
virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
|
||||
|
||||
/*
|
||||
* *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Please note - no diamond problems because of virtual inheritance. Also, both base classes
|
||||
* are pure virtual with no data members. This is the base class for program building.
|
||||
* Subclasses are nearly identical but each has their own way of emitting transforms. State for
|
||||
* each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
|
||||
* respective builders
|
||||
*/
|
||||
class GrGLProgramBuilder : public GrGLGPBuilder,
|
||||
public GrGLFPBuilder {
|
||||
public:
|
||||
/** Generates a shader program.
|
||||
*
|
||||
* The program implements what is specified in the stages given as input.
|
||||
* After successful generation, the builder result objects are available
|
||||
* to be used.
|
||||
* @return true if generation was successful.
|
||||
*/
|
||||
static GrGLProgram* CreateProgram(const GrOptDrawState&,
|
||||
const GrGLProgramDesc&,
|
||||
GrGpu::DrawType,
|
||||
const GrGeometryStage* inGeometryProcessor,
|
||||
const GrFragmentStage* inColorStages[],
|
||||
const GrFragmentStage* inCoverageStages[],
|
||||
GrGpuGL* gpu);
|
||||
|
||||
virtual UniformHandle addUniform(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
const char** outName = NULL) SK_OVERRIDE {
|
||||
return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
|
||||
}
|
||||
virtual UniformHandle addUniformArray(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
int arrayCount,
|
||||
const char** outName = NULL) SK_OVERRIDE;
|
||||
|
||||
virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
|
||||
return fUniforms[u.toShaderBuilderIndex()].fVariable;
|
||||
}
|
||||
|
||||
virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
|
||||
return this->getUniformVariable(u).c_str();
|
||||
}
|
||||
|
||||
virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
|
||||
|
||||
virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
|
||||
|
||||
virtual GrGLFragmentShaderBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
|
||||
virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
|
||||
|
||||
virtual void addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** vsOutName = NULL,
|
||||
const char** fsInName = NULL,
|
||||
GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
|
||||
|
||||
// Handles for program uniforms (other than per-effect uniforms)
|
||||
struct BuiltinUniformHandles {
|
||||
@ -60,278 +173,176 @@ public:
|
||||
UniformHandle fDstCopySamplerUni;
|
||||
};
|
||||
|
||||
struct UniformInfo {
|
||||
GrGLShaderVar fVariable;
|
||||
uint32_t fVisibility;
|
||||
GrGLint fLocation;
|
||||
};
|
||||
|
||||
// This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
|
||||
// after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
|
||||
// name strings. Otherwise, we'd have to hand out copies.
|
||||
typedef GrTAllocator<UniformInfo> UniformInfoArray;
|
||||
|
||||
struct SeparableVaryingInfo {
|
||||
GrGLShaderVar fVariable;
|
||||
GrGLint fLocation;
|
||||
};
|
||||
|
||||
typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
|
||||
|
||||
/** Generates a shader program.
|
||||
*
|
||||
* The program implements what is specified in the stages given as input.
|
||||
* After successful generation, the builder result objects are available
|
||||
* to be used.
|
||||
* @return true if generation was successful.
|
||||
*/
|
||||
|
||||
bool genProgram(const GrGeometryStage* inGeometryProcessor,
|
||||
const GrFragmentStage* inColorStages[],
|
||||
const GrFragmentStage* inCoverageStages[]);
|
||||
|
||||
GrGLProgramEffects* getGeometryProcessor() const {
|
||||
SkASSERT(fProgramID); return fGeometryProcessor.get();
|
||||
}
|
||||
GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
|
||||
GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
|
||||
const BuiltinUniformHandles& getBuiltinUniformHandles() const {
|
||||
SkASSERT(fProgramID);
|
||||
return fUniformHandles;
|
||||
}
|
||||
GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
|
||||
bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
|
||||
int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
|
||||
const UniformInfoArray& getUniformInfos() const { return fUniforms; }
|
||||
const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
|
||||
return fSeparableVaryingInfos;
|
||||
}
|
||||
|
||||
virtual ~GrGLProgramBuilder() {}
|
||||
|
||||
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
|
||||
visibility is a bitfield of ShaderVisibility values indicating from which shaders the
|
||||
uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
|
||||
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
|
||||
it will refer to the final uniform name after return. Use the addUniformArray variant to add
|
||||
an array of uniforms. */
|
||||
GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
const char** outName = NULL) {
|
||||
return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
|
||||
}
|
||||
GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
|
||||
GrSLType type,
|
||||
const char* name,
|
||||
int arrayCount,
|
||||
const char** outName = NULL);
|
||||
|
||||
const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
|
||||
return fUniforms[u.toShaderBuilderIndex()].fVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for getUniformVariable(u).c_str()
|
||||
*/
|
||||
const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
|
||||
return this->getUniformVariable(u).c_str();
|
||||
}
|
||||
|
||||
const GrGLContextInfo& ctxInfo() const;
|
||||
|
||||
GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
|
||||
GrGpuGL* gpu() const { return fGpu; }
|
||||
|
||||
protected:
|
||||
typedef GrTAllocator<GrGLShaderVar> VarArray;
|
||||
static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
|
||||
const GrOptDrawState&,
|
||||
GrGpu::DrawType,
|
||||
bool hasGeometryProcessor,
|
||||
GrGpuGL*);
|
||||
|
||||
GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
|
||||
|
||||
const GrOptDrawState& optState() const { return fOptState; }
|
||||
const GrGLProgramDesc& desc() const { return fDesc; }
|
||||
|
||||
// Helper for emitEffects().
|
||||
void createAndEmitEffects(const GrFragmentStage* effectStages[],
|
||||
int effectCnt,
|
||||
const GrGLProgramDesc::EffectKeyProvider&,
|
||||
GrGLSLExpr4* inOutFSColor);
|
||||
|
||||
/*
|
||||
* A helper function called to emit the geometry processor as well as individual coverage
|
||||
* and color stages. this will call into subclasses emit effect
|
||||
*/
|
||||
void emitEffect(const GrProcessorStage& effectStage,
|
||||
int effectIndex,
|
||||
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
|
||||
GrGLSLExpr4* inColor,
|
||||
GrGLSLExpr4* outColor);
|
||||
|
||||
/**
|
||||
* Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
|
||||
* appends the necessary data to the TextureSamplerArray* object so effects can add texture
|
||||
* lookups to their code. This method is only meant to be called during the construction phase.
|
||||
*/
|
||||
void emitSamplers(const GrProcessor& effect,
|
||||
GrGLProcessor::TextureSamplerArray* outSamplers);
|
||||
const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
|
||||
|
||||
// Generates a name for a variable. The generated string will be name prefixed by the prefix
|
||||
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
|
||||
// generating stage code.
|
||||
void nameVariable(SkString* out, char prefix, const char* name);
|
||||
|
||||
virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
|
||||
|
||||
virtual void bindProgramLocations(GrGLuint programId);
|
||||
void resolveProgramLocations(GrGLuint programId);
|
||||
|
||||
void appendDecls(const VarArray&, SkString*) const;
|
||||
void appendUniformDecls(ShaderVisibility, SkString*) const;
|
||||
|
||||
class CodeStage : SkNoncopyable {
|
||||
public:
|
||||
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
|
||||
|
||||
bool inStageCode() const {
|
||||
this->validate();
|
||||
return SkToBool(fEffectStage);
|
||||
}
|
||||
|
||||
const GrProcessorStage* effectStage() const {
|
||||
this->validate();
|
||||
return fEffectStage;
|
||||
}
|
||||
|
||||
int stageIndex() const {
|
||||
this->validate();
|
||||
return fCurrentIndex;
|
||||
}
|
||||
|
||||
class AutoStageRestore : SkNoncopyable {
|
||||
public:
|
||||
AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
|
||||
SkASSERT(codeStage);
|
||||
fSavedIndex = codeStage->fCurrentIndex;
|
||||
fSavedEffectStage = codeStage->fEffectStage;
|
||||
|
||||
if (NULL == newStage) {
|
||||
codeStage->fCurrentIndex = -1;
|
||||
} else {
|
||||
codeStage->fCurrentIndex = codeStage->fNextIndex++;
|
||||
}
|
||||
codeStage->fEffectStage = newStage;
|
||||
|
||||
fCodeStage = codeStage;
|
||||
}
|
||||
~AutoStageRestore() {
|
||||
fCodeStage->fCurrentIndex = fSavedIndex;
|
||||
fCodeStage->fEffectStage = fSavedEffectStage;
|
||||
}
|
||||
private:
|
||||
CodeStage* fCodeStage;
|
||||
int fSavedIndex;
|
||||
const GrProcessorStage* fSavedEffectStage;
|
||||
};
|
||||
private:
|
||||
void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
|
||||
int fNextIndex;
|
||||
int fCurrentIndex;
|
||||
const GrProcessorStage* fEffectStage;
|
||||
};
|
||||
|
||||
class GrGLProcessorEmitterInterface {
|
||||
public:
|
||||
virtual ~GrGLProcessorEmitterInterface() {}
|
||||
virtual GrGLProcessor* createGLInstance() = 0;
|
||||
virtual void emit(const GrProcessorKey& key,
|
||||
const char* outColor,
|
||||
const char* inColor,
|
||||
const GrGLProcessor::TransformedCoordsArray& coords,
|
||||
const GrGLProcessor::TextureSamplerArray& samplers) = 0;
|
||||
};
|
||||
|
||||
class GrGLFragmentProcessorEmitter : public GrGLProcessorEmitterInterface {
|
||||
public:
|
||||
GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
|
||||
: fBuilder(builder)
|
||||
, fFragmentProcessor(NULL)
|
||||
, fGLFragmentProcessor(NULL) {}
|
||||
virtual ~GrGLFragmentProcessorEmitter() {}
|
||||
void set(const GrFragmentProcessor* fp) {
|
||||
SkASSERT(NULL == fFragmentProcessor);
|
||||
fFragmentProcessor = fp;
|
||||
}
|
||||
virtual GrGLProcessor* createGLInstance() {
|
||||
SkASSERT(fFragmentProcessor);
|
||||
SkASSERT(NULL == fGLFragmentProcessor);
|
||||
fGLFragmentProcessor =
|
||||
fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
|
||||
return fGLFragmentProcessor;
|
||||
}
|
||||
virtual void emit(const GrProcessorKey& key,
|
||||
const char* outColor,
|
||||
const char* inColor,
|
||||
const GrGLProcessor::TransformedCoordsArray& coords,
|
||||
const GrGLProcessor::TextureSamplerArray& samplers) {
|
||||
SkASSERT(fFragmentProcessor);
|
||||
SkASSERT(fGLFragmentProcessor);
|
||||
fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
|
||||
coords, samplers);
|
||||
// this will not leak because it hasa already been used by createGLInstance
|
||||
fGLFragmentProcessor = NULL;
|
||||
fFragmentProcessor = NULL;
|
||||
}
|
||||
private:
|
||||
GrGLProgramBuilder* fBuilder;
|
||||
const GrFragmentProcessor* fFragmentProcessor;
|
||||
GrGLFragmentProcessor* fGLFragmentProcessor;
|
||||
};
|
||||
|
||||
GrGLProcessorEmitterInterface* fEffectEmitter;
|
||||
CodeStage fCodeStage;
|
||||
SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
|
||||
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
|
||||
BuiltinUniformHandles fUniformHandles;
|
||||
bool fFragOnly;
|
||||
int fTexCoordSetCnt;
|
||||
GrGLuint fProgramID;
|
||||
GrGLFragmentShaderBuilder fFS;
|
||||
SeparableVaryingInfoArray fSeparableVaryingInfos;
|
||||
|
||||
private:
|
||||
virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
|
||||
void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
|
||||
void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
|
||||
const GrFragmentStage* colorStages[],
|
||||
const GrFragmentStage* coverageStages[],
|
||||
GrGLSLExpr4* inputColor,
|
||||
GrGLSLExpr4* inputCoverage) = 0;
|
||||
/*
|
||||
* Subclasses override emitEffect below to emit data and code for a specific single effect
|
||||
*/
|
||||
virtual void emitEffect(const GrProcessorStage&,
|
||||
const GrProcessorKey&,
|
||||
const char* outColor,
|
||||
const char* inColor,
|
||||
int stageIndex) = 0;
|
||||
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*);
|
||||
|
||||
/*
|
||||
* Because we have fragment only builders, and those builders need to implement a subclass
|
||||
* of program effects, we have to have base classes overload the program effects here
|
||||
*/
|
||||
virtual GrGLProgramEffects* getProgramEffects() = 0;
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* Compiles all the shaders, links them into a program, and writes the program id to the output
|
||||
* struct.
|
||||
**/
|
||||
bool finish();
|
||||
void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
|
||||
void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
|
||||
|
||||
GrGLFragmentProcessorEmitter fGrProcessorEmitter;
|
||||
// Subclasses create different programs
|
||||
virtual GrGLProgram* createProgram(GrGLuint programID);
|
||||
|
||||
void appendUniformDecls(ShaderVisibility, SkString*) const;
|
||||
|
||||
// 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:
|
||||
AutoStageRestore(GrGLProgramBuilder* pb)
|
||||
: fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
|
||||
~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
|
||||
private:
|
||||
GrGLProgramBuilder* fPB;
|
||||
bool fOutOfStage;
|
||||
};
|
||||
class AutoStageAdvance {
|
||||
public:
|
||||
AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
|
||||
~AutoStageAdvance() { fPB->exitStage(); }
|
||||
private:
|
||||
GrGLProgramBuilder* fPB;
|
||||
};
|
||||
void exitStage() { fOutOfStage = true; }
|
||||
void enterStage() { fOutOfStage = false; }
|
||||
int stageIndex() const { return fStageIndex; }
|
||||
|
||||
typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
|
||||
typedef GrGLProgramDataManager::UniformInfo UniformInfo;
|
||||
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
|
||||
|
||||
// number of each input/output type in a single allocation block, used by many builders
|
||||
static const int kVarsPerBlock;
|
||||
|
||||
BuiltinUniformHandles fUniformHandles;
|
||||
GrGLVertexBuilder fVS;
|
||||
GrGLGeometryBuilder fGS;
|
||||
GrGLFragmentShaderBuilder fFS;
|
||||
bool fOutOfStage;
|
||||
int fStageIndex;
|
||||
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
|
||||
SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
|
||||
|
||||
const GrOptDrawState& fOptState;
|
||||
const GrGLProgramDesc& fDesc;
|
||||
GrGpuGL* fGpu;
|
||||
UniformInfoArray fUniforms;
|
||||
|
||||
friend class GrGLShaderBuilder;
|
||||
friend class GrGLVertexBuilder;
|
||||
friend class GrGLFragmentShaderBuilder;
|
||||
friend class GrGLGeometryBuilder;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
|
||||
* and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
|
||||
* state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
|
||||
*
|
||||
* TODO We really don't need this class to have an array of processors. It makes sense for it
|
||||
* to just have one, also break out the transforms
|
||||
*/
|
||||
class GrGLInstalledProcessors : public SkRefCnt {
|
||||
public:
|
||||
GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
|
||||
: fGLProcessors(reserveCount)
|
||||
, fSamplers(reserveCount)
|
||||
, fTransforms(reserveCount)
|
||||
, fHasExplicitLocalCoords(hasExplicitLocalCoords) {
|
||||
}
|
||||
|
||||
virtual ~GrGLInstalledProcessors();
|
||||
|
||||
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
||||
|
||||
struct Sampler {
|
||||
SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
|
||||
UniformHandle fUniform;
|
||||
int fTextureUnit;
|
||||
};
|
||||
|
||||
class ShaderVarHandle {
|
||||
public:
|
||||
bool isValid() const { return fHandle > -1; }
|
||||
ShaderVarHandle() : fHandle(-1) {}
|
||||
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
|
||||
int handle() const { SkASSERT(this->isValid()); return fHandle; }
|
||||
UniformHandle convertToUniformHandle() {
|
||||
SkASSERT(this->isValid());
|
||||
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
int fHandle;
|
||||
};
|
||||
|
||||
struct Transform {
|
||||
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
|
||||
ShaderVarHandle fHandle;
|
||||
SkMatrix fCurrentValue;
|
||||
GrSLType fType;
|
||||
};
|
||||
|
||||
void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
|
||||
SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
|
||||
SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
|
||||
|
||||
SkTArray<GrGLProcessor*> fGLProcessors;
|
||||
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
|
||||
SkTArray<SkSTArray<2, Transform, true> > fTransforms;
|
||||
bool fHasExplicitLocalCoords;
|
||||
|
||||
friend class GrGLShaderBuilder;
|
||||
friend class GrGLVertexShaderBuilder;
|
||||
friend class GrGLFragmentShaderBuilder;
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "GrGLShaderBuilder.h"
|
||||
#include "GrGLFullProgramBuilder.h"
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "../GrGpuGL.h"
|
||||
#include "../GrGLShaderVar.h"
|
||||
@ -53,13 +53,12 @@ void append_texture_lookup(SkString* out,
|
||||
out->appendf(".%s", swizzle);
|
||||
}
|
||||
}
|
||||
static const int kVarsPerBlock = 8;
|
||||
}
|
||||
|
||||
GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
|
||||
: fProgramBuilder(program)
|
||||
, fInputs(kVarsPerBlock)
|
||||
, fOutputs(kVarsPerBlock)
|
||||
, fInputs(GrGLProgramBuilder::kVarsPerBlock)
|
||||
, fOutputs(GrGLProgramBuilder::kVarsPerBlock)
|
||||
, fFeaturesAddedMask(0) {
|
||||
}
|
||||
|
||||
@ -143,6 +142,13 @@ void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionNam
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
|
||||
for (int i = 0; i < vars.count(); ++i) {
|
||||
vars[i].appendDecl(fProgramBuilder->ctxInfo(), out);
|
||||
out->append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
|
||||
const char* coordName,
|
||||
uint32_t configComponentMask,
|
||||
@ -155,8 +161,3 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
|
||||
swizzle,
|
||||
kVec2f_GrSLType);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
, fFullProgramBuilder(program) {}
|
||||
|
@ -9,21 +9,12 @@
|
||||
#define GrGLShaderBuilder_DEFINED
|
||||
|
||||
#include "gl/GrGLProgramDesc.h"
|
||||
#include "gl/GrGLProgramEffects.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLProgramDataManager.h"
|
||||
#include "GrBackendProcessorFactory.h"
|
||||
#include "GrColor.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
class GrGLContextInfo;
|
||||
class GrProcessorStage;
|
||||
class GrGLProgramDesc;
|
||||
class GrGLProgramBuilder;
|
||||
class GrGLFullProgramBuilder;
|
||||
|
||||
/**
|
||||
base class for all shaders builders
|
||||
@ -32,6 +23,7 @@ class GrGLShaderBuilder {
|
||||
public:
|
||||
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
|
||||
typedef GrGLProcessor::TextureSampler TextureSampler;
|
||||
|
||||
GrGLShaderBuilder(GrGLProgramBuilder* program);
|
||||
|
||||
void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
|
||||
@ -112,7 +104,7 @@ public:
|
||||
GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
|
||||
|
||||
/**
|
||||
* Helper for begining and ending a block in the fragment code.
|
||||
* Helper for begining and ending a block in the shader code.
|
||||
*/
|
||||
class ShaderBlock {
|
||||
public:
|
||||
@ -127,7 +119,10 @@ public:
|
||||
private:
|
||||
GrGLShaderBuilder* fBuilder;
|
||||
};
|
||||
|
||||
protected:
|
||||
typedef GrTAllocator<GrGLShaderVar> VarArray;
|
||||
void appendDecls(const VarArray& vars, SkString* out) const;
|
||||
|
||||
/*
|
||||
* this super low level function is just for use internally to builders
|
||||
@ -142,8 +137,6 @@ protected:
|
||||
*/
|
||||
void addFeature(uint32_t featureBit, const char* extensionName);
|
||||
|
||||
typedef GrTAllocator<GrGLShaderVar> VarArray;
|
||||
|
||||
GrGLProgramBuilder* fProgramBuilder;
|
||||
|
||||
SkString fCode;
|
||||
@ -154,21 +147,4 @@ protected:
|
||||
VarArray fOutputs;
|
||||
uint32_t fFeaturesAddedMask;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Full Shader builder is the base class for shaders which are only accessible through full program
|
||||
* builder, ie vertex, geometry, and later TCU / TES. Using this base class, they can access the
|
||||
* full program builder functionality through the full program pointer
|
||||
*/
|
||||
class GrGLFullShaderBuilder : public GrGLShaderBuilder {
|
||||
public:
|
||||
GrGLFullShaderBuilder(GrGLFullProgramBuilder* program);
|
||||
|
||||
GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; }
|
||||
protected:
|
||||
GrGLFullProgramBuilder* fFullProgramBuilder;
|
||||
private:
|
||||
typedef GrGLShaderBuilder INHERITED;
|
||||
};
|
||||
#endif
|
||||
|
@ -6,46 +6,25 @@
|
||||
*/
|
||||
|
||||
#include "GrGLVertexShaderBuilder.h"
|
||||
#include "GrGLFullProgramBuilder.h"
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "GrGLShaderStringBuilder.h"
|
||||
#include "../GrGpuGL.h"
|
||||
#include "../../GrOptDrawState.h"
|
||||
|
||||
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
|
||||
#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
|
||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
|
||||
|
||||
namespace {
|
||||
inline const char* color_attribute_name() { return "inColor"; }
|
||||
inline const char* coverage_attribute_name() { return "inCoverage"; }
|
||||
}
|
||||
static const char* color_attribute_name() { return "inColor"; }
|
||||
static const char* coverage_attribute_name() { return "inCoverage"; }
|
||||
|
||||
GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
|
||||
GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
, fPositionVar(NULL)
|
||||
, fLocalCoordsVar(NULL) {
|
||||
}
|
||||
bool GrGLVertexShaderBuilder::addAttribute(const GrShaderVar& var) {
|
||||
SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
|
||||
for (int i = 0; i < fInputs.count(); ++i) {
|
||||
const GrGLShaderVar& attr = fInputs[i];
|
||||
// if attribute already added, don't add it again
|
||||
if (attr.getName().equals(var.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fInputs.push_back(var);
|
||||
return true;
|
||||
, fLocalCoordsVar(NULL)
|
||||
, fEffectAttribOffset(0) {
|
||||
}
|
||||
|
||||
void GrGLVertexShaderBuilder::emitAttributes(const GrGeometryProcessor& gp) {
|
||||
const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
|
||||
int numAttributes = vars.count();
|
||||
for (int a = 0; a < numAttributes; ++a) {
|
||||
this->addAttribute(vars[a]);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
|
||||
SkString* GrGLVertexBuilder::addVarying(GrSLType type, const char* name,
|
||||
const char** vsOutName) {
|
||||
fOutputs.push_back();
|
||||
fOutputs.back().setType(type);
|
||||
fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
||||
@ -54,30 +33,88 @@ void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const
|
||||
if (vsOutName) {
|
||||
*vsOutName = fOutputs.back().getName().c_str();
|
||||
}
|
||||
return fOutputs.back().accessName();
|
||||
}
|
||||
|
||||
void GrGLVertexBuilder::setupLocalCoords() {
|
||||
fPositionVar = &fInputs.push_back();
|
||||
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
|
||||
if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) {
|
||||
fLocalCoordsVar = &fInputs.push_back();
|
||||
fLocalCoordsVar->set(kVec2f_GrSLType,
|
||||
GrGLShaderVar::kAttribute_TypeModifier,
|
||||
"inLocalCoords");
|
||||
} else {
|
||||
fLocalCoordsVar = fPositionVar;
|
||||
}
|
||||
fEffectAttribOffset = fInputs.count();
|
||||
}
|
||||
|
||||
void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
|
||||
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
void GrGLVertexBuilder::transformGLToSkiaCoords() {
|
||||
const char* viewMName;
|
||||
fProgramBuilder->fUniformHandles.fViewMatrixUni =
|
||||
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType,
|
||||
"ViewM",
|
||||
&viewMName);
|
||||
|
||||
// Transform the position into Skia's device coords.
|
||||
this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);", viewMName, fPositionVar->c_str());
|
||||
}
|
||||
|
||||
void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) {
|
||||
SkString name(inName);
|
||||
const char *vsName, *fsName;
|
||||
fProgramBuilder->addVarying(kVec4f_GrSLType, name.c_str(), &vsName, &fsName);
|
||||
name.prepend("in");
|
||||
this->addAttribute(GrShaderVar(name.c_str(),
|
||||
kVec4f_GrSLType,
|
||||
GrShaderVar::kAttribute_TypeModifier));
|
||||
this->codeAppendf("%s = %s;", vsName, name.c_str());
|
||||
*out = fsName;
|
||||
fEffectAttribOffset++;
|
||||
}
|
||||
|
||||
void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) {
|
||||
const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
|
||||
int numAttributes = vars.count();
|
||||
for (int a = 0; a < numAttributes; ++a) {
|
||||
this->addAttribute(vars[a]);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLVertexBuilder::transformSkiaToGLCoords() {
|
||||
const char* rtAdjustName;
|
||||
fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
|
||||
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"rtAdjustment",
|
||||
&rtAdjustName);
|
||||
|
||||
// Transform from Skia's device coords to GL's normalized device coords.
|
||||
this->codeAppendf("gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
|
||||
rtAdjustName, rtAdjustName);
|
||||
}
|
||||
|
||||
void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
|
||||
// Bind the attrib locations to same values for all shaders
|
||||
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->header();
|
||||
SkASSERT(-1 != header.fPositionAttributeIndex);
|
||||
GL_CALL(BindAttribLocation(programId,
|
||||
GL_CALL(BindAttribLocation(programID,
|
||||
header.fPositionAttributeIndex,
|
||||
fPositionVar->c_str()));
|
||||
if (-1 != header.fLocalCoordAttributeIndex) {
|
||||
GL_CALL(BindAttribLocation(programId,
|
||||
GL_CALL(BindAttribLocation(programID,
|
||||
header.fLocalCoordAttributeIndex,
|
||||
fLocalCoordsVar->c_str()));
|
||||
}
|
||||
if (-1 != header.fColorAttributeIndex) {
|
||||
GL_CALL(BindAttribLocation(programId,
|
||||
GL_CALL(BindAttribLocation(programID,
|
||||
header.fColorAttributeIndex,
|
||||
color_attribute_name()));
|
||||
}
|
||||
if (-1 != header.fCoverageAttributeIndex) {
|
||||
GL_CALL(BindAttribLocation(programId,
|
||||
GL_CALL(BindAttribLocation(programID,
|
||||
header.fCoverageAttributeIndex,
|
||||
coverage_attribute_name()));
|
||||
}
|
||||
@ -86,6 +123,7 @@ void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
|
||||
const GrVertexAttrib* vaPtr = optState.getVertexAttribs();
|
||||
const int vaCount = optState.getVertexAttribCount();
|
||||
|
||||
// We start binding attributes after builtins
|
||||
int i = fEffectAttribOffset;
|
||||
for (int index = 0; index < vaCount; index++) {
|
||||
if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) {
|
||||
@ -97,22 +135,22 @@ void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
|
||||
index != header.fCoverageAttributeIndex);
|
||||
// We should never find another effect attribute if we have bound everything
|
||||
SkASSERT(i < fInputs.count());
|
||||
GL_CALL(BindAttribLocation(programId, index, fInputs[i].c_str()));
|
||||
GL_CALL(BindAttribLocation(programID, index, fInputs[i].c_str()));
|
||||
i++;
|
||||
}
|
||||
// Make sure we bound everything
|
||||
SkASSERT(fInputs.count() == i);
|
||||
}
|
||||
|
||||
bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) const {
|
||||
GrGpuGL* gpu = fProgramBuilder->gpu();
|
||||
const GrGLContext& glCtx = gpu->glContext();
|
||||
const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
|
||||
SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
|
||||
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
|
||||
fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
|
||||
fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
|
||||
this->appendDecls(fInputs, &vertShaderSrc);
|
||||
this->appendDecls(fOutputs, &vertShaderSrc);
|
||||
vertShaderSrc.append("void main() {");
|
||||
vertShaderSrc.append(fCode);
|
||||
vertShaderSrc.append("}\n");
|
||||
@ -126,72 +164,15 @@ bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
|
||||
const char* rtAdjustName;
|
||||
fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
|
||||
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
"rtAdjustment",
|
||||
&rtAdjustName);
|
||||
|
||||
// Transform from Skia's device coords to GL's normalized device coords.
|
||||
this->codeAppendf(
|
||||
"gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
|
||||
rtAdjustName, rtAdjustName);
|
||||
}
|
||||
|
||||
void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
|
||||
const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
||||
|
||||
fPositionVar = &fInputs.push_back();
|
||||
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
|
||||
if (-1 != header.fLocalCoordAttributeIndex) {
|
||||
fLocalCoordsVar = &fInputs.push_back();
|
||||
fLocalCoordsVar->set(kVec2f_GrSLType,
|
||||
GrGLShaderVar::kAttribute_TypeModifier,
|
||||
"inLocalCoords");
|
||||
} else {
|
||||
fLocalCoordsVar = fPositionVar;
|
||||
}
|
||||
|
||||
const char* viewMName;
|
||||
fProgramBuilder->fUniformHandles.fViewMatrixUni =
|
||||
fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType,
|
||||
"ViewM",
|
||||
&viewMName);
|
||||
|
||||
// Transform the position into Skia's device coords.
|
||||
this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
|
||||
viewMName, fPositionVar->c_str());
|
||||
|
||||
// we output point size in the GS if present
|
||||
if (header.fEmitsPointSize
|
||||
#if GR_GL_EXPERIMENTAL_GS
|
||||
&& !header.fExperimentalGS
|
||||
#endif
|
||||
) {
|
||||
this->codeAppend("gl_PointSize = 1.0;");
|
||||
}
|
||||
|
||||
if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
|
||||
this->addAttribute(GrShaderVar(color_attribute_name(),
|
||||
kVec4f_GrSLType,
|
||||
GrShaderVar::kAttribute_TypeModifier));
|
||||
const char *vsName, *fsName;
|
||||
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
|
||||
this->codeAppendf("%s = %s;", vsName, color_attribute_name());
|
||||
*color = fsName;
|
||||
}
|
||||
|
||||
if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
|
||||
this->addAttribute(GrShaderVar(coverage_attribute_name(),
|
||||
kVec4f_GrSLType,
|
||||
GrShaderVar::kAttribute_TypeModifier));
|
||||
const char *vsName, *fsName;
|
||||
fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
|
||||
this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
|
||||
*coverage = fsName;
|
||||
}
|
||||
fEffectAttribOffset = fInputs.count();
|
||||
bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) {
|
||||
SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
|
||||
for (int i = 0; i < fInputs.count(); ++i) {
|
||||
const GrGLShaderVar& attr = fInputs[i];
|
||||
// if attribute already added, don't add it again
|
||||
if (attr.getName().equals(var.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fInputs.push_back(var);
|
||||
return true;
|
||||
}
|
||||
|
@ -7,26 +7,22 @@
|
||||
|
||||
#ifndef GrGLVertexShader_DEFINED
|
||||
#define GrGLVertexShader_DEFINED
|
||||
|
||||
#include "GrGLShaderBuilder.h"
|
||||
|
||||
class GrGLProgramBuilder;
|
||||
|
||||
class GrGLVertexShaderBuilder : public GrGLFullShaderBuilder {
|
||||
// TODO we only actually ever need to return a GrGLShaderBuilder for this guy, none of the below
|
||||
// functions need to be part of VertexShaderBuilder's public interface
|
||||
class GrGLVertexBuilder : public GrGLShaderBuilder {
|
||||
public:
|
||||
GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program);
|
||||
|
||||
/*
|
||||
* this call is only for GrGLProgramEffects' internal use
|
||||
*/
|
||||
void emitAttributes(const GrGeometryProcessor& gp);
|
||||
GrGLVertexBuilder(GrGLProgramBuilder* program);
|
||||
|
||||
/**
|
||||
* Are explicit local coordinates provided as input to the vertex shader.
|
||||
*/
|
||||
bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
|
||||
|
||||
const SkString* getEffectAttributeName(int attributeIndex) const;
|
||||
|
||||
/** Returns a vertex attribute that represents the local coords in the VS. This may be the same
|
||||
as positionAttribute() or it may not be. It depends upon whether the rendering code
|
||||
specified explicit local coords or not in the GrDrawState. */
|
||||
@ -37,28 +33,25 @@ public:
|
||||
*/
|
||||
const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
|
||||
|
||||
private:
|
||||
/*
|
||||
* Add attribute will push a new attribute onto the end. It will also assert if there is
|
||||
* a duplicate attribute
|
||||
* Internal call for GrGLProgramBuilder.addVarying
|
||||
*/
|
||||
bool addAttribute(const GrShaderVar& var);
|
||||
|
||||
/*
|
||||
* Internal call for GrGLFullProgramBuilder.addVarying
|
||||
*/
|
||||
void addVarying(GrSLType type,
|
||||
const char* name,
|
||||
const char** vsOutName);
|
||||
SkString* addVarying(GrSLType type, const char* name, const char** vsOutName);
|
||||
|
||||
/*
|
||||
* private helpers for compilation by GrGLProgramBuilder
|
||||
*/
|
||||
void bindProgramLocations(GrGLuint programId);
|
||||
void setupLocalCoords();
|
||||
void transformGLToSkiaCoords();
|
||||
void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out);
|
||||
void emitAttributes(const GrGeometryProcessor& gp);
|
||||
void transformSkiaToGLCoords();
|
||||
void bindVertexAttributes(GrGLuint programID);
|
||||
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
|
||||
void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage);
|
||||
void emitCodeAfterEffects();
|
||||
|
||||
private:
|
||||
// an internal call which checks for uniquness of a var before adding it to the list of inputs
|
||||
bool addAttribute(const GrShaderVar& var);
|
||||
struct AttributePair {
|
||||
void set(int index, const SkString& name) {
|
||||
fIndex = index; fName = name;
|
||||
@ -71,9 +64,7 @@ private:
|
||||
GrGLShaderVar* fLocalCoordsVar;
|
||||
int fEffectAttribOffset;
|
||||
|
||||
friend class GrGLFullProgramBuilder;
|
||||
|
||||
typedef GrGLFullShaderBuilder INHERITED;
|
||||
typedef GrGLShaderBuilder INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "GrContextFactory.h"
|
||||
#include "GrOptDrawState.h"
|
||||
#include "effects/GrConfigConversionEffect.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
#include "gl/GrGLPathRendering.h"
|
||||
#include "gl/GrGpuGL.h"
|
||||
#include "SkChecksum.h"
|
||||
@ -24,7 +25,7 @@
|
||||
|
||||
static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
|
||||
bool* readsFragPosition, bool* requiresVertexShader) {
|
||||
if (stage.getFragmentProcessor()->willReadDstColor()) {
|
||||
if (stage.getProcessor()->willReadDstColor()) {
|
||||
*readsDst = true;
|
||||
}
|
||||
if (stage.getProcessor()->willReadFragmentPosition()) {
|
||||
@ -335,12 +336,14 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
|
||||
*this->caps(),
|
||||
drawType));
|
||||
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
|
||||
*optState.get(),
|
||||
SkAutoTUnref<GrGLProgram> program(
|
||||
GrGLProgramBuilder::CreateProgram(*optState,
|
||||
pdesc,
|
||||
geometryProcessor.get(),
|
||||
drawType,
|
||||
geometryProcessor,
|
||||
stages,
|
||||
stages + numColorStages));
|
||||
stages + numColorStages,
|
||||
this));
|
||||
for (int s = 0; s < numStages; ++s) {
|
||||
SkDELETE(stages[s]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user