blob: 7f79a34c6bf62434de74d0d896440fd8fc6fa81e [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"
robertphillips391395d2016-03-02 09:26:36 -080011#include "GrDrawContextPriv.h"
bsalomonc41f4d62015-08-03 14:23:03 -070012#include "SkRRect.h"
joshualitt04194f32016-01-13 10:08:27 -080013#include "batches/GrDrawBatch.h"
14#include "batches/GrRectBatchFactory.h"
15#include "effects/GrRRectEffect.h"
bsalomonc41f4d62015-08-03 14:23:03 -070016
17namespace skiagm {
18
19///////////////////////////////////////////////////////////////////////////////
20
21class BigRRectAAEffectGM : public GM {
22public:
bsalomon4a4f14b2015-12-09 10:17:35 -080023 BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
24 : fRRect(rrect)
25 , fName(name) {
26 this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
27 // Each test case draws the rrect with gaps around it.
28 fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
29 fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
30
31 // Add a pad between test cases.
32 fTestOffsetX = fTestWidth + kPad;
33 fTestOffsetY = fTestHeight + kPad;
34
35 // We draw two tests in x (fill and inv-fill) and pad around
36 // all four sides of the image.
37 fWidth = 2 * fTestOffsetX + kPad;
38 fHeight = fTestOffsetY + kPad;
bsalomonc41f4d62015-08-03 14:23:03 -070039 }
40
41protected:
42 SkString onShortName() override {
bsalomon4a4f14b2015-12-09 10:17:35 -080043 SkString name;
44 name.printf("big_rrect_%s_aa_effect", fName);
45 return name;
bsalomonc41f4d62015-08-03 14:23:03 -070046 }
47
bsalomon4a4f14b2015-12-09 10:17:35 -080048 SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
bsalomonc41f4d62015-08-03 14:23:03 -070049
50 void onDraw(SkCanvas* canvas) override {
robertphillips175dd9b2016-04-28 14:32:04 -070051 GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
joshualitt04194f32016-01-13 10:08:27 -080052 if (!drawContext) {
robertphillips175dd9b2016-04-28 14:32:04 -070053 skiagm::GM::DrawGpuOnlyMessage(canvas);
joshualitt04194f32016-01-13 10:08:27 -080054 return;
55 }
56
bsalomonc41f4d62015-08-03 14:23:03 -070057 SkPaint paint;
58
bsalomonc41f4d62015-08-03 14:23:03 -070059 int y = kPad;
60 int x = kPad;
61 static const GrPrimitiveEdgeType kEdgeTypes[] = {
62 kFillAA_GrProcessorEdgeType,
63 kInverseFillAA_GrProcessorEdgeType,
64 };
bsalomon4a4f14b2015-12-09 10:17:35 -080065 SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
bsalomonc41f4d62015-08-03 14:23:03 -070066 for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
67 GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
bsalomon4a4f14b2015-12-09 10:17:35 -080068 canvas->save();
halcanary9d524f22016-03-29 09:03:52 -070069 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
bsalomonc41f4d62015-08-03 14:23:03 -070070
bsalomon4a4f14b2015-12-09 10:17:35 -080071 // Draw a background for the test case
72 SkPaint paint;
73 paint.setColor(SK_ColorWHITE);
74 canvas->drawRect(testBounds, paint);
bsalomonc41f4d62015-08-03 14:23:03 -070075
robertphillips28a838e2016-06-23 14:07:00 -070076 GrPaint grPaint;
77 grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
bsalomon4a4f14b2015-12-09 10:17:35 -080078
79 SkRRect rrect = fRRect;
80 rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
bungeman06ca8ec2016-06-09 08:01:03 -070081 sk_sp<GrFragmentProcessor> fp(GrRRectEffect::Make(edgeType, rrect));
bsalomon4a4f14b2015-12-09 10:17:35 -080082 SkASSERT(fp);
83 if (fp) {
robertphillips28a838e2016-06-23 14:07:00 -070084 grPaint.addCoverageFragmentProcessor(std::move(fp));
bsalomon4a4f14b2015-12-09 10:17:35 -080085
86 SkRect bounds = testBounds;
87 bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
88
joshualitt04194f32016-01-13 10:08:27 -080089 SkAutoTUnref<GrDrawBatch> batch(
90 GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
91 nullptr, nullptr));
robertphillips28a838e2016-06-23 14:07:00 -070092 drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch);
bsalomon4a4f14b2015-12-09 10:17:35 -080093 }
94 canvas->restore();
95 x = x + fTestOffsetX;
bsalomonc41f4d62015-08-03 14:23:03 -070096 }
97 }
98
bsalomonc41f4d62015-08-03 14:23:03 -070099private:
bsalomon4a4f14b2015-12-09 10:17:35 -0800100 // pad between test cases
101 static const int kPad = 7;
102 // gap between rect for each case that is rendered and exterior of rrect
103 static const int kGap = 3;
bsalomonc41f4d62015-08-03 14:23:03 -0700104
bsalomon4a4f14b2015-12-09 10:17:35 -0800105 SkRRect fRRect;
106 int fWidth;
107 int fHeight;
108 int fTestWidth;
109 int fTestHeight;
110 int fTestOffsetX;
111 int fTestOffsetY;
112 const char* fName;
bsalomonc41f4d62015-08-03 14:23:03 -0700113 typedef GM INHERITED;
114};
115
116///////////////////////////////////////////////////////////////////////////////
bsalomon4a4f14b2015-12-09 10:17:35 -0800117// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
118// the shader
119static const int kSize = 700;
bsalomonc41f4d62015-08-03 14:23:03 -0700120
bsalomon4a4f14b2015-12-09 10:17:35 -0800121DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
122DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
123DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
124// The next two have small linear segments between the corners
125DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
126DEF_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 -0700127
128}
129#endif