Split big rrect aa effect up into separate images
Needed to enlarge radii to surface bugs without exceeding max texture size on low end devices. BUG=chromium:477684 Review URL: https://codereview.chromium.org/1508003008
This commit is contained in:
parent
db64af3b17
commit
4a4f14ba3f
@ -18,17 +18,32 @@ namespace skiagm {
|
||||
|
||||
class BigRRectAAEffectGM : public GM {
|
||||
public:
|
||||
BigRRectAAEffectGM() {
|
||||
this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
|
||||
this->setUpRRects();
|
||||
BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
|
||||
: fRRect(rrect)
|
||||
, fName(name) {
|
||||
this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
|
||||
// Each test case draws the rrect with gaps around it.
|
||||
fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
|
||||
fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
|
||||
|
||||
// Add a pad between test cases.
|
||||
fTestOffsetX = fTestWidth + kPad;
|
||||
fTestOffsetY = fTestHeight + kPad;
|
||||
|
||||
// We draw two tests in x (fill and inv-fill) and pad around
|
||||
// all four sides of the image.
|
||||
fWidth = 2 * fTestOffsetX + kPad;
|
||||
fHeight = fTestOffsetY + kPad;
|
||||
}
|
||||
|
||||
protected:
|
||||
SkString onShortName() override {
|
||||
return SkString("big_rrect_aa_effect");
|
||||
SkString name;
|
||||
name.printf("big_rrect_%s_aa_effect", fName);
|
||||
return name;
|
||||
}
|
||||
|
||||
SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
|
||||
SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
|
||||
@ -40,95 +55,82 @@ protected:
|
||||
|
||||
SkPaint paint;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
static const SkRect kMaxRRectBound = SkRect::MakeWH(SkIntToScalar(kMaxSize),
|
||||
SkIntToScalar(kMaxSize));
|
||||
static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
|
||||
SkIntToScalar(kImageHeight));
|
||||
#endif
|
||||
|
||||
int y = kPad;
|
||||
int x = kPad;
|
||||
static const GrPrimitiveEdgeType kEdgeTypes[] = {
|
||||
kFillAA_GrProcessorEdgeType,
|
||||
kInverseFillAA_GrProcessorEdgeType,
|
||||
};
|
||||
SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
|
||||
for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
|
||||
GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
|
||||
for (int curRRect = 0; curRRect < fRRects.count(); ++curRRect) {
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERT(kMaxRRectBound.contains(fRRects[curRRect].getBounds()));
|
||||
SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
|
||||
imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
||||
SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
|
||||
#endif
|
||||
canvas->save();
|
||||
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
||||
GrTestTarget tt;
|
||||
context->getTestTarget(&tt, rt);
|
||||
if (nullptr == tt.target()) {
|
||||
SkDEBUGFAIL("Couldn't get Gr test target.");
|
||||
return;
|
||||
}
|
||||
GrPipelineBuilder pipelineBuilder;
|
||||
pipelineBuilder.setXPFactory(
|
||||
GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
|
||||
canvas->save();
|
||||
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
||||
|
||||
SkRRect rrect = fRRects[curRRect];
|
||||
rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
|
||||
SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
|
||||
SkASSERT(fp);
|
||||
if (fp) {
|
||||
pipelineBuilder.addCoverageFragmentProcessor(fp);
|
||||
pipelineBuilder.setRenderTarget(rt);
|
||||
// Draw a background for the test case
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorWHITE);
|
||||
canvas->drawRect(testBounds, paint);
|
||||
|
||||
SkRect bounds = SkRect::MakeWH(SkIntToScalar(kMaxSize),
|
||||
SkIntToScalar(kMaxSize));
|
||||
bounds.outset(2.f, 2.f);
|
||||
bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
||||
|
||||
tt.target()->drawNonAARect(pipelineBuilder,
|
||||
0xff000000,
|
||||
SkMatrix::I(),
|
||||
bounds);
|
||||
}
|
||||
canvas->restore();
|
||||
x = x + kDrawOffset;
|
||||
if (x + kMaxSize> kImageWidth) {
|
||||
x = kPad;
|
||||
y += kDrawOffset;
|
||||
GrTestTarget tt;
|
||||
context->getTestTarget(&tt, rt);
|
||||
if (!tt.target()) {
|
||||
SkDEBUGFAIL("Couldn't get Gr test target.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
GrPipelineBuilder pipelineBuilder;
|
||||
pipelineBuilder.setXPFactory(
|
||||
GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
|
||||
|
||||
SkRRect rrect = fRRect;
|
||||
rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
|
||||
SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
|
||||
SkASSERT(fp);
|
||||
if (fp) {
|
||||
pipelineBuilder.addCoverageFragmentProcessor(fp);
|
||||
pipelineBuilder.setRenderTarget(rt);
|
||||
|
||||
SkRect bounds = testBounds;
|
||||
bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
||||
|
||||
tt.target()->drawNonAARect(pipelineBuilder,
|
||||
0xff000000,
|
||||
SkMatrix::I(),
|
||||
bounds);
|
||||
}
|
||||
canvas->restore();
|
||||
x = x + fTestOffsetX;
|
||||
}
|
||||
}
|
||||
|
||||
void setUpRRects() {
|
||||
SkScalar maxSize = SkIntToScalar(kMaxSize);
|
||||
fRRects.push()->setRect(SkRect::MakeWH(maxSize, maxSize));
|
||||
fRRects.push()->setOval(SkRect::MakeWH(maxSize, maxSize));
|
||||
fRRects.push()->setOval(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f));
|
||||
fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f),
|
||||
maxSize/2.f - 10.f, maxSize/2.f - 10.f);
|
||||
fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10),
|
||||
maxSize/2.f - 10.f, maxSize/2.f - 20.f);
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kPad = 5;
|
||||
static const int kMaxSize = 300;
|
||||
static const int kDrawOffset = kMaxSize + kPad;
|
||||
// pad between test cases
|
||||
static const int kPad = 7;
|
||||
// gap between rect for each case that is rendered and exterior of rrect
|
||||
static const int kGap = 3;
|
||||
|
||||
static const int kImageWidth = 4 * kDrawOffset + kPad;
|
||||
static const int kImageHeight = 3 * kDrawOffset + kPad;
|
||||
|
||||
|
||||
SkTDArray<SkRRect> fRRects;
|
||||
SkRRect fRRect;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
int fTestWidth;
|
||||
int fTestHeight;
|
||||
int fTestOffsetX;
|
||||
int fTestOffsetY;
|
||||
const char* fName;
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
|
||||
// the shader
|
||||
static const int kSize = 700;
|
||||
|
||||
DEF_GM( return new BigRRectAAEffectGM (); )
|
||||
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
|
||||
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
|
||||
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
|
||||
// The next two have small linear segments between the corners
|
||||
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
|
||||
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -153,6 +153,12 @@ public:
|
||||
return rr;
|
||||
}
|
||||
|
||||
static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
|
||||
SkRRect rr;
|
||||
rr.setRectXY(rect, xRad, yRad);
|
||||
return rr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this RR to match the supplied oval. All x radii will equal half the
|
||||
* width and all y radii will equal half the height.
|
||||
|
Loading…
Reference in New Issue
Block a user