Index: src/gpu/GrAARectRenderer.cpp |
=================================================================== |
--- src/gpu/GrAARectRenderer.cpp (revision 8955) |
+++ src/gpu/GrAARectRenderer.cpp (working copy) |
@@ -13,6 +13,108 @@ |
SK_DEFINE_INST_COUNT(GrAARectRenderer) |
+/////////////////////////////////////////////////////////////////////////////// |
+class GrGLAlignedRectEffect; |
+ |
+// Axis Aligned special case |
+class GrAlignedRectEffect : public GrEffect { |
+public: |
+ static GrEffectRef* Create() { |
+ GR_CREATE_STATIC_EFFECT(gAlignedRectEffect, GrAlignedRectEffect, ()); |
+ gAlignedRectEffect->ref(); |
+ return gAlignedRectEffect; |
+ } |
+ |
+ virtual ~GrAlignedRectEffect() {} |
+ |
+ static const char* Name() { return "AlignedRectEdge"; } |
+ |
+ virtual void getConstantColorComponents(GrColor* color, |
+ uint32_t* validFlags) const SK_OVERRIDE { |
+ *validFlags = 0; |
+ } |
+ |
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
+ return GrTBackendEffectFactory<GrAlignedRectEffect>::getInstance(); |
+ } |
+ |
+ class GLEffect : public GrGLEffect { |
+ public: |
+ GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
+ : INHERITED (factory) {} |
+ |
+ virtual void emitCode(GrGLShaderBuilder* builder, |
+ const GrDrawEffect& drawEffect, |
+ EffectKey key, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TextureSamplerArray& samplers) SK_OVERRIDE { |
+ // setup the varying for the Axis aligned rect effect |
+ // xy -> interpolated offset |
+ // zw -> w/2+0.5, h/2+0.5 |
+ const char *vsRectName, *fsRectName; |
+ builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); |
+ const SkString* attr0Name = |
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); |
+ builder->vsCodeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); |
+ |
+ // TODO: compute these scale factors in the VS |
+ // These scale factors adjust the coverage for < 1 pixel wide/high rects |
+ builder->fsCodeAppendf("\tfloat wScale = max(1.0, 2.0/(0.5+%s.z));\n", |
+ fsRectName); |
+ builder->fsCodeAppendf("\tfloat hScale = max(1.0, 2.0/(0.5+%s.w));\n", |
+ fsRectName); |
+ |
+ // Compute the coverage for the rect's width |
+ builder->fsCodeAppendf("\tfloat coverage = clamp(wScale*(%s.z-abs(%s.x)), 0.0, 1.0);\n", |
+ fsRectName, |
+ fsRectName); |
+ |
+ // Compute the coverage for the rect's height and merge with the width |
+ builder->fsCodeAppendf( |
+ "\tcoverage = min(coverage, clamp(hScale*(%s.w-abs(%s.y)), 0.0, 1.0));\n", |
+ fsRectName, |
+ fsRectName); |
+ |
+ SkString modulate; |
+ GrGLSLModulatef<4>(&modulate, inputColor, "coverage"); |
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); |
+ } |
+ |
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { |
+ return 0; |
+ } |
+ |
+ virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {} |
+ |
+ private: |
+ typedef GrGLEffect INHERITED; |
+ }; |
+ |
+ |
+private: |
+ GrAlignedRectEffect() : GrEffect() { |
+ this->addVertexAttrib(kVec4f_GrSLType); |
+ } |
+ |
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; } |
+ |
+ GR_DECLARE_EFFECT_TEST; |
+ |
+ typedef GrEffect INHERITED; |
+}; |
+ |
+ |
+GR_DEFINE_EFFECT_TEST(GrAlignedRectEffect); |
+ |
+GrEffectRef* GrAlignedRectEffect::TestCreate(SkMWCRandom* random, |
+ GrContext* context, |
+ const GrDrawTargetCaps&, |
+ GrTexture* textures[]) { |
+ return GrAlignedRectEffect::Create(); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
class GrGLRectEffect; |
/** |
@@ -257,10 +359,10 @@ |
return fAAStrokeRectIndexBuffer; |
} |
-void GrAARectRenderer::fillAARect(GrGpu* gpu, |
- GrDrawTarget* target, |
- const GrRect& devRect, |
- bool useVertexCoverage) { |
+void GrAARectRenderer::geometryFillAARect(GrGpu* gpu, |
+ GrDrawTarget* target, |
+ const GrRect& devRect, |
+ bool useVertexCoverage) { |
GrDrawState* drawState = target->drawState(); |
set_aa_rect_vertex_attributes(drawState, useVertexCoverage); |
@@ -311,6 +413,9 @@ |
target->resetIndexSource(); |
} |
+namespace { |
+ |
+// Rotated |
struct RectVertex { |
GrPoint fPos; |
GrPoint fCenter; |
@@ -318,22 +423,33 @@ |
GrPoint fWidthHeight; |
}; |
-namespace { |
- |
+// Rotated |
extern const GrVertexAttrib gAARectVertexAttribs[] = { |
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
{ kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, |
{ kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding } |
}; |
+// Axis Aligned |
+struct AARectVertex { |
+ GrPoint fPos; |
+ GrPoint fOffset; |
+ GrPoint fWidthHeight; |
}; |
+// Axis Aligned |
+extern const GrVertexAttrib gAAAARectVertexAttribs[] = { |
+ { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
+ { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, |
+}; |
+ |
+}; |
+ |
void GrAARectRenderer::shaderFillAARect(GrGpu* gpu, |
GrDrawTarget* target, |
const GrRect& rect, |
const SkMatrix& combinedMatrix, |
- const GrRect& devRect, |
- bool useVertexCoverage) { |
+ const GrRect& devRect) { |
GrDrawState* drawState = target->drawState(); |
SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY()); |
@@ -345,15 +461,12 @@ |
// compute transformed (width, 0) and (0, height) vectors |
SkVector vec[2] = { |
- { combinedMatrix[SkMatrix::kMScaleX] * rect.width(), |
- combinedMatrix[SkMatrix::kMSkewY] * rect.width() }, |
- { combinedMatrix[SkMatrix::kMSkewX] * rect.height(), |
- combinedMatrix[SkMatrix::kMScaleY] * rect.height() } |
+ { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, |
+ { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } |
}; |
- SkScalar newWidth = vec[0].length() / 2.0f + 0.5f; |
- SkScalar newHeight = vec[1].length() / 2.0f + 0.5f; |
- |
+ 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)); |
GrAssert(sizeof(RectVertex) == drawState->getVertexSize()); |
@@ -401,6 +514,69 @@ |
target->resetIndexSource(); |
} |
+void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu, |
+ GrDrawTarget* target, |
+ const GrRect& rect, |
+ const SkMatrix& combinedMatrix, |
+ const GrRect& devRect) { |
+ GrDrawState* drawState = target->drawState(); |
+ SkASSERT(combinedMatrix.rectStaysRect()); |
+ |
+ drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs)); |
+ GrAssert(sizeof(AARectVertex) == drawState->getVertexSize()); |
+ |
+ GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); |
+ if (!geo.succeeded()) { |
+ GrPrintf("Failed to get space for vertices!\n"); |
+ return; |
+ } |
+ |
+ AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices()); |
+ |
+ enum { |
+ // the edge effects share this stage with glyph rendering |
+ // (kGlyphMaskStage in GrTextContext) && SW path rendering |
+ // (kPathMaskStage in GrSWMaskHelper) |
+ kEdgeEffectStage = GrPaint::kTotalStages, |
+ }; |
+ |
+ GrEffectRef* effect = GrAlignedRectEffect::Create(); |
+ static const int kOffsetIndex = 1; |
+ drawState->setEffect(kEdgeEffectStage, effect, kOffsetIndex)->unref(); |
+ |
+ SkRect devBounds = { |
+ devRect.fLeft - SK_ScalarHalf, |
+ devRect.fTop - SK_ScalarHalf, |
+ devRect.fRight + SK_ScalarHalf, |
+ devRect.fBottom + SK_ScalarHalf |
+ }; |
+ |
+ GrPoint 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(gpu->getContext()->getQuadIndexBuffer()); |
+ target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); |
+ target->resetIndexSource(); |
+} |
+ |
void GrAARectRenderer::strokeAARect(GrGpu* gpu, |
GrDrawTarget* target, |
const GrRect& devRect, |
@@ -423,7 +599,7 @@ |
if (spare <= 0) { |
GrRect r(devRect); |
r.inset(-rx, -ry); |
- this->fillAARect(gpu, target, r, useVertexCoverage); |
+ this->fillAARect(gpu, target, r, SkMatrix::I(), r, useVertexCoverage); |
return; |
} |