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