xref: /aosp_15_r20/external/skia/gm/convexpolyeffect.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2014 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 // This test only works with the GPU backend.
9 
10 #include "gm/gm.h"
11 #include "include/core/SkBlendMode.h"
12 #include "include/core/SkCanvas.h"
13 #include "include/core/SkMatrix.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkPath.h"
16 #include "include/core/SkPoint.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkScalar.h"
19 #include "include/core/SkSize.h"
20 #include "include/core/SkString.h"
21 #include "include/private/gpu/ganesh/GrTypesPriv.h"
22 #include "src/core/SkCanvasPriv.h"
23 #include "src/gpu/ganesh/GrCanvas.h"
24 #include "src/gpu/ganesh/GrFragmentProcessor.h"
25 #include "src/gpu/ganesh/GrPaint.h"
26 #include "src/gpu/ganesh/SurfaceDrawContext.h"
27 #include "src/gpu/ganesh/effects/GrConvexPolyEffect.h"
28 #include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h"
29 #include "tools/gpu/TestOps.h"
30 
31 #include <memory>
32 #include <utility>
33 
34 class GrAppliedClip;
35 
36 namespace skiagm {
37 
38 /**
39  * This GM directly exercises a GrProcessor that draws convex polygons.
40  */
41 class ConvexPolyEffect : public GpuGM {
42 public:
ConvexPolyEffect()43     ConvexPolyEffect() {
44         this->setBGColor(0xFFFFFFFF);
45     }
46 
47 protected:
getName() const48     SkString getName() const override { return SkString("convex_poly_effect"); }
49 
getISize()50     SkISize getISize() override { return SkISize::Make(720, 550); }
51 
onOnceBeforeDraw()52     void onOnceBeforeDraw() override {
53         SkPath tri;
54         tri.moveTo(5.f, 5.f);
55         tri.lineTo(100.f, 20.f);
56         tri.lineTo(15.f, 100.f);
57 
58         fPaths.push_back(tri);
59         fPaths.emplace_back();
60         fPaths.back().reverseAddPath(tri);
61 
62         tri.close();
63         fPaths.push_back(tri);
64 
65         SkPath ngon;
66         constexpr SkScalar kRadius = 50.f;
67         const SkPoint center = { kRadius, kRadius };
68         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
69             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
70             SkPoint point = { SkScalarCos(angle), SkScalarSin(angle) };
71             point.scale(kRadius);
72             point = center + point;
73             if (0 == i) {
74                 ngon.moveTo(point);
75             } else {
76                 ngon.lineTo(point);
77             }
78         }
79 
80         fPaths.push_back(ngon);
81         SkMatrix scaleM;
82         scaleM.setScale(1.1f, 0.4f);
83         ngon.transform(scaleM);
84         fPaths.push_back(ngon);
85 
86         SkPath linePath;
87         linePath.moveTo(5.f, 5.f);
88         linePath.lineTo(6.f, 6.f);
89         fPaths.push_back(linePath);
90     }
91 
onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)92     DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
93         auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas);
94         if (!sdc) {
95             *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
96             return DrawResult::kSkip;
97         }
98 
99         SkScalar y = 0;
100         static constexpr SkScalar kDX = 12.f;
101         static constexpr SkScalar kOutset = 5.f;
102 
103         for (const SkPath& path : fPaths) {
104             SkScalar x = 0;
105 
106             for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
107                 const SkMatrix m = SkMatrix::Translate(x, y);
108                 SkPath p;
109                 path.transform(m, &p);
110 
111                 GrClipEdgeType edgeType = (GrClipEdgeType) et;
112                 auto [success, fp] = GrConvexPolyEffect::Make(/*inputFP=*/nullptr, edgeType, p);
113                 if (!success) {
114                     continue;
115                 }
116 
117                 GrPaint grPaint;
118                 grPaint.setColor4f({ 0, 0, 0, 1.f });
119                 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
120                 grPaint.setCoverageFragmentProcessor(std::move(fp));
121                 auto rect = p.getBounds().makeOutset(kOutset, kOutset);
122                 auto op = sk_gpu_test::test_ops::MakeRect(rContext, std::move(grPaint), rect);
123                 sdc->addDrawOp(std::move(op));
124 
125                 x += SkScalarCeilToScalar(path.getBounds().width() + kDX);
126             }
127 
128             // Draw AA and non AA paths using normal API for reference.
129             canvas->save();
130             canvas->translate(x, y);
131             SkPaint paint;
132             canvas->drawPath(path, paint);
133             canvas->translate(path.getBounds().width() + 10.f, 0);
134             paint.setAntiAlias(true);
135             canvas->drawPath(path, paint);
136             canvas->restore();
137 
138             y += SkScalarCeilToScalar(path.getBounds().height() + 20.f);
139         }
140 
141         return DrawResult::kOk;
142     }
143 
144 private:
145     std::vector<SkPath> fPaths;
146 
147     using INHERITED = GM;
148 };
149 
150 DEF_GM(return new ConvexPolyEffect;)
151 
152 }  // namespace skiagm
153