Chromium Code Reviews| Index: src/gpu/GrAARectRenderer.cpp |
| =================================================================== |
| --- src/gpu/GrAARectRenderer.cpp (revision 8912) |
| +++ src/gpu/GrAARectRenderer.cpp (working copy) |
| @@ -13,6 +13,108 @@ |
| SK_DEFINE_INST_COUNT(GrAARectRenderer) |
| +/////////////////////////////////////////////////////////////////////////////// |
| +class GrGLAARectEffect; |
|
bsalomon
2013/04/29 19:44:50
AlignedRectEffect? It seems like we've reserved AA
robertphillips
2013/05/02 13:56:39
Done.
|
| + |
| +// Axis Aligned special case |
| +class GrAARectEffect : public GrEffect { |
| +public: |
| + static GrEffectRef* Create() { |
| + GR_CREATE_STATIC_EFFECT(gAARectEffect, GrAARectEffect, ()); |
| + gAARectEffect->ref(); |
| + return gAARectEffect; |
| + } |
| + |
| + virtual ~GrAARectEffect() {} |
| + |
| + static const char* Name() { return "AARectEdge"; } |
| + |
| + virtual void getConstantColorComponents(GrColor* color, |
| + uint32_t* validFlags) const SK_OVERRIDE { |
| + *validFlags = 0; |
| + } |
| + |
| + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
| + return GrTBackendEffectFactory<GrAARectEffect>::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: |
| + GrAARectEffect() : 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(GrAARectEffect); |
| + |
| +GrEffectRef* GrAARectEffect::TestCreate(SkMWCRandom* random, |
| + GrContext* context, |
| + const GrDrawTargetCaps&, |
| + GrTexture* textures[]) { |
| + return GrAARectEffect::Create(); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| class GrGLRectEffect; |
| /** |
| @@ -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] } |
| }; |
|
jvanverth1
2013/04/29 20:02:42
Is this different from 0.5*devRect.width() + 0.5?
robertphillips
2013/05/02 13:56:39
newWidth and newHeight are relative to 'dir' so th
|
| - 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,68 @@ |
| target->resetIndexSource(); |
| } |
| +void GrAARectRenderer::shaderFillAAAARect(GrGpu* gpu, |
| + GrDrawTarget* target, |
| + 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 = GrAARectEffect::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, |