Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Unified Diff: src/gpu/GrAARectRenderer.cpp

Issue 691313003: Revert of Default geometry processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrAARectRenderer.h ('k') | src/gpu/GrDefaultGeoProcFactory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrAARectRenderer.cpp
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index 46196e2e4ef542d8e3d8a70d8e7fcc377b59b1f7..ead4ea16a37aac51d45ca9e729dca52335f56774 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -13,6 +13,251 @@
#include "GrTBackendProcessorFactory.h"
#include "SkColorPriv.h"
#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();
+}
///////////////////////////////////////////////////////////////////////////////
@@ -303,6 +548,155 @@
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,
« no previous file with comments | « src/gpu/GrAARectRenderer.h ('k') | src/gpu/GrDefaultGeoProcFactory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698