From d85f32ca40475fb246dd8ca93abaf1c3db0389e1 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Fri, 28 Feb 2014 14:43:26 +0000 Subject: Make GrConvexPolyEffect support inverse fills and non-AA rects BUG=skia:2151 R=robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/183833003 git-svn-id: http://skia.googlecode.com/svn/trunk@13621 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/convexpolyeffect.cpp | 68 ++++++++++++++++--------------- src/gpu/GrClipMaskManager.cpp | 2 +- src/gpu/effects/GrConvexPolyEffect.cpp | 73 +++++++++++++++++++++++++--------- src/gpu/effects/GrConvexPolyEffect.h | 8 ++-- 4 files changed, 94 insertions(+), 57 deletions(-) diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp index 2632bd4186..9142ca9cbd 100644 --- a/gm/convexpolyeffect.cpp +++ b/gm/convexpolyeffect.cpp @@ -44,7 +44,7 @@ protected: } virtual SkISize onISize() SK_OVERRIDE { - return make_isize(475, 800); + return make_isize(720, 800); } virtual uint32_t onGetFlags() const SK_OVERRIDE { @@ -100,7 +100,6 @@ protected: fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f)); // inverted in x and y fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f)); - } virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { @@ -174,55 +173,58 @@ protected: y += SkScalarCeilToScalar(path->getBounds().height() + 20.f); } - // Draw rects. We only have specialized effect code for the AA case, so don't do non-AA. for (SkTLList::Iter iter(fRects, SkTLList::Iter::kHead_IterStart); NULL != iter.get(); iter.next()) { SkScalar x = 0; - GrTestTarget tt; - context->getTestTarget(&tt); - if (NULL == tt.target()) { - SkDEBUGFAIL("Couldn't get Gr test target."); - return; - } - - SkRect rect = *iter.get(); - rect.offset(x, y); - SkAutoTUnref effect(GrConvexPolyEffect::CreateForAAFillRect(rect)); - if (!effect) { - SkDEBUGFAIL("Couldn't create convex poly effect."); - return; - } + for (int et = 0; et < GrConvexPolyEffect::kEdgeTypeCnt; ++et) { + GrTestTarget tt; + context->getTestTarget(&tt); + if (NULL == tt.target()) { + SkDEBUGFAIL("Couldn't get Gr test target."); + return; + } + SkRect rect = *iter.get(); + rect.offset(x, y); + GrConvexPolyEffect::EdgeType edgeType = (GrConvexPolyEffect::EdgeType) et; + SkAutoTUnref effect(GrConvexPolyEffect::Create(edgeType, rect)); + if (!effect) { + SkDEBUGFAIL("Couldn't create convex poly effect."); + return; + } - GrDrawState* drawState = tt.target()->drawState(); - drawState->setVertexAttribs(SK_ARRAY_COUNT(kAttribs)); - drawState->addCoverageEffect(effect, 1); - drawState->setIdentityViewMatrix(); - drawState->setRenderTarget(rt); - drawState->setColor(0xff000000); + GrDrawState* drawState = tt.target()->drawState(); + drawState->setVertexAttribs(SK_ARRAY_COUNT(kAttribs)); + drawState->addCoverageEffect(effect, 1); + drawState->setIdentityViewMatrix(); + drawState->setRenderTarget(rt); + drawState->setColor(0xff000000); - SkPoint verts[4]; - SkRect bounds = rect; - bounds.outset(5.f, 5.f); - bounds.toQuad(verts); + SkPoint verts[4]; + SkRect bounds = rect; + bounds.outset(5.f, 5.f); + bounds.toQuad(verts); - tt.target()->setVertexSourceToArray(verts, 4); - tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); - tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6); + tt.target()->setVertexSourceToArray(verts, 4); + tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); + tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6); - x += SkScalarCeilToScalar(rect.width() + 10.f); + x += SkScalarCeilToScalar(rect.width() + 10.f); + } - // Draw AA rect using normal API for reference + // Draw rect without and with AA using normal API for reference canvas->save(); canvas->translate(x, y); SkPaint paint; + canvas->drawRect(*iter.get(), paint); + x += SkScalarCeilToScalar(iter.get()->width() + 10.f); paint.setAntiAlias(true); canvas->drawRect(*iter.get(), paint); canvas->restore(); - y += SkScalarCeilToScalar(rect.height() + 20.f); + y += SkScalarCeilToScalar(iter.get()->height() + 20.f); } } diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index b637bd6c7a..90106fa7e0 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -200,7 +200,7 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), SkIntToScalar(-clipDataIn->fOrigin.fY) }; rect.offset(offset); - effect.reset(GrConvexPolyEffect::CreateForAAFillRect(rect)); + effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::kFillAA_EdgeType, rect)); // This should never fail. SkASSERT(effect); } diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index bbfa3bb82c..baad92837c 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -19,13 +19,14 @@ class GLAARectEffect; class AARectEffect : public GrEffect { public: typedef GLAARectEffect GLEffect; + typedef GrConvexPolyEffect::EdgeType EdgeType; const SkRect& getRect() const { return fRect; } static const char* Name() { return "AARect"; } - static GrEffectRef* Create(const SkRect& rect) { - return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(AARectEffect, (rect)))); + static GrEffectRef* Create(EdgeType edgeType, const SkRect& rect) { + return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(AARectEffect, (edgeType, rect)))); } virtual void getConstantColorComponents(GrColor* color, @@ -39,10 +40,12 @@ public: } } + GrConvexPolyEffect::EdgeType getEdgeType() const { return fEdgeType; } + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; private: - AARectEffect(const SkRect& rect) : fRect(rect) { + AARectEffect(EdgeType edgeType, const SkRect& rect) : fRect(rect), fEdgeType(edgeType) { this->setWillReadFragmentPosition(); } @@ -52,6 +55,8 @@ private: } SkRect fRect; + EdgeType fEdgeType; + typedef GrEffect INHERITED; GR_DECLARE_EFFECT_TEST; @@ -64,11 +69,14 @@ GrEffectRef* AARectEffect::TestCreate(SkRandom* random, GrContext*, const GrDrawTargetCaps& caps, GrTexture*[]) { + EdgeType edgeType = static_cast( + random->nextULessThan(GrConvexPolyEffect::kEdgeTypeCnt)); + SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(), random->nextSScalar1(), random->nextSScalar1(), random->nextSScalar1()); - return AARectEffect::Create(rect); + return AARectEffect::Create(edgeType, rect); } ////////////////////////////////////////////////////////////////////////////// @@ -85,7 +93,7 @@ public: const TransformedCoordsArray&, const TextureSamplerArray&) SK_OVERRIDE; - static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; } + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; @@ -108,23 +116,39 @@ void GLAARectEffect::emitCode(GrGLShaderBuilder* builder, const char* inputColor, const TransformedCoordsArray&, const TextureSamplerArray& samplers) { + const AARectEffect& aare = drawEffect.castEffect(); const char *rectName; + // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), + // respectively. fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "rect", &rectName); const char* fragmentPos = builder->fragmentPosition(); - // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), - // respectively. The amount of coverage removed in x and y by the edges is computed as a pair of - // negative numbers, xSub and ySub. - builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); - builder->fsCodeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); - builder->fsCodeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); - // Now compute coverage in x and y and multiply them to get the fraction of the pixel covered. - builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); + if (GrConvexPolyEffect::kFillAA_EdgeType == aare.getEdgeType() || + GrConvexPolyEffect::kInverseFillAA_EdgeType == aare.getEdgeType()) { + // The amount of coverage removed in x and y by the edges is computed as a pair of negative + // numbers, xSub and ySub. + builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); + builder->fsCodeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); + builder->fsCodeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); + builder->fsCodeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); + builder->fsCodeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); + // Now compute coverage in x and y and multiply them to get the fraction of the pixel + // covered. + builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); + } else { + builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n"); + builder->fsCodeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); + builder->fsCodeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > 0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); + builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > 0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); + } + if (GrConvexPolyEffect::kInverseFillAA_EdgeType == aare.getEdgeType() || + GrConvexPolyEffect::kInverseFillNoAA_EdgeType == aare.getEdgeType()) { + builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); + } builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } @@ -139,6 +163,11 @@ void GLAARectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& } } +GrGLEffect::EffectKey GLAARectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { + const AARectEffect& aare = drawEffect.castEffect(); + return aare.getEdgeType(); +} + const GrBackendEffectFactory& AARectEffect::getFactory() const { return GrTBackendEffectFactory::getInstance(); } @@ -196,20 +225,26 @@ void GrGLConvexPolyEffect::emitCode(GrGLShaderBuilder* builder, edgeArrayName, i, fragmentPos, fragmentPos); switch (cpe.getEdgeType()) { case GrConvexPolyEffect::kFillAA_EdgeType: + case GrConvexPolyEffect::kInverseFillAA_EdgeType: // inverse handled at the end builder->fsCodeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); - builder->fsCodeAppend("\t\talpha *= edge;\n"); break; case GrConvexPolyEffect::kFillNoAA_EdgeType: + case GrConvexPolyEffect::kInverseFillNoAA_EdgeType: // inverse handled at the end builder->fsCodeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n"); - builder->fsCodeAppend("\t\talpha *= edge;\n"); break; } + builder->fsCodeAppend("\t\talpha *= edge;\n"); } // Woe is me. See skbug.com/2149. if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) { builder->fsCodeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n"); } + + if (GrConvexPolyEffect::kInverseFillAA_EdgeType == cpe.getEdgeType() || + GrConvexPolyEffect::kInverseFillNoAA_EdgeType == cpe.getEdgeType() ) { + builder->fsCodeAppend("\talpha = 1.0 - alpha;\n"); + } builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); } @@ -277,8 +312,8 @@ GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path, const return Create(type, n, edges); } -GrEffectRef* GrConvexPolyEffect::CreateForAAFillRect(const SkRect& rect) { - return AARectEffect::Create(rect); +GrEffectRef* GrConvexPolyEffect::Create(EdgeType edgeType, const SkRect& rect) { + return AARectEffect::Create(edgeType, rect); } GrConvexPolyEffect::~GrConvexPolyEffect() {} diff --git a/src/gpu/effects/GrConvexPolyEffect.h b/src/gpu/effects/GrConvexPolyEffect.h index c712eb3af8..ab9d313c16 100644 --- a/src/gpu/effects/GrConvexPolyEffect.h +++ b/src/gpu/effects/GrConvexPolyEffect.h @@ -21,13 +21,13 @@ class SkPath; */ class GrConvexPolyEffect : public GrEffect { public: - /** This could be expanded to include a AA hairline mode. If so, unify with GrBezierEffect's - enum. */ enum EdgeType { kFillNoAA_EdgeType, kFillAA_EdgeType, + kInverseFillNoAA_EdgeType, + kInverseFillAA_EdgeType, - kLastEdgeType = kFillAA_EdgeType, + kLastEdgeType = kInverseFillAA_EdgeType, }; enum { @@ -64,7 +64,7 @@ public: /** * Creates an effect that fills inside the rect with AA edges.. */ - static GrEffectRef* CreateForAAFillRect(const SkRect&); + static GrEffectRef* Create(EdgeType, const SkRect&); virtual ~GrConvexPolyEffect(); -- cgit v1.2.3