Index: src/gpu/GrAARectRenderer.cpp |
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp |
index ead4ea16a37aac51d45ca9e729dca52335f56774..46196e2e4ef542d8e3d8a70d8e7fcc377b59b1f7 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, |