2012-12-17 21:48:19 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2012 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm.h"
|
2014-03-04 16:52:20 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2016-01-13 18:08:27 +00:00
|
|
|
#include "GrContext.h"
|
2016-10-27 18:47:55 +00:00
|
|
|
#include "GrRenderTargetContextPriv.h"
|
2016-12-01 15:59:09 +00:00
|
|
|
#include "batches/GrDrawOp.h"
|
2016-01-13 18:08:27 +00:00
|
|
|
#include "batches/GrRectBatchFactory.h"
|
2014-03-04 16:52:20 +00:00
|
|
|
#include "effects/GrRRectEffect.h"
|
|
|
|
#endif
|
2012-12-17 21:48:19 +00:00
|
|
|
#include "SkRRect.h"
|
|
|
|
|
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class RRectGM : public GM {
|
|
|
|
public:
|
2014-03-04 16:25:34 +00:00
|
|
|
enum Type {
|
|
|
|
kBW_Draw_Type,
|
|
|
|
kAA_Draw_Type,
|
|
|
|
kBW_Clip_Type,
|
|
|
|
kAA_Clip_Type,
|
|
|
|
kEffect_Type,
|
|
|
|
};
|
2016-01-08 21:48:43 +00:00
|
|
|
RRectGM(Type type) : fType(type) { }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
void onOnceBeforeDraw() override {
|
2015-06-15 13:51:08 +00:00
|
|
|
this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
|
2012-12-17 21:48:19 +00:00
|
|
|
this->setUpRRects();
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkString onShortName() override {
|
2012-12-17 21:48:19 +00:00
|
|
|
SkString name("rrect");
|
2014-03-04 16:25:34 +00:00
|
|
|
switch (fType) {
|
|
|
|
case kBW_Draw_Type:
|
|
|
|
name.append("_draw_bw");
|
|
|
|
break;
|
|
|
|
case kAA_Draw_Type:
|
|
|
|
name.append("_draw_aa");
|
|
|
|
break;
|
|
|
|
case kBW_Clip_Type:
|
|
|
|
name.append("_clip_bw");
|
|
|
|
break;
|
|
|
|
case kAA_Clip_Type:
|
|
|
|
name.append("_clip_aa");
|
|
|
|
break;
|
|
|
|
case kEffect_Type:
|
|
|
|
name.append("_effect");
|
|
|
|
break;
|
2012-12-17 21:48:19 +00:00
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2016-10-27 18:47:55 +00:00
|
|
|
GrRenderTargetContext* renderTargetContext =
|
|
|
|
canvas->internal_private_accessTopLayerRenderTargetContext();
|
|
|
|
if (kEffect_Type == fType && !renderTargetContext) {
|
2015-09-09 15:16:41 +00:00
|
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
2014-03-04 16:25:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2014-03-04 16:25:34 +00:00
|
|
|
SkPaint paint;
|
|
|
|
if (kAA_Draw_Type == fType) {
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
}
|
2014-03-05 03:02:06 +00:00
|
|
|
|
2016-09-01 18:24:54 +00:00
|
|
|
const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
|
|
|
|
SkIntToScalar(kTileY));
|
2014-03-10 19:33:16 +00:00
|
|
|
#ifdef SK_DEBUG
|
2016-09-01 18:24:54 +00:00
|
|
|
const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
|
|
|
|
SkIntToScalar(kImageHeight));
|
2014-03-10 19:33:16 +00:00
|
|
|
#endif
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2014-03-10 19:51:46 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-09-23 16:50:21 +00:00
|
|
|
int lastEdgeType = (kEffect_Type == fType) ? kLast_GrProcessorEdgeType: 0;
|
2014-03-10 19:51:46 +00:00
|
|
|
#else
|
|
|
|
int lastEdgeType = 0;
|
|
|
|
#endif
|
2014-03-10 19:33:16 +00:00
|
|
|
|
|
|
|
int y = 1;
|
2014-03-10 19:51:46 +00:00
|
|
|
for (int et = 0; et <= lastEdgeType; ++et) {
|
2014-03-10 19:33:16 +00:00
|
|
|
int x = 1;
|
|
|
|
for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
|
|
|
|
bool drew = true;
|
|
|
|
#ifdef SK_DEBUG
|
|
|
|
SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
|
|
|
|
SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
|
|
|
|
imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
|
|
|
|
#endif
|
2012-12-17 21:48:19 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
2014-03-04 16:25:34 +00:00
|
|
|
if (kEffect_Type == fType) {
|
2014-03-04 16:52:20 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2016-06-23 21:07:00 +00:00
|
|
|
GrPaint grPaint;
|
2016-10-28 19:42:34 +00:00
|
|
|
grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
|
2014-03-05 03:02:06 +00:00
|
|
|
|
2014-03-10 19:33:16 +00:00
|
|
|
SkRRect rrect = fRRects[curRRect];
|
2014-03-04 16:25:34 +00:00
|
|
|
rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
|
2014-09-23 16:50:21 +00:00
|
|
|
GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
|
2016-06-09 15:01:03 +00:00
|
|
|
sk_sp<GrFragmentProcessor> fp(GrRRectEffect::Make(edgeType, rrect));
|
2014-09-23 16:50:21 +00:00
|
|
|
if (fp) {
|
2016-06-23 21:07:00 +00:00
|
|
|
grPaint.addCoverageFragmentProcessor(std::move(fp));
|
2014-03-04 16:25:34 +00:00
|
|
|
|
|
|
|
SkRect bounds = rrect.getBounds();
|
|
|
|
bounds.outset(2.f, 2.f);
|
2014-03-05 03:02:06 +00:00
|
|
|
|
2016-12-09 21:07:12 +00:00
|
|
|
sk_sp<GrDrawOp> op(
|
2016-01-13 18:08:27 +00:00
|
|
|
GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(),
|
|
|
|
bounds, nullptr, nullptr));
|
2016-12-09 21:07:12 +00:00
|
|
|
renderTargetContext->priv().testingOnly_addDrawOp(grPaint,
|
2016-12-09 20:10:07 +00:00
|
|
|
GrAAType::kNone,
|
2016-12-09 21:07:12 +00:00
|
|
|
std::move(op));
|
2014-03-10 19:33:16 +00:00
|
|
|
} else {
|
|
|
|
drew = false;
|
2014-03-04 16:25:34 +00:00
|
|
|
}
|
2014-03-04 16:52:20 +00:00
|
|
|
#endif
|
2014-03-04 16:25:34 +00:00
|
|
|
} else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
|
|
|
|
bool aaClip = (kAA_Clip_Type == fType);
|
2016-09-21 18:15:07 +00:00
|
|
|
canvas->clipRRect(fRRects[curRRect], aaClip);
|
2012-12-17 21:48:19 +00:00
|
|
|
canvas->drawRect(kMaxTileBound, paint);
|
|
|
|
} else {
|
2014-03-10 19:33:16 +00:00
|
|
|
canvas->drawRRect(fRRects[curRRect], paint);
|
2012-12-17 21:48:19 +00:00
|
|
|
}
|
|
|
|
canvas->restore();
|
2014-03-10 19:33:16 +00:00
|
|
|
if (drew) {
|
|
|
|
x = x + kTileX;
|
|
|
|
if (x > kImageWidth) {
|
|
|
|
x = 1;
|
|
|
|
y += kTileY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (x != 1) {
|
|
|
|
y += kTileY;
|
2012-12-17 21:48:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void setUpRRects() {
|
2012-12-18 02:03:03 +00:00
|
|
|
// each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
|
2012-12-17 21:48:19 +00:00
|
|
|
// the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
|
|
|
|
|
|
|
|
// simple cases
|
|
|
|
fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
|
|
|
|
fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
|
|
|
|
fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
|
2014-02-19 15:18:05 +00:00
|
|
|
fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
|
|
|
|
// small circular corners are an interesting test case for gpu clipping
|
|
|
|
fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
|
|
|
|
fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
|
|
|
|
fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
|
2012-12-17 21:48:19 +00:00
|
|
|
|
|
|
|
// The first complex case needs special handling since it is a square
|
|
|
|
fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
|
2012-12-24 13:56:17 +00:00
|
|
|
for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
|
2012-12-17 21:48:19 +00:00
|
|
|
fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-03-04 16:25:34 +00:00
|
|
|
Type fType;
|
2014-03-05 03:02:06 +00:00
|
|
|
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kImageWidth = 640;
|
|
|
|
static constexpr int kImageHeight = 480;
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kTileX = 80;
|
|
|
|
static constexpr int kTileY = 40;
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kNumSimpleCases = 7;
|
|
|
|
static constexpr int kNumComplexCases = 35;
|
2012-12-17 21:58:02 +00:00
|
|
|
static const SkVector gRadii[kNumComplexCases][4];
|
2012-12-17 21:48:19 +00:00
|
|
|
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kNumRRects = kNumSimpleCases + kNumComplexCases;
|
2012-12-17 21:48:19 +00:00
|
|
|
SkRRect fRRects[kNumRRects];
|
|
|
|
|
|
|
|
typedef GM INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Radii for the various test cases. Order is UL, UR, LR, LL
|
|
|
|
const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
|
|
|
|
// a circle
|
|
|
|
{ { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
|
|
|
|
|
|
|
|
// odd ball cases
|
|
|
|
{ { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
|
|
|
|
{ { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
|
|
|
|
{ { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
|
|
|
|
|
|
|
|
// UL
|
|
|
|
{ { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
|
|
|
|
// UR
|
|
|
|
{ { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
|
|
|
|
// LR
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
|
|
|
|
|
|
|
|
// LL
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
|
|
|
|
|
|
|
|
// over-sized radii
|
|
|
|
{ { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
|
2014-02-21 22:41:56 +00:00
|
|
|
|
|
|
|
// circular corner tabs
|
|
|
|
{ { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
|
|
|
|
{ { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
|
|
|
|
{ { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
|
2014-03-11 15:54:51 +00:00
|
|
|
|
2014-03-24 14:53:09 +00:00
|
|
|
// small radius circular corner tabs
|
|
|
|
{ { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
|
|
|
|
{ { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
|
|
|
|
|
2014-03-11 15:54:51 +00:00
|
|
|
// single circular corner cases
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
|
|
|
|
{ { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
|
|
|
|
{ { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
|
|
|
|
{ { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
|
2014-03-13 18:01:05 +00:00
|
|
|
|
|
|
|
// nine patch elliptical
|
|
|
|
{ { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
|
|
|
|
{ { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
|
2014-03-24 14:53:09 +00:00
|
|
|
|
|
|
|
// nine patch elliptical, small radii
|
|
|
|
{ { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
|
|
|
|
{ { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
|
|
|
|
{ { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
|
|
|
|
{ { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
|
|
|
|
|
2012-12-17 21:48:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-03-04 16:25:34 +00:00
|
|
|
DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
|
|
|
|
DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
|
|
|
|
DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
|
|
|
|
DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
|
2014-03-04 16:52:20 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-03-04 16:25:34 +00:00
|
|
|
DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )
|
2014-03-04 16:52:20 +00:00
|
|
|
#endif
|
2012-12-17 21:48:19 +00:00
|
|
|
|
|
|
|
}
|