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