blob: c3f47f932d1ca06c85c50d58d635fb090b50805b [file] [log] [blame]
bsalomonc41f4d62015-08-03 14:23:03 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#if SK_SUPPORT_GPU
10#include "GrTest.h"
11#include "effects/GrRRectEffect.h"
12#include "SkDevice.h"
13#include "SkRRect.h"
14
15namespace skiagm {
16
17///////////////////////////////////////////////////////////////////////////////
18
19class BigRRectAAEffectGM : public GM {
20public:
bsalomon4a4f14b2015-12-09 10:17:35 -080021 BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
22 : fRRect(rrect)
23 , fName(name) {
24 this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
25 // Each test case draws the rrect with gaps around it.
26 fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
27 fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
28
29 // Add a pad between test cases.
30 fTestOffsetX = fTestWidth + kPad;
31 fTestOffsetY = fTestHeight + kPad;
32
33 // We draw two tests in x (fill and inv-fill) and pad around
34 // all four sides of the image.
35 fWidth = 2 * fTestOffsetX + kPad;
36 fHeight = fTestOffsetY + kPad;
bsalomonc41f4d62015-08-03 14:23:03 -070037 }
38
39protected:
40 SkString onShortName() override {
bsalomon4a4f14b2015-12-09 10:17:35 -080041 SkString name;
42 name.printf("big_rrect_%s_aa_effect", fName);
43 return name;
bsalomonc41f4d62015-08-03 14:23:03 -070044 }
45
bsalomon4a4f14b2015-12-09 10:17:35 -080046 SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
bsalomonc41f4d62015-08-03 14:23:03 -070047
48 void onDraw(SkCanvas* canvas) override {
49 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -070050 GrContext* context = rt ? rt->getContext() : nullptr;
bsalomonc41f4d62015-08-03 14:23:03 -070051 if (!context) {
halcanary2a243382015-09-09 08:16:41 -070052 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonc41f4d62015-08-03 14:23:03 -070053 return;
54 }
55
56 SkPaint paint;
57
bsalomonc41f4d62015-08-03 14:23:03 -070058 int y = kPad;
59 int x = kPad;
60 static const GrPrimitiveEdgeType kEdgeTypes[] = {
61 kFillAA_GrProcessorEdgeType,
62 kInverseFillAA_GrProcessorEdgeType,
63 };
bsalomon4a4f14b2015-12-09 10:17:35 -080064 SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
bsalomonc41f4d62015-08-03 14:23:03 -070065 for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
66 GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
bsalomon4a4f14b2015-12-09 10:17:35 -080067 canvas->save();
68 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
bsalomonc41f4d62015-08-03 14:23:03 -070069
bsalomon4a4f14b2015-12-09 10:17:35 -080070 // Draw a background for the test case
71 SkPaint paint;
72 paint.setColor(SK_ColorWHITE);
73 canvas->drawRect(testBounds, paint);
bsalomonc41f4d62015-08-03 14:23:03 -070074
bsalomon4a4f14b2015-12-09 10:17:35 -080075 GrTestTarget tt;
76 context->getTestTarget(&tt, rt);
77 if (!tt.target()) {
78 SkDEBUGFAIL("Couldn't get Gr test target.");
79 return;
bsalomonc41f4d62015-08-03 14:23:03 -070080 }
bsalomon4a4f14b2015-12-09 10:17:35 -080081 GrPipelineBuilder pipelineBuilder;
82 pipelineBuilder.setXPFactory(
83 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
84
85 SkRRect rrect = fRRect;
86 rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
87 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
88 SkASSERT(fp);
89 if (fp) {
90 pipelineBuilder.addCoverageFragmentProcessor(fp);
91 pipelineBuilder.setRenderTarget(rt);
92
93 SkRect bounds = testBounds;
94 bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
95
96 tt.target()->drawNonAARect(pipelineBuilder,
97 0xff000000,
98 SkMatrix::I(),
99 bounds);
100 }
101 canvas->restore();
102 x = x + fTestOffsetX;
bsalomonc41f4d62015-08-03 14:23:03 -0700103 }
104 }
105
bsalomonc41f4d62015-08-03 14:23:03 -0700106private:
bsalomon4a4f14b2015-12-09 10:17:35 -0800107 // pad between test cases
108 static const int kPad = 7;
109 // gap between rect for each case that is rendered and exterior of rrect
110 static const int kGap = 3;
bsalomonc41f4d62015-08-03 14:23:03 -0700111
bsalomon4a4f14b2015-12-09 10:17:35 -0800112 SkRRect fRRect;
113 int fWidth;
114 int fHeight;
115 int fTestWidth;
116 int fTestHeight;
117 int fTestOffsetX;
118 int fTestOffsetY;
119 const char* fName;
bsalomonc41f4d62015-08-03 14:23:03 -0700120 typedef GM INHERITED;
121};
122
123///////////////////////////////////////////////////////////////////////////////
bsalomon4a4f14b2015-12-09 10:17:35 -0800124// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
125// the shader
126static const int kSize = 700;
bsalomonc41f4d62015-08-03 14:23:03 -0700127
bsalomon4a4f14b2015-12-09 10:17:35 -0800128DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
129DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
130DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
131// The next two have small linear segments between the corners
132DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
133DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
bsalomonc41f4d62015-08-03 14:23:03 -0700134
135}
136#endif