blob: fde636071b21b115e7215e0ec20d1f406a07e723 [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
joshualitt04194f32016-01-13 10:08:27 -080010#include "GrContext.h"
11#include "GrDrawContext.h"
12#include "GrPipelineBuilder.h"
bsalomonc41f4d62015-08-03 14:23:03 -070013#include "SkDevice.h"
14#include "SkRRect.h"
joshualitt04194f32016-01-13 10:08:27 -080015#include "batches/GrDrawBatch.h"
16#include "batches/GrRectBatchFactory.h"
17#include "effects/GrRRectEffect.h"
bsalomonc41f4d62015-08-03 14:23:03 -070018
19namespace skiagm {
20
21///////////////////////////////////////////////////////////////////////////////
22
23class BigRRectAAEffectGM : public GM {
24public:
bsalomon4a4f14b2015-12-09 10:17:35 -080025 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;
bsalomonc41f4d62015-08-03 14:23:03 -070041 }
42
43protected:
44 SkString onShortName() override {
bsalomon4a4f14b2015-12-09 10:17:35 -080045 SkString name;
46 name.printf("big_rrect_%s_aa_effect", fName);
47 return name;
bsalomonc41f4d62015-08-03 14:23:03 -070048 }
49
bsalomon4a4f14b2015-12-09 10:17:35 -080050 SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
bsalomonc41f4d62015-08-03 14:23:03 -070051
52 void onDraw(SkCanvas* canvas) override {
53 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -070054 GrContext* context = rt ? rt->getContext() : nullptr;
bsalomonc41f4d62015-08-03 14:23:03 -070055 if (!context) {
halcanary2a243382015-09-09 08:16:41 -070056 skiagm::GM::DrawGpuOnlyMessage(canvas);
bsalomonc41f4d62015-08-03 14:23:03 -070057 return;
58 }
59
joshualitt04194f32016-01-13 10:08:27 -080060 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
61 if (!drawContext) {
62 return;
63 }
64
bsalomonc41f4d62015-08-03 14:23:03 -070065 SkPaint paint;
66
bsalomonc41f4d62015-08-03 14:23:03 -070067 int y = kPad;
68 int x = kPad;
69 static const GrPrimitiveEdgeType kEdgeTypes[] = {
70 kFillAA_GrProcessorEdgeType,
71 kInverseFillAA_GrProcessorEdgeType,
72 };
bsalomon4a4f14b2015-12-09 10:17:35 -080073 SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
bsalomonc41f4d62015-08-03 14:23:03 -070074 for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
75 GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
bsalomon4a4f14b2015-12-09 10:17:35 -080076 canvas->save();
77 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
bsalomonc41f4d62015-08-03 14:23:03 -070078
bsalomon4a4f14b2015-12-09 10:17:35 -080079 // Draw a background for the test case
80 SkPaint paint;
81 paint.setColor(SK_ColorWHITE);
82 canvas->drawRect(testBounds, paint);
bsalomonc41f4d62015-08-03 14:23:03 -070083
bsalomon4a4f14b2015-12-09 10:17:35 -080084 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
joshualitt04194f32016-01-13 10:08:27 -080099 SkAutoTUnref<GrDrawBatch> batch(
100 GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
101 nullptr, nullptr));
102 drawContext->internal_drawBatch(pipelineBuilder, batch);
bsalomon4a4f14b2015-12-09 10:17:35 -0800103 }
104 canvas->restore();
105 x = x + fTestOffsetX;
bsalomonc41f4d62015-08-03 14:23:03 -0700106 }
107 }
108
bsalomonc41f4d62015-08-03 14:23:03 -0700109private:
bsalomon4a4f14b2015-12-09 10:17:35 -0800110 // 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;
bsalomonc41f4d62015-08-03 14:23:03 -0700114
bsalomon4a4f14b2015-12-09 10:17:35 -0800115 SkRRect fRRect;
116 int fWidth;
117 int fHeight;
118 int fTestWidth;
119 int fTestHeight;
120 int fTestOffsetX;
121 int fTestOffsetY;
122 const char* fName;
bsalomonc41f4d62015-08-03 14:23:03 -0700123 typedef GM INHERITED;
124};
125
126///////////////////////////////////////////////////////////////////////////////
bsalomon4a4f14b2015-12-09 10:17:35 -0800127// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
128// the shader
129static const int kSize = 700;
bsalomonc41f4d62015-08-03 14:23:03 -0700130
bsalomon4a4f14b2015-12-09 10:17:35 -0800131DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
132DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
133DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
134// The next two have small linear segments between the corners
135DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
136DEF_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 -0700137
138}
139#endif