Specialize GrConvexPolyEffect for AA rects, use for AA clip rects.
BUG=skia:2051 R=robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/140093004 git-svn-id: http://skia.googlecode.com/svn/trunk@13375 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
fffc9dcf57
commit
f053980016
@ -35,6 +35,12 @@
|
||||
|
||||
# Added by bsalomon for skbug.com/2051, https://codereview.chromium.org/151523005
|
||||
filltypespersp
|
||||
# Added by bsalomon for skbug.com/2051, https://codereview.chromium.org/140093004/
|
||||
complexclip2_rect_aa
|
||||
aaclip
|
||||
simpleaaclip_rect
|
||||
convex_poly_clip
|
||||
convex_poly_effect
|
||||
|
||||
# Need to rebaseline all platforms, as the content was changed to remove
|
||||
# deprecated calling pattern.
|
||||
|
@ -44,7 +44,7 @@ protected:
|
||||
}
|
||||
|
||||
virtual SkISize onISize() SK_OVERRIDE {
|
||||
return make_isize(475, 530);
|
||||
return make_isize(475, 800);
|
||||
}
|
||||
|
||||
virtual uint32_t onGetFlags() const SK_OVERRIDE {
|
||||
@ -85,6 +85,22 @@ protected:
|
||||
scaleM.setScale(1.1f, 0.4f);
|
||||
ngon.transform(scaleM);
|
||||
fPaths.addToTail(ngon);
|
||||
|
||||
// integer edges
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
|
||||
// half-integer edges
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
|
||||
// vertically/horizontally thin rects that cover pixel centers
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
|
||||
// vertically/horizontally thin rects that don't cover pixel centers
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
|
||||
fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
|
||||
// small in x and y
|
||||
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 {
|
||||
@ -98,11 +114,11 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
const SkPath* path;
|
||||
SkScalar y = 0;
|
||||
for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
|
||||
NULL != (path = iter.get());
|
||||
NULL != iter.get();
|
||||
iter.next()) {
|
||||
const SkPath* path = iter.get();
|
||||
SkScalar x = 0;
|
||||
|
||||
for (int et = 0; et < GrConvexPolyEffect::kEdgeTypeCnt; ++et) {
|
||||
@ -142,7 +158,7 @@ protected:
|
||||
tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
|
||||
tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
|
||||
|
||||
x += path->getBounds().width() + 10.f;
|
||||
x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
|
||||
}
|
||||
|
||||
// Draw AA and non AA paths using normal API for reference.
|
||||
@ -155,18 +171,69 @@ protected:
|
||||
canvas->drawPath(*path, paint);
|
||||
canvas->restore();
|
||||
|
||||
y += path->getBounds().height() + 20.f;
|
||||
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<SkRect>::Iter iter(fRects, SkTLList<SkRect>::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<GrEffectRef> effect(GrConvexPolyEffect::CreateForAAFillRect(rect));
|
||||
if (!effect) {
|
||||
SkDEBUGFAIL("Couldn't create convex poly effect.");
|
||||
return;
|
||||
}
|
||||
|
||||
GrDrawState* drawState = tt.target()->drawState();
|
||||
drawState->setVertexAttribs<kAttribs>(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);
|
||||
|
||||
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);
|
||||
|
||||
// Draw AA rect using normal API for reference
|
||||
canvas->save();
|
||||
canvas->translate(x, y);
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
canvas->drawRect(*iter.get(), paint);
|
||||
canvas->restore();
|
||||
|
||||
y += SkScalarCeilToScalar(rect.height() + 20.f);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkTLList<SkPath> fPaths;
|
||||
|
||||
SkTLList<SkRect> fRects;
|
||||
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
DEF_GM( return SkNEW(ConvexPolyEffect); )
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -67,7 +67,7 @@ private:
|
||||
*/
|
||||
#define GR_DECLARE_EFFECT_TEST \
|
||||
static GrEffectTestFactory gTestFactory; \
|
||||
static GrEffectRef* TestCreate(SkRandom*, \
|
||||
static GrEffectRef* TestCreate(SkRandom*, \
|
||||
GrContext*, \
|
||||
const GrDrawTargetCaps&, \
|
||||
GrTexture* dummyTextures[2])
|
||||
@ -91,7 +91,7 @@ private:
|
||||
// The unit test relies on static initializers. Just declare the TestCreate function so that
|
||||
// its definitions will compile.
|
||||
#define GR_DECLARE_EFFECT_TEST \
|
||||
static GrEffectRef* TestCreate(SkRandom*, \
|
||||
static GrEffectRef* TestCreate(SkRandom*, \
|
||||
GrContext*, \
|
||||
const GrDrawTargetCaps&, \
|
||||
GrTexture* dummyTextures[2])
|
||||
|
@ -156,25 +156,37 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
|
||||
|
||||
// If there is only one clip element and it is a convex polygon we just install an effect that
|
||||
// clips against the edges.
|
||||
if (1 == elements.count() && SkClipStack::Element::kPath_Type == elements.tail()->getType() &&
|
||||
SkRegion::kReplace_Op == elements.tail()->getOp()) {
|
||||
const SkPath& path = elements.tail()->getPath();
|
||||
bool isAA = GR_AA_CLIP && elements.tail()->isAA();
|
||||
if (1 == elements.count() && SkRegion::kReplace_Op == elements.tail()->getOp()) {
|
||||
SkAutoTUnref<GrEffectRef> effect;
|
||||
if (rt->isMultisampled()) {
|
||||
// A coverage effect for AA clipping won't play nicely with MSAA.
|
||||
if (!isAA) {
|
||||
if (SkClipStack::Element::kPath_Type == elements.tail()->getType()) {
|
||||
const SkPath& path = elements.tail()->getPath();
|
||||
bool isAA = GR_AA_CLIP && elements.tail()->isAA();
|
||||
if (rt->isMultisampled()) {
|
||||
// A coverage effect for AA clipping won't play nicely with MSAA.
|
||||
if (!isAA) {
|
||||
SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
|
||||
SkIntToScalar(-clipDataIn->fOrigin.fY) };
|
||||
effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::kFillNoAA_EdgeType,
|
||||
path, &offset));
|
||||
}
|
||||
} else {
|
||||
SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
|
||||
SkIntToScalar(-clipDataIn->fOrigin.fY) };
|
||||
effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::kFillNoAA_EdgeType,
|
||||
path, &offset));
|
||||
GrConvexPolyEffect::EdgeType type = isAA ? GrConvexPolyEffect::kFillAA_EdgeType :
|
||||
GrConvexPolyEffect::kFillNoAA_EdgeType;
|
||||
effect.reset(GrConvexPolyEffect::Create(type, path, &offset));
|
||||
}
|
||||
} else {
|
||||
} else if (GR_AA_CLIP && elements.tail()->isAA() && !rt->isMultisampled()) {
|
||||
// We only handle AA/non-MSAA rects here. Coverage effect AA isn't MSAA friendly and
|
||||
// non-AA rect clips are handled by the scissor.
|
||||
SkASSERT(SkClipStack::Element::kRect_Type == elements.tail()->getType());
|
||||
SkRect rect = elements.tail()->getRect();
|
||||
SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
|
||||
SkIntToScalar(-clipDataIn->fOrigin.fY) };
|
||||
GrConvexPolyEffect::EdgeType type = isAA ? GrConvexPolyEffect::kFillAA_EdgeType :
|
||||
GrConvexPolyEffect::kFillNoAA_EdgeType;
|
||||
effect.reset(GrConvexPolyEffect::Create(type, path, &offset));
|
||||
SkIntToScalar(-clipDataIn->fOrigin.fY) };
|
||||
rect.offset(offset);
|
||||
effect.reset(GrConvexPolyEffect::CreateForAAFillRect(rect));
|
||||
// This should never fail.
|
||||
SkASSERT(effect);
|
||||
}
|
||||
if (effect) {
|
||||
are->set(fGpu->drawState());
|
||||
|
@ -14,6 +14,138 @@
|
||||
|
||||
#include "SkPath.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
class GLAARectEffect;
|
||||
|
||||
class AARectEffect : public GrEffect {
|
||||
public:
|
||||
typedef GLAARectEffect GLEffect;
|
||||
|
||||
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))));
|
||||
}
|
||||
|
||||
virtual void getConstantColorComponents(GrColor* color,
|
||||
uint32_t* validFlags) const SK_OVERRIDE {
|
||||
if (fRect.isEmpty()) {
|
||||
// An empty rect will have no coverage anywhere.
|
||||
*color = 0x00000000;
|
||||
*validFlags = kRGBA_GrColorComponentFlags;
|
||||
} else {
|
||||
*validFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
AARectEffect(const SkRect& rect) : fRect(rect) {
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
|
||||
const AARectEffect& aare = CastEffect<AARectEffect>(other);
|
||||
return fRect == aare.fRect;
|
||||
}
|
||||
|
||||
SkRect fRect;
|
||||
typedef GrEffect INHERITED;
|
||||
|
||||
GR_DECLARE_EFFECT_TEST;
|
||||
|
||||
};
|
||||
|
||||
GR_DEFINE_EFFECT_TEST(AARectEffect);
|
||||
|
||||
GrEffectRef* AARectEffect::TestCreate(SkRandom* random,
|
||||
GrContext*,
|
||||
const GrDrawTargetCaps& caps,
|
||||
GrTexture*[]) {
|
||||
SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(),
|
||||
random->nextSScalar1(),
|
||||
random->nextSScalar1(),
|
||||
random->nextSScalar1());
|
||||
return AARectEffect::Create(rect);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GLAARectEffect : public GrGLEffect {
|
||||
public:
|
||||
GLAARectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
|
||||
|
||||
virtual void emitCode(GrGLShaderBuilder* builder,
|
||||
const GrDrawEffect& drawEffect,
|
||||
EffectKey key,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TransformedCoordsArray&,
|
||||
const TextureSamplerArray&) SK_OVERRIDE;
|
||||
|
||||
static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; }
|
||||
|
||||
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
GrGLUniformManager::UniformHandle fRectUniform;
|
||||
SkRect fPrevRect;
|
||||
typedef GrGLEffect INHERITED;
|
||||
};
|
||||
|
||||
GLAARectEffect::GLAARectEffect(const GrBackendEffectFactory& factory,
|
||||
const GrDrawEffect& drawEffect)
|
||||
: INHERITED (factory) {
|
||||
fPrevRect.fLeft = SK_ScalarNaN;
|
||||
}
|
||||
|
||||
void GLAARectEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrDrawEffect& drawEffect,
|
||||
EffectKey key,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TransformedCoordsArray&,
|
||||
const TextureSamplerArray& samplers) {
|
||||
const char *rectName;
|
||||
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");
|
||||
|
||||
builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
|
||||
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
|
||||
}
|
||||
|
||||
void GLAARectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
|
||||
const AARectEffect& aare = drawEffect.castEffect<AARectEffect>();
|
||||
const SkRect& rect = aare.getRect();
|
||||
if (rect != fPrevRect) {
|
||||
uman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
|
||||
rect.fRight - 0.5f, rect.fBottom - 0.5f);
|
||||
fPrevRect = rect;
|
||||
}
|
||||
}
|
||||
|
||||
const GrBackendEffectFactory& AARectEffect::getFactory() const {
|
||||
return GrTBackendEffectFactory<AARectEffect>::getInstance();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrGLConvexPolyEffect : public GrGLEffect {
|
||||
public:
|
||||
GrGLConvexPolyEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
|
||||
@ -146,6 +278,10 @@ GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path, const
|
||||
return Create(type, n, edges);
|
||||
}
|
||||
|
||||
GrEffectRef* GrConvexPolyEffect::CreateForAAFillRect(const SkRect& rect) {
|
||||
return AARectEffect::Create(rect);
|
||||
}
|
||||
|
||||
GrConvexPolyEffect::~GrConvexPolyEffect() {}
|
||||
|
||||
void GrConvexPolyEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
|
||||
|
@ -62,6 +62,11 @@ public:
|
||||
*/
|
||||
static GrEffectRef* Create(EdgeType, const SkPath&, const SkVector* offset= NULL);
|
||||
|
||||
/**
|
||||
* Creates an effect that fills inside the rect with AA edges..
|
||||
*/
|
||||
static GrEffectRef* CreateForAAFillRect(const SkRect&);
|
||||
|
||||
virtual ~GrConvexPolyEffect();
|
||||
|
||||
static const char* Name() { return "ConvexPoly"; }
|
||||
|
Loading…
Reference in New Issue
Block a user