aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp4
-rw-r--r--src/gpu/GrAARectRenderer.cpp394
-rw-r--r--src/gpu/GrAARectRenderer.h18
-rw-r--r--src/gpu/GrDefaultGeoProcFactory.cpp182
-rw-r--r--src/gpu/GrDefaultGeoProcFactory.h83
-rw-r--r--src/gpu/GrOptDrawState.cpp7
-rw-r--r--src/gpu/GrOvalRenderer.cpp12
-rw-r--r--src/gpu/GrProcessor.cpp2
-rw-r--r--src/gpu/effects/GrBezierEffect.cpp12
-rw-r--r--src/gpu/effects/GrCustomCoordsTextureEffect.cpp4
-rw-r--r--src/gpu/effects/GrDashingEffect.cpp8
-rwxr-xr-xsrc/gpu/effects/GrDistanceFieldTextureEffect.cpp12
-rw-r--r--src/gpu/gl/GrGLSL.h8
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp92
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h24
-rw-r--r--src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp59
-rw-r--r--src/gpu/gl/builders/GrGLVertexShaderBuilder.h17
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(&center, 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;