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