• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "GrContext.h"
11 #include "GrDrawContext.h"
12 #include "GrPipelineBuilder.h"
13 #include "SkDevice.h"
14 #include "SkRRect.h"
15 #include "batches/GrDrawBatch.h"
16 #include "batches/GrRectBatchFactory.h"
17 #include "effects/GrRRectEffect.h"
18 
19 namespace skiagm {
20 
21 ///////////////////////////////////////////////////////////////////////////////
22 
23 class BigRRectAAEffectGM : public GM {
24 public:
BigRRectAAEffectGM(const SkRRect & rrect,const char * name)25     BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
26         : fRRect(rrect)
27         , fName(name) {
28         this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
29         // Each test case draws the rrect with gaps around it.
30         fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
31         fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
32 
33         // Add a pad between test cases.
34         fTestOffsetX = fTestWidth + kPad;
35         fTestOffsetY = fTestHeight + kPad;
36 
37         // We draw two tests in x (fill and inv-fill) and pad around
38         // all four sides of the image.
39         fWidth = 2 * fTestOffsetX + kPad;
40         fHeight = fTestOffsetY + kPad;
41     }
42 
43 protected:
onShortName()44     SkString onShortName() override {
45         SkString name;
46         name.printf("big_rrect_%s_aa_effect", fName);
47         return name;
48     }
49 
onISize()50     SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
51 
onDraw(SkCanvas * canvas)52     void onDraw(SkCanvas* canvas) override {
53         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
54         GrContext* context = rt ? rt->getContext() : nullptr;
55         if (!context) {
56             skiagm::GM::DrawGpuOnlyMessage(canvas);
57             return;
58         }
59 
60         SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
61         if (!drawContext) {
62             return;
63         }
64 
65         SkPaint paint;
66 
67         int y = kPad;
68         int x = kPad;
69         static const GrPrimitiveEdgeType kEdgeTypes[] = {
70             kFillAA_GrProcessorEdgeType,
71             kInverseFillAA_GrProcessorEdgeType,
72         };
73         SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
74         for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
75             GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
76             canvas->save();
77                 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
78 
79                 // Draw a background for the test case
80                 SkPaint paint;
81                 paint.setColor(SK_ColorWHITE);
82                 canvas->drawRect(testBounds, paint);
83 
84                 GrPipelineBuilder pipelineBuilder;
85                 pipelineBuilder.setXPFactory(
86                     GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
87 
88                 SkRRect rrect = fRRect;
89                 rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
90                 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
91                 SkASSERT(fp);
92                 if (fp) {
93                     pipelineBuilder.addCoverageFragmentProcessor(fp);
94                     pipelineBuilder.setRenderTarget(rt);
95 
96                     SkRect bounds = testBounds;
97                     bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
98 
99                     SkAutoTUnref<GrDrawBatch> batch(
100                             GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
101                                                                 nullptr, nullptr));
102                     drawContext->internal_drawBatch(pipelineBuilder, batch);
103                 }
104             canvas->restore();
105             x = x + fTestOffsetX;
106         }
107     }
108 
109 private:
110     // pad between test cases
111     static const int kPad = 7;
112     // gap between rect for each case that is rendered and exterior of rrect
113     static const int kGap = 3;
114 
115     SkRRect fRRect;
116     int fWidth;
117     int fHeight;
118     int fTestWidth;
119     int fTestHeight;
120     int fTestOffsetX;
121     int fTestOffsetY;
122     const char* fName;
123     typedef GM INHERITED;
124 };
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 // This value is motivated by bug chromium:477684. It has to be large to cause overflow in
128 // the shader
129 static const int kSize = 700;
130 
131 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
132 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
133 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
134 // The next two have small linear segments between the corners
135 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"); )
136 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"); )
137 
138 }
139 #endif
140