diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrAARectRenderer.cpp | 394 | ||||
-rw-r--r-- | src/gpu/GrAARectRenderer.h | 18 | ||||
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.cpp | 182 | ||||
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.h | 83 | ||||
-rw-r--r-- | src/gpu/GrOptDrawState.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 12 | ||||
-rw-r--r-- | src/gpu/GrProcessor.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrBezierEffect.cpp | 12 | ||||
-rw-r--r-- | src/gpu/effects/GrCustomCoordsTextureEffect.cpp | 4 | ||||
-rw-r--r-- | src/gpu/effects/GrDashingEffect.cpp | 8 | ||||
-rwxr-xr-x | src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 12 | ||||
-rw-r--r-- | src/gpu/gl/GrGLSL.h | 8 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.cpp | 92 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.h | 24 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp | 59 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLVertexShaderBuilder.h | 17 |
17 files changed, 459 insertions, 479 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index eecc72270c..3325b1cf68 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -561,6 +561,10 @@ public: const GrShaderVar& inQuadEdge = args.fGP.cast<QuadEdgeEffect>().inQuadEdge(); GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), inQuadEdge.c_str()); + + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); } static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index ead4ea16a3..46196e2e4e 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -15,251 +15,6 @@ #include "GrGeometryProcessor.h" /////////////////////////////////////////////////////////////////////////////// -class GrGLAlignedRectEffect; - -// Axis Aligned special case -class GrAlignedRectEffect : public GrGeometryProcessor { -public: - static GrGeometryProcessor* Create() { - GR_CREATE_STATIC_PROCESSOR(gAlignedRectEffect, GrAlignedRectEffect, ()); - gAlignedRectEffect->ref(); - return gAlignedRectEffect; - } - - virtual ~GrAlignedRectEffect() {} - - static const char* Name() { return "AlignedRectEdge"; } - - const GrShaderVar& inRect() const { return fInRect; } - - virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { - return GrTBackendGeometryProcessorFactory<GrAlignedRectEffect>::getInstance(); - } - - class GLProcessor : public GrGLGeometryProcessor { - public: - GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) - : INHERITED (factory) {} - - virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - // setup the varying for the Axis aligned rect effect - // xy -> interpolated offset - // zw -> w/2+0.5, h/2+0.5 - GrGLVertToFrag v(kVec4f_GrSLType); - args.fPB->addVarying("Rect", &v); - - const GrShaderVar& inRect = args.fGP.cast<GrAlignedRectEffect>().inRect(); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.fsIn(), inRect.c_str()); - - GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); - // TODO: compute all these offsets, spans, and scales in the VS - fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", v.fsIn()); - fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", v.fsIn()); - fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); - // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects - // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. - fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); - fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); - // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum - // value of coverage that is used. In other words it is the coverage that is - // used in the interior of the rect after the ramp. - fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); - fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); - - // Compute the coverage for the rect's width - fsBuilder->codeAppendf( - "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", v.fsIn(), - v.fsIn()); - // Compute the coverage for the rect's height and merge with the width - fsBuilder->codeAppendf( - "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n", - v.fsIn(), v.fsIn()); - - - fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("coverage")).c_str()); - } - - static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} - - virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {} - - private: - typedef GrGLGeometryProcessor INHERITED; - }; - - -private: - GrAlignedRectEffect() - : fInRect(this->addVertexAttrib(GrShaderVar("inRect", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { - } - - const GrShaderVar& fInRect; - - virtual bool onIsEqual(const GrGeometryProcessor&) const SK_OVERRIDE { return true; } - - virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { - inout->mulByUnknownAlpha(); - } - - GR_DECLARE_GEOMETRY_PROCESSOR_TEST; - - typedef GrGeometryProcessor INHERITED; -}; - - -GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrAlignedRectEffect); - -GrGeometryProcessor* GrAlignedRectEffect::TestCreate(SkRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - return GrAlignedRectEffect::Create(); -} - -/////////////////////////////////////////////////////////////////////////////// -class GrGLRectEffect; - -/** - * The output of this effect is a modulation of the input color and coverage - * for an arbitrarily oriented rect. The rect is specified as: - * Center of the rect - * Unit vector point down the height of the rect - * Half width + 0.5 - * Half height + 0.5 - * The center and vector are stored in a vec4 varying ("RectEdge") with the - * center in the xy components and the vector in the zw components. - * The munged width and height are stored in a vec2 varying ("WidthHeight") - * with the width in x and the height in y. - */ - -class GrRectEffect : public GrGeometryProcessor { -public: - static GrGeometryProcessor* Create() { - GR_CREATE_STATIC_PROCESSOR(gRectEffect, GrRectEffect, ()); - gRectEffect->ref(); - return gRectEffect; - } - - virtual ~GrRectEffect() {} - - static const char* Name() { return "RectEdge"; } - - const GrShaderVar& inRectEdge() const { return fInRectEdge; } - const GrShaderVar& inWidthHeight() const { return fInWidthHeight; } - - virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { - return GrTBackendGeometryProcessorFactory<GrRectEffect>::getInstance(); - } - - class GLProcessor : public GrGLGeometryProcessor { - public: - GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) - : INHERITED (factory) {} - - virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - // setup the varying for the center point and the unit vector - // that points down the height of the rect - GrGLVertToFrag rectEdge(kVec4f_GrSLType); - args.fPB->addVarying("RectEdge", &rectEdge); - - const GrRectEffect& rectEffect = args.fGP.cast<GrRectEffect>(); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("%s = %s;", rectEdge.vsOut(), rectEffect.inRectEdge().c_str()); - - // setup the varying for width/2+.5 and height/2+.5 - GrGLVertToFrag widthHeight(kVec2f_GrSLType); - args.fPB->addVarying("WidthHeight", &widthHeight); - vsBuilder->codeAppendf("%s = %s;", - widthHeight.vsOut(), - rectEffect.inWidthHeight().c_str()); - - GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); - // TODO: compute all these offsets, spans, and scales in the VS - fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", widthHeight.fsIn()); - fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", widthHeight.fsIn()); - fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); - // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects - // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. - fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); - fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); - // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum - // value of coverage that is used. In other words it is the coverage that is - // used in the interior of the rect after the ramp. - fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); - fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); - - // Compute the coverage for the rect's width - fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", - fsBuilder->fragmentPosition(), rectEdge.fsIn()); - fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n", - rectEdge.fsIn(), rectEdge.fsIn()); - fsBuilder->codeAppendf( - "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n", - widthHeight.fsIn()); - - // Compute the coverage for the rect's height and merge with the width - fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", - rectEdge.fsIn()); - fsBuilder->codeAppendf( - "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n", - widthHeight.fsIn()); - - - fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("coverage")).c_str()); - } - - static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} - - virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {} - - private: - typedef GrGLGeometryProcessor INHERITED; - }; - - - -private: - GrRectEffect() - : fInRectEdge(this->addVertexAttrib(GrShaderVar("inRectEdge", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) - , fInWidthHeight(this->addVertexAttrib( - GrShaderVar("inWidthHeight", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { - this->setWillReadFragmentPosition(); - } - - virtual bool onIsEqual(const GrGeometryProcessor&) const SK_OVERRIDE { return true; } - - virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { - inout->mulByUnknownAlpha(); - } - - const GrShaderVar& fInRectEdge; - const GrShaderVar& fInWidthHeight; - - GR_DECLARE_GEOMETRY_PROCESSOR_TEST; - - typedef GrGeometryProcessor INHERITED; -}; - - -GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRectEffect); - -GrGeometryProcessor* GrRectEffect::TestCreate(SkRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - return GrRectEffect::Create(); -} - -/////////////////////////////////////////////////////////////////////////////// namespace { extern const GrVertexAttrib gAARectAttribs[] = { @@ -548,155 +303,6 @@ void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target, target->resetIndexSource(); } -namespace { - -// Rotated -struct RectVertex { - SkPoint fPos; - SkPoint fCenter; - SkPoint fDir; - SkPoint fWidthHeight; -}; - -// Rotated -extern const GrVertexAttrib gAARectVertexAttribs[] = { - { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, - { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding } -}; - -// Axis Aligned -struct AARectVertex { - SkPoint fPos; - SkPoint fOffset; - SkPoint fWidthHeight; -}; - -// Axis Aligned -extern const GrVertexAttrib gAAAARectVertexAttribs[] = { - { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, - { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }, -}; - -}; - -void GrAARectRenderer::shaderFillAARect(GrDrawTarget* target, - const SkRect& rect, - const SkMatrix& combinedMatrix) { - GrDrawState* drawState = target->drawState(); - - SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY()); - combinedMatrix.mapPoints(¢er, 1); - - // compute transformed (0, 1) vector - SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] }; - dir.normalize(); - - // compute transformed (width, 0) and (0, height) vectors - SkVector vec[2] = { - { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, - { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } - }; - - SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf; - SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf; - drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs), - sizeof(RectVertex)); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); - if (!geo.succeeded()) { - SkDebugf("Failed to get space for vertices!\n"); - return; - } - - RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices()); - - GrGeometryProcessor* gp = GrRectEffect::Create(); - drawState->setGeometryProcessor(gp)->unref(); - - for (int i = 0; i < 4; ++i) { - verts[i].fCenter = center; - verts[i].fDir = dir; - verts[i].fWidthHeight.fX = newWidth; - verts[i].fWidthHeight.fY = newHeight; - } - - SkRect devRect; - combinedMatrix.mapRect(&devRect, rect); - - SkRect devBounds = { - devRect.fLeft - SK_ScalarHalf, - devRect.fTop - SK_ScalarHalf, - devRect.fRight + SK_ScalarHalf, - devRect.fBottom + SK_ScalarHalf - }; - - verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); - verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); - verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); - verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); - - target->setIndexSourceToBuffer(fGpu->getContext()->getQuadIndexBuffer()); - target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); - target->resetIndexSource(); -} - -void GrAARectRenderer::shaderFillAlignedAARect(GrDrawTarget* target, - const SkRect& rect, - const SkMatrix& combinedMatrix) { - GrDrawState* drawState = target->drawState(); - SkASSERT(combinedMatrix.rectStaysRect()); - - drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs), - sizeof(AARectVertex)); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); - if (!geo.succeeded()) { - SkDebugf("Failed to get space for vertices!\n"); - return; - } - - AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices()); - - GrGeometryProcessor* gp = GrAlignedRectEffect::Create(); - drawState->setGeometryProcessor(gp)->unref(); - - SkRect devRect; - combinedMatrix.mapRect(&devRect, rect); - - SkRect devBounds = { - devRect.fLeft - SK_ScalarHalf, - devRect.fTop - SK_ScalarHalf, - devRect.fRight + SK_ScalarHalf, - devRect.fBottom + SK_ScalarHalf - }; - - SkPoint widthHeight = { - SkScalarHalf(devRect.width()) + SK_ScalarHalf, - SkScalarHalf(devRect.height()) + SK_ScalarHalf - }; - - verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); - verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY); - verts[0].fWidthHeight = widthHeight; - - verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); - verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY); - verts[1].fWidthHeight = widthHeight; - - verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); - verts[2].fOffset = widthHeight; - verts[2].fWidthHeight = widthHeight; - - verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); - verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY); - verts[3].fWidthHeight = widthHeight; - - target->setIndexSourceToBuffer(fGpu->getContext()->getQuadIndexBuffer()); - target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); - target->resetIndexSource(); -} - void GrAARectRenderer::strokeAARect(GrDrawTarget* target, const SkRect& rect, const SkMatrix& combinedMatrix, diff --git a/src/gpu/GrAARectRenderer.h b/src/gpu/GrAARectRenderer.h index c6e3976b7f..e39b87a5fd 100644 --- a/src/gpu/GrAARectRenderer.h +++ b/src/gpu/GrAARectRenderer.h @@ -44,17 +44,7 @@ public: const SkRect& rect, const SkMatrix& combinedMatrix, const SkRect& devRect) { -#ifdef SHADER_AA_FILL_RECT - if (combinedMatrix.rectStaysRect()) { - this->shaderFillAlignedAARect(gpu, target, - rect, combinedMatrix); - } else { - this->shaderFillAARect(gpu, target, - rect, combinedMatrix); - } -#else this->geometryFillAARect(target, rect, combinedMatrix, devRect); -#endif } void strokeAARect(GrDrawTarget* target, @@ -76,14 +66,6 @@ private: const SkMatrix& combinedMatrix, const SkRect& devRect); - void shaderFillAARect(GrDrawTarget* target, - const SkRect& rect, - const SkMatrix& combinedMatrix); - - void shaderFillAlignedAARect(GrDrawTarget* target, - const SkRect& rect, - const SkMatrix& combinedMatrix); - void geometryStrokeAARect(GrDrawTarget* target, const SkRect& devOutside, const SkRect& devOutsideAssist, diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp new file mode 100644 index 0000000000..8e93f379b6 --- /dev/null +++ b/src/gpu/GrDefaultGeoProcFactory.cpp @@ -0,0 +1,182 @@ +/* + * 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 "GrDefaultGeoProcFactory.h" + +#include "gl/builders/GrGLProgramBuilder.h" +#include "gl/GrGLGeometryProcessor.h" +#include "GrDrawState.h" +#include "GrTBackendProcessorFactory.h" + +/* + * The default Geometry Processor simply takes position and multiplies it by the uniform view + * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or + * local coords. + */ +class DefaultGeoProc : public GrGeometryProcessor { +public: + static GrGeometryProcessor* Create() { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProc, DefaultGeoProc, ()); + return SkRef(gDefaultGeoProc); + } + + static const char* Name() { return "DefaultGeometryProcessor"; } + + virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { + return GrTBackendGeometryProcessorFactory<DefaultGeoProc>::getInstance(); + } + + class GLProcessor : public GrGLGeometryProcessor { + public: + GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) + : INHERITED (factory) {} + + virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { + GrGLVertexBuilder* vs = args.fPB->getVertexShaderBuilder(); + + // setup position varying + vs->codeAppendf("%s = %s * vec3(%s, 1);", vs->glPosition(), vs->uViewM(), + vs->inPosition()); + + // output coverage in FS(pass through) + GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder(); + fs->codeAppendf("%s = %s;", args.fOutput, GrGLSLExpr4(args.fInput).c_str()); + } + + static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} + + virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {} + + private: + typedef GrGLGeometryProcessor INHERITED; + }; + +private: + DefaultGeoProc() {} + + virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { + return true; + } + + virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { + inout->mulByUnknownAlpha(); + } + + GR_DECLARE_GEOMETRY_PROCESSOR_TEST; + + typedef GrFragmentProcessor INHERITED; +}; + +GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc); + +GrGeometryProcessor* DefaultGeoProc::TestCreate(SkRandom* random, + GrContext*, + const GrDrawTargetCaps& caps, + GrTexture*[]) { + return DefaultGeoProc::Create(); +} + +// We use these arrays to customize our default GP. We only need 4 because we omit coverage if +// coverage is not requested in the flags to the create function. +GrVertexAttrib kDefaultPositionGeoProc[] = { + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding }, +}; + +GrVertexAttrib kDefaultPosColorGeoProc[] = { + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding }, +}; + +GrVertexAttrib kDefaultPosUVGeoProc[] = { + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, + { kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, 2 * sizeof(SkPoint), kCoverage_GrVertexAttribBinding }, +}; + +GrVertexAttrib kDefaultPosColUVGeoProc[] = { + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding }, + { kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kLocalCoord_GrVertexAttribBinding }, + { kVec4ub_GrVertexAttribType, 2 * sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding }, +}; + +static size_t get_size(GrDefaultGeoProcFactory::GPType flag) { + switch (flag) { + case GrDefaultGeoProcFactory::kPosition_GPType: + return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); + case GrDefaultGeoProcFactory::kColor_GPType: + return GrVertexAttribTypeSize(kVec4ub_GrVertexAttribType); + case GrDefaultGeoProcFactory::kLocalCoord_GPType: + return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); + case GrDefaultGeoProcFactory::kCoverage_GPType: + return GrVertexAttribTypeSize(kVec4ub_GrVertexAttribType); + default: + SkFAIL("Should never get here"); + return 0; + } +} + +const GrGeometryProcessor* +GrDefaultGeoProcFactory::CreateAndSetAttribs(GrDrawState* ds, uint32_t gpTypeFlags) { + SkASSERT(ds); + // always atleast position in the GP + size_t size = get_size(kPosition_GPType); + int count = 1; + + bool hasColor = SkToBool(gpTypeFlags & kColor_GPType); + bool hasLocalCoord = SkToBool(gpTypeFlags & kLocalCoord_GPType); + bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPType); + + if (hasColor) { + size += get_size(kColor_GPType); + count++; + if (hasLocalCoord) { + size += get_size(kLocalCoord_GPType); + count++; + if (hasCoverage) { + size += get_size(kCoverage_GPType); + count++; + ds->setVertexAttribs<kDefaultPosColUVGeoProc>(count, size); + } else { + ds->setVertexAttribs<kDefaultPosColUVGeoProc>(count, size); + + } + } else { + if (hasCoverage) { + size += get_size(kCoverage_GPType); + count++; + ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size); + } else { + ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size); + } + } + } else if (hasLocalCoord) { + size += get_size(kLocalCoord_GPType); + count++; + if (hasCoverage) { + size += get_size(kCoverage_GPType); + count++; + ds->setVertexAttribs<kDefaultPosUVGeoProc>(count, size); + } else { + ds->setVertexAttribs<kDefaultPosUVGeoProc>(count, size); + } + } else if (hasCoverage) { + size += get_size(kCoverage_GPType); + count++; + ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size); + } else { + // Just position + ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size); + } + return DefaultGeoProc::Create(); +} + +const GrGeometryProcessor* GrDefaultGeoProcFactory::Create() { + return DefaultGeoProc::Create(); +} diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h new file mode 100644 index 0000000000..26ce66249a --- /dev/null +++ b/src/gpu/GrDefaultGeoProcFactory.h @@ -0,0 +1,83 @@ +/* + * 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 GrDefaultGeoProcFactory_DEFINED +#define GrDefaultGeoProcFactory_DEFINED + +#include "GrGeometryProcessor.h" + +class GrDrawState; + +/* + * A factory for creating default Geometry Processors which simply multiply position by the uniform + * view matrix and wire through color, coverage, UV coords if requested. Right now this is only + * used in the creation of optimized draw states because adding default GPs to the drawstate can + * interfere with batching due to updating the drawstate. + * TODO When we track geometry state separately from the draw state, we should be able use a default + * GP with every draw call + */ +class GrDefaultGeoProcFactory { +public: + // Structs for adding vertex attributes + struct PositionAttr { + SkPoint fPosition; + }; + + struct PositionCoverageAttr { + SkPoint fPosition; + GrColor fCoverage; + }; + + struct PositionColorAttr { + SkPoint fPosition; + SkColor fColor; + }; + + struct PositionColorCoverageAttr { + SkPoint fPosition; + SkColor fColor; + GrColor fCoverage; + }; + + struct PositionLocalCoordAttr { + SkPoint fPosition; + SkPoint fLocalCoord; + }; + + struct PositionLocalCoordCoverageAttr { + SkPoint fPosition; + SkPoint fLocalCoord; + GrColor fCoverage; + }; + + struct PositionColorLocalCoordAttr { + SkPoint fPosition; + GrColor fColor; + SkPoint fLocalCoord; + }; + + struct PositionColorLocalCoordCoverage { + SkPoint fPosition; + GrColor fColor; + SkPoint fLocalCoord; + GrColor fCoverage; + }; + + enum GPType { + kPosition_GPType = 0x0, // we ALWAYS have position + kColor_GPType = 0x01, + kLocalCoord_GPType = 0x02, + kCoverage_GPType= 0x04, + kLastGPType = kCoverage_GPType + }; + + // YOU MUST UNREF + static const GrGeometryProcessor* CreateAndSetAttribs(GrDrawState*, uint32_t GPTypeFlags); + static const GrGeometryProcessor* Create(); +}; + +#endif diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index 529e9ed75e..a9d8ec4888 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -7,9 +7,10 @@ #include "GrOptDrawState.h" +#include "GrDefaultGeoProcFactory.h" #include "GrDrawState.h" #include "GrDrawTargetCaps.h" -#include "gl/GrGpuGL.h" +#include "GrGpu.h" GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags, @@ -63,6 +64,10 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, // Copy GeometryProcesssor from DS or ODS if (drawState.hasGeometryProcessor()) { fGeometryProcessor.initAndRef(drawState.fGeometryProcessor); + } else if (!GrGpu::IsPathRenderingDrawType(drawType)) { + // Install default GP, this will be ignored if we are rendering with fragment shader only + // TODO(joshualitt) rendering code should do this + fGeometryProcessor.reset(GrDefaultGeoProcFactory::Create()); } else { fGeometryProcessor.reset(NULL); } diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 4575287d05..c06909d5e1 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -100,6 +100,10 @@ public: GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();; vsBuilder->codeAppendf("%s = %s;", v.vsOut(), circleEffect.inCircleEdge().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);", v.fsIn()); @@ -219,6 +223,10 @@ public: vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), ellipseEffect.inEllipseRadii().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + // for outer curve GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(), @@ -365,6 +373,10 @@ public: vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), ellipseEffect.inEllipseOffsets1().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); SkAssertResult(fsBuilder->enableFeature( GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index 79798b6b82..3de1dcf891 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -38,7 +38,7 @@ GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() { * manually adjusted. */ static const int kFPFactoryCount = 37; -static const int kGPFactoryCount = 15; +static const int kGPFactoryCount = 14; template<> void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() { diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index 196168c06a..26049b398b 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -44,6 +44,10 @@ void GrGLConicEffect::emitCode(const EmitArgs& args) { GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inConicCoeffs.c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), + vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppend("float edgeAlpha;"); @@ -184,6 +188,10 @@ void GrGLQuadEffect::emitCode(const EmitArgs& args) { const GrShaderVar& inHairQuadEdge = args.fGP.cast<GrQuadEffect>().inHairQuadEdge(); vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inHairQuadEdge.c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), + vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("float edgeAlpha;"); @@ -310,6 +318,10 @@ void GrGLCubicEffect::emitCode(const EmitArgs& args) { const GrShaderVar& inCubicCoeffs = args.fGP.cast<GrCubicEffect>().inCubicCoeffs(); vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inCubicCoeffs.c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), + vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, GrGLShaderVar::kHigh_Precision); diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp index afa0754603..77e799414a 100644 --- a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp +++ b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp @@ -31,6 +31,10 @@ public: const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords(); vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inTextureCoords.c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("%s = ", args.fOutput); fsBuilder->appendTextureLookupAndModulate(args.fInput, diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp index f2e4438158..65ba84858d 100644 --- a/src/gpu/effects/GrDashingEffect.cpp +++ b/src/gpu/effects/GrDashingEffect.cpp @@ -520,6 +520,10 @@ void GLDashingCircleEffect::emitCode(const EmitArgs& args) { GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dce.inCoord().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), + vsBuilder->inPosition()); + // transforms all points so that we can compare them to our test circle GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n", @@ -723,6 +727,10 @@ void GLDashingLineEffect::emitCode(const EmitArgs& args) { GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), de.inCoord().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), + vsBuilder->inPosition()); + // transforms all points so that we can compare them to our test rect GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n", diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index b9776986b5..0c7a9a3d8c 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -45,6 +45,10 @@ public: GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + const char* textureSizeUniName = NULL; fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "TextureSize", @@ -256,6 +260,10 @@ public: GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + const char* textureSizeUniName = NULL; fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, "TextureSize", @@ -410,6 +418,10 @@ public: GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), vsBuilder->inPosition()); + const char* textureSizeUniName = NULL; // width, height, 1/(3*width) fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h index b031a40a61..99671c130e 100644 --- a/src/gpu/gl/GrGLSL.h +++ b/src/gpu/gl/GrGLSL.h @@ -106,6 +106,10 @@ public: return fExpr.c_str(); } + bool isValid() const { + return kFullExpr_ExprType != fType || !fExpr.isEmpty(); + } + protected: /** Constructs an invalid expression. * Useful only as a return value from functions that never actually return @@ -166,10 +170,6 @@ protected: fExpr.appendf(format, in0, in1); } - bool isValid() const { - return kFullExpr_ExprType != fType || !fExpr.isEmpty(); - } - /** Returns expression casted to another type. * Generic implementation that is called for non-trivial cases of casts. */ template <typename T> diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 8fc6020121..de4a1d5e6e 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -57,9 +57,11 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, bool hasVertexShader = !(header.fUseNvpr && gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode); + if (hasVertexShader) { - pb->fVS.setupLocalCoords(); - pb->fVS.transformGLToSkiaCoords(); + pb->fVS.setupUniformViewMatrix(); + pb->fVS.setupPositionAndLocalCoords(); + if (header.fEmitsPointSize) { pb->fVS.codeAppend("gl_PointSize = 1.0;"); } @@ -75,10 +77,10 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, // remove this cast to a vec4. GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); - pb->emitAndInstallProcs(optState, &inputColor, &inputCoverageVec4); + pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4); if (hasVertexShader) { - pb->fVS.transformSkiaToGLCoords(); + pb->fVS.transformToNormalizedDeviceSpace(); } // write the secondary color output if necessary @@ -171,7 +173,17 @@ GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32 UniformInfo& uni = fUniforms.push_back(); uni.fVariable.setType(type); uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - this->nameVariable(uni.fVariable.accessName(), 'u', name); + // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use + // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB + // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then + // the names will mismatch. I think the correct solution is to have all GPs which need the + // uniform view matrix, they should upload the view matrix in their setData along with regular + // uniforms. + char prefix = 'u'; + if ('u' == name[0]) { + prefix = '\0'; + } + this->nameVariable(uni.fVariable.accessName(), prefix, name); uni.fVariable.setArrayCount(count); uni.fVisibility = visibility; @@ -230,23 +242,40 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input } } -void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, - GrGLSLExpr4* inputColor, +void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { + // We need to collect all of the transforms to thread them through the GP in the case of GPs + // which use additional shader stages between the VS and the FS. To do this we emit a dummy + // input coverage + GrGLSLExpr4 coverageInput = *inputCoverage; + if (fOptState.hasGeometryProcessor()) { + AutoStageAdvance adv(this); + SkString outColorName; + this->nameVariable(&outColorName, '\0', "gpOutput"); + coverageInput = outColorName; + } + GrGLSLExpr4 gpOutput = coverageInput; + + // Emit fragment processors fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); - int numProcs = optState.numFragmentStages(); - this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor); - if (optState.hasGeometryProcessor()) { - const GrGeometryProcessor& gp = *optState.getGeometryProcessor(); + int numProcs = fOptState.numFragmentStages(); + this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); + this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, &coverageInput); + + // We have to save the existing code stack, and then append it to the fragment shader code + // after emiting the GP + if (fOptState.hasGeometryProcessor()) { + SkString existingCode(fFS.fCode); + fFS.fCode.reset(); + const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); fVS.emitAttributes(gp); ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType, GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset); - GrGLSLExpr4 output; - this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output); - *inputCoverage = output; + this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &gpOutput); + fFS.fCode.append(existingCode); } - this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage); + *inputCoverage = coverageInput; } void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) { @@ -272,9 +301,14 @@ void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, // Program builders have a bit of state we need to clear with each effect AutoStageAdvance adv(this); - // create var to hold stage result + // create var to hold stage result. If we already have a valid output name, just use that + // otherwise create a new mangled one. SkString outColorName; - this->nameVariable(&outColorName, '\0', "output"); + if (output->isValid()) { + outColorName = output->c_str(); + } else { + this->nameVariable(&outColorName, '\0', "output"); + } fFS.codeAppendf("vec4 %s;", outColorName.c_str()); *output = outColorName; @@ -315,8 +349,8 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs, void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, const GrProcessorKey& key, - const char* outColor, - const char* inColor) { + const char* outCoverage, + const char* inCoverage) { SkASSERT(!fGeometryProcessor); fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); @@ -325,7 +359,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); this->emitSamplers(gp, &samplers, fGeometryProcessor); - GrGLGeometryProcessor::EmitArgs args(this, gp, key, outColor, inColor, samplers); + GrGLGeometryProcessor::EmitArgs args(this, gp, key, outCoverage, inCoverage, samplers); fGeometryProcessor->fGLProc->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect @@ -374,23 +408,13 @@ void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage, suffixedVaryingName.appendf("_%i", t); varyingName = suffixedVaryingName.c_str(); } + const char* coords = kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ? + fVS.positionAttribute().c_str() : + fVS.localCoordsAttribute().c_str(); GrGLVertToFrag v(varyingType); - this->addVarying(varyingName, &v); + this->addCoordVarying(varyingName, &v, uniName, coords); - 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;", - v.vsOut(), uniName, coords.c_str()); - } else { - fVS.codeAppendf("%s = %s * vec3(%s, 1);", - v.vsOut(), uniName, coords.c_str()); - } SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (SkString(v.fsIn()), varyingType)); } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 4bcf50be6a..a44fa91090 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -241,8 +241,7 @@ protected: // generating stage code. void nameVariable(SkString* out, char prefix, const char* name); void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage); - void emitAndInstallProcs(const GrOptDrawState& optState, - GrGLSLExpr4* inputColor, + void emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage); void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut); template <class Proc> @@ -259,8 +258,8 @@ protected: const char* inColor); void emitAndInstallProc(const GrGeometryProcessor&, const GrProcessorKey&, - const char* outColor, - const char* inColor); + const char* outCoverage, + const char* inCoverage); void verify(const GrGeometryProcessor&); void verify(const GrFragmentProcessor&); void emitSamplers(const GrProcessor&, @@ -314,6 +313,22 @@ protected: void enterStage() { fOutOfStage = false; } int stageIndex() const { return fStageIndex; } + struct TransformVarying { + TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords) + : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {} + GrGLVarying fV; + SkString fUniName; + SkString fSourceCoords; + }; + + void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName, + const char* sourceCoords) { + this->addVarying(name, v); + fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords)); + } + + const char* rtAdjustment() const { return "rtAdjustment"; } + // number of each input/output type in a single allocation block, used by many builders static const int kVarsPerBlock; @@ -331,6 +346,7 @@ protected: const GrProgramDesc& fDesc; GrGpuGL* fGpu; UniformInfoArray fUniforms; + SkSTArray<16, TransformVarying, true> fCoordVaryings; friend class GrGLShaderBuilder; friend class GrGLVertexBuilder; diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index 2bef113410..7af5ce9843 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -20,6 +20,7 @@ GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program) : INHERITED(program) , fPositionVar(NULL) , fLocalCoordsVar(NULL) + , fRtAdjustName(NULL) , fEffectAttribOffset(0) { } @@ -31,9 +32,22 @@ void GrGLVertexBuilder::addVarying(const char* name, GrGLVarying* v) { v->fVsOut = fOutputs.back().getName().c_str(); } -void GrGLVertexBuilder::setupLocalCoords() { +void GrGLVertexBuilder::setupUniformViewMatrix() { + fProgramBuilder->fUniformHandles.fViewMatrixUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility, + kMat33f_GrSLType, + this->uViewM()); +} + +void GrGLVertexBuilder::setupPositionAndLocalCoords() { + // Setup position + this->codeAppendf("vec3 %s;", this->glPosition()); + + // setup position and local coords attribute fPositionVar = &fInputs.push_back(); - fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition"); + fPositionVar->set(kVec2f_GrSLType, + GrGLShaderVar::kAttribute_TypeModifier, + this->inPosition()); if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) { fLocalCoordsVar = &fInputs.push_back(); fLocalCoordsVar->set(kVec2f_GrSLType, @@ -45,18 +59,6 @@ void GrGLVertexBuilder::setupLocalCoords() { fEffectAttribOffset = fInputs.count(); } -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, GrGLSLExpr1* out) { GrGLVertToFrag v(kFloat_GrSLType); fProgramBuilder->addVarying(inName, &v); @@ -91,17 +93,34 @@ void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) { } } -void GrGLVertexBuilder::transformSkiaToGLCoords() { - const char* rtAdjustName; +void GrGLVertexBuilder::transformToNormalizedDeviceSpace() { + // setup RT Uniform fProgramBuilder->fUniformHandles.fRTAdjustmentUni = fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility, kVec4f_GrSLType, - "rtAdjustment", - &rtAdjustName); + fProgramBuilder->rtAdjustment(), + &fRtAdjustName); + // Wire transforms + SkTArray<GrGLProgramBuilder::TransformVarying, true>& transVs = fProgramBuilder->fCoordVaryings; + int transformCount = transVs.count(); + for (int i = 0; i < transformCount; i++) { + const char* coords = transVs[i].fSourceCoords.c_str(); + + // varying = matrix * coords (logically) + const GrGLVarying& v = transVs[i].fV; + if (kVec2f_GrSLType == v.fType) { + this->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.fVsOut, transVs[i].fUniName.c_str(), + coords); + } else { + this->codeAppendf("%s = %s * vec3(%s, 1);", v.fVsOut, transVs[i].fUniName.c_str(), + coords); + } + } // 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); + this->codeAppendf("gl_Position = vec4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);", + this->glPosition(), fRtAdjustName, this->glPosition(), fRtAdjustName, + this->glPosition()); } void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) { diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h index 2f14bd7702..7d6d95e508 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h @@ -31,6 +31,15 @@ public: */ const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } + /** returns the expected position output */ + const char* glPosition() const { return "pos3"; } + + /** returns the expected uviewM matrix */ + // TODO all of this fixed function stuff can live on the GP/PP + const char* uViewM() const { return "uViewM"; } + const char* inPosition() const { return "inPosition"; } + + private: /* * Internal call for GrGLProgramBuilder.addVarying @@ -40,12 +49,13 @@ private: /* * private helpers for compilation by GrGLProgramBuilder */ - void setupLocalCoords(); - void transformGLToSkiaCoords(); + void transformToNormalizedDeviceSpace(); + //TODO GP itself should setup the uniform view matrix + void setupUniformViewMatrix(); + void setupPositionAndLocalCoords(); void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr1* out); void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out); void emitAttributes(const GrGeometryProcessor& gp); - void transformSkiaToGLCoords(); void bindVertexAttributes(GrGLuint programID); bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; @@ -61,6 +71,7 @@ private: GrGLShaderVar* fPositionVar; GrGLShaderVar* fLocalCoordsVar; + const char* fRtAdjustName; int fEffectAttribOffset; friend class GrGLProgramBuilder; |