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