1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker // This test only works with the GPU backend. 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint3.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h" 24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h" 25*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h" 26*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 27*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCanvasPriv.h" 28*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkGeometry.h" 29*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPointPriv.h" 30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCanvas.h" 31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h" 32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h" 33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h" 34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrMemoryPool.h" 35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpFlushState.h" 36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpsRenderPass.h" 37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPaint.h" 38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorAnalysis.h" 39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorSet.h" 40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h" 41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h" 42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrUserStencilSettings.h" 43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h" 44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/effects/GrBezierEffect.h" 45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h" 46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrPathUtils.h" 47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrDrawOp.h" 48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrMeshDrawOp.h" 49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h" 50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h" 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 53*c8dee2aaSAndroid Build Coastguard Worker #include <utility> 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker class GrAppliedClip; 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm { 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker class BezierTestOp : public GrMeshDrawOp { 60*c8dee2aaSAndroid Build Coastguard Worker public: fixedFunctionFlags() const61*c8dee2aaSAndroid Build Coastguard Worker FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } 62*c8dee2aaSAndroid Build Coastguard Worker finalize(const GrCaps & caps,const GrAppliedClip * clip,GrClampType clampType)63*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet::Analysis finalize( 64*c8dee2aaSAndroid Build Coastguard Worker const GrCaps& caps, const GrAppliedClip* clip, GrClampType clampType) override { 65*c8dee2aaSAndroid Build Coastguard Worker return fProcessorSet.finalize( 66*c8dee2aaSAndroid Build Coastguard Worker fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, 67*c8dee2aaSAndroid Build Coastguard Worker &GrUserStencilSettings::kUnused, caps, clampType, &fColor); 68*c8dee2aaSAndroid Build Coastguard Worker } 69*c8dee2aaSAndroid Build Coastguard Worker visitProxies(const GrVisitProxyFunc & func) const70*c8dee2aaSAndroid Build Coastguard Worker void visitProxies(const GrVisitProxyFunc& func) const override { 71*c8dee2aaSAndroid Build Coastguard Worker if (fProgramInfo) { 72*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo->visitFPProxies(func); 73*c8dee2aaSAndroid Build Coastguard Worker } else { 74*c8dee2aaSAndroid Build Coastguard Worker fProcessorSet.visitProxies(func); 75*c8dee2aaSAndroid Build Coastguard Worker } 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker 78*c8dee2aaSAndroid Build Coastguard Worker protected: BezierTestOp(const SkRect & rect,const SkPMColor4f & color,int32_t classID)79*c8dee2aaSAndroid Build Coastguard Worker BezierTestOp(const SkRect& rect, const SkPMColor4f& color, int32_t classID) 80*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(classID) 81*c8dee2aaSAndroid Build Coastguard Worker , fRect(rect) 82*c8dee2aaSAndroid Build Coastguard Worker , fColor(color) 83*c8dee2aaSAndroid Build Coastguard Worker , fProcessorSet(SkBlendMode::kSrc) { 84*c8dee2aaSAndroid Build Coastguard Worker this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo); 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker 87*c8dee2aaSAndroid Build Coastguard Worker virtual GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) = 0; 88*c8dee2aaSAndroid Build Coastguard Worker programInfo()89*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* programInfo() override { return fProgramInfo; } 90*c8dee2aaSAndroid Build Coastguard Worker onCreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)91*c8dee2aaSAndroid Build Coastguard Worker void onCreateProgramInfo(const GrCaps* caps, 92*c8dee2aaSAndroid Build Coastguard Worker SkArenaAlloc* arena, 93*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView, 94*c8dee2aaSAndroid Build Coastguard Worker bool usesMSAASurface, 95*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip&& appliedClip, 96*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView& dstProxyView, 97*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers, 98*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) override { 99*c8dee2aaSAndroid Build Coastguard Worker auto gp = this->makeGP(*caps, arena); 100*c8dee2aaSAndroid Build Coastguard Worker if (!gp) { 101*c8dee2aaSAndroid Build Coastguard Worker return; 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone; 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, writeView, 107*c8dee2aaSAndroid Build Coastguard Worker usesMSAASurface, 108*c8dee2aaSAndroid Build Coastguard Worker std::move(appliedClip), 109*c8dee2aaSAndroid Build Coastguard Worker dstProxyView, gp, 110*c8dee2aaSAndroid Build Coastguard Worker std::move(fProcessorSet), 111*c8dee2aaSAndroid Build Coastguard Worker GrPrimitiveType::kTriangles, 112*c8dee2aaSAndroid Build Coastguard Worker renderPassXferBarriers, 113*c8dee2aaSAndroid Build Coastguard Worker colorLoadOp, 114*c8dee2aaSAndroid Build Coastguard Worker flags); 115*c8dee2aaSAndroid Build Coastguard Worker } 116*c8dee2aaSAndroid Build Coastguard Worker onExecute(GrOpFlushState * flushState,const SkRect & chainBounds)117*c8dee2aaSAndroid Build Coastguard Worker void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final { 118*c8dee2aaSAndroid Build Coastguard Worker if (!fProgramInfo) { 119*c8dee2aaSAndroid Build Coastguard Worker this->createProgramInfo(flushState); 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker if (!fProgramInfo) { 123*c8dee2aaSAndroid Build Coastguard Worker return; 124*c8dee2aaSAndroid Build Coastguard Worker } 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds); 127*c8dee2aaSAndroid Build Coastguard Worker flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline()); 128*c8dee2aaSAndroid Build Coastguard Worker flushState->drawMesh(*fMesh); 129*c8dee2aaSAndroid Build Coastguard Worker } 130*c8dee2aaSAndroid Build Coastguard Worker rect() const131*c8dee2aaSAndroid Build Coastguard Worker const SkRect& rect() const { return fRect; } color() const132*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& color() const { return fColor; } 133*c8dee2aaSAndroid Build Coastguard Worker 134*c8dee2aaSAndroid Build Coastguard Worker protected: 135*c8dee2aaSAndroid Build Coastguard Worker GrSimpleMesh* fMesh = nullptr; // filled in by the derived classes 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker private: 138*c8dee2aaSAndroid Build Coastguard Worker SkRect fRect; 139*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f fColor; 140*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet fProcessorSet; 141*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* fProgramInfo = nullptr; 142*c8dee2aaSAndroid Build Coastguard Worker 143*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrMeshDrawOp; 144*c8dee2aaSAndroid Build Coastguard Worker }; 145*c8dee2aaSAndroid Build Coastguard Worker 146*c8dee2aaSAndroid Build Coastguard Worker /** 147*c8dee2aaSAndroid Build Coastguard Worker * This GM directly exercises effects that draw Bezier curves in the GPU backend. 148*c8dee2aaSAndroid Build Coastguard Worker */ 149*c8dee2aaSAndroid Build Coastguard Worker class BezierConicTestOp : public BezierTestOp { 150*c8dee2aaSAndroid Build Coastguard Worker public: 151*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID 152*c8dee2aaSAndroid Build Coastguard Worker name() const153*c8dee2aaSAndroid Build Coastguard Worker const char* name() const final { return "BezierConicTestOp"; } 154*c8dee2aaSAndroid Build Coastguard Worker Make(GrRecordingContext * context,const SkRect & rect,const SkPMColor4f & color,const SkMatrix & klm)155*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* context, 156*c8dee2aaSAndroid Build Coastguard Worker const SkRect& rect, 157*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& color, 158*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& klm) { 159*c8dee2aaSAndroid Build Coastguard Worker return GrOp::Make<BezierConicTestOp>(context, rect, color, klm); 160*c8dee2aaSAndroid Build Coastguard Worker } 161*c8dee2aaSAndroid Build Coastguard Worker 162*c8dee2aaSAndroid Build Coastguard Worker private: 163*c8dee2aaSAndroid Build Coastguard Worker friend class ::GrOp; // for ctor 164*c8dee2aaSAndroid Build Coastguard Worker BezierConicTestOp(const SkRect & rect,const SkPMColor4f & color,const SkMatrix & klm)165*c8dee2aaSAndroid Build Coastguard Worker BezierConicTestOp(const SkRect& rect, const SkPMColor4f& color, const SkMatrix& klm) 166*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(rect, color, ClassID()) 167*c8dee2aaSAndroid Build Coastguard Worker , fKLM(klm) {} 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker struct Vertex { 170*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPosition; 171*c8dee2aaSAndroid Build Coastguard Worker float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 172*c8dee2aaSAndroid Build Coastguard Worker }; 173*c8dee2aaSAndroid Build Coastguard Worker makeGP(const GrCaps & caps,SkArenaAlloc * arena)174*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final { 175*c8dee2aaSAndroid Build Coastguard Worker auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(), 176*c8dee2aaSAndroid Build Coastguard Worker false); 177*c8dee2aaSAndroid Build Coastguard Worker if (!tmp) { 178*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 179*c8dee2aaSAndroid Build Coastguard Worker } 180*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tmp->vertexStride() == sizeof(Vertex)); 181*c8dee2aaSAndroid Build Coastguard Worker return tmp; 182*c8dee2aaSAndroid Build Coastguard Worker } 183*c8dee2aaSAndroid Build Coastguard Worker onPrepareDraws(GrMeshDrawTarget * target)184*c8dee2aaSAndroid Build Coastguard Worker void onPrepareDraws(GrMeshDrawTarget* target) final { 185*c8dee2aaSAndroid Build Coastguard Worker QuadHelper helper(target, sizeof(Vertex), 1); 186*c8dee2aaSAndroid Build Coastguard Worker Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices()); 187*c8dee2aaSAndroid Build Coastguard Worker if (!verts) { 188*c8dee2aaSAndroid Build Coastguard Worker return; 189*c8dee2aaSAndroid Build Coastguard Worker } 190*c8dee2aaSAndroid Build Coastguard Worker SkRect rect = this->rect(); 191*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex)); 192*c8dee2aaSAndroid Build Coastguard Worker for (int v = 0; v < 4; ++v) { 193*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f}; 194*c8dee2aaSAndroid Build Coastguard Worker fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1); 195*c8dee2aaSAndroid Build Coastguard Worker } 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker fMesh = helper.mesh(); 198*c8dee2aaSAndroid Build Coastguard Worker } 199*c8dee2aaSAndroid Build Coastguard Worker 200*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fKLM; 201*c8dee2aaSAndroid Build Coastguard Worker 202*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kVertsPerCubic = 4; 203*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kIndicesPerCubic = 6; 204*c8dee2aaSAndroid Build Coastguard Worker 205*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = BezierTestOp; 206*c8dee2aaSAndroid Build Coastguard Worker }; 207*c8dee2aaSAndroid Build Coastguard Worker 208*c8dee2aaSAndroid Build Coastguard Worker 209*c8dee2aaSAndroid Build Coastguard Worker /** 210*c8dee2aaSAndroid Build Coastguard Worker * This GM directly exercises effects that draw Bezier curves in the GPU backend. 211*c8dee2aaSAndroid Build Coastguard Worker */ 212*c8dee2aaSAndroid Build Coastguard Worker class BezierConicEffects : public GpuGM { 213*c8dee2aaSAndroid Build Coastguard Worker public: BezierConicEffects()214*c8dee2aaSAndroid Build Coastguard Worker BezierConicEffects() { 215*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(0xFFFFFFFF); 216*c8dee2aaSAndroid Build Coastguard Worker } 217*c8dee2aaSAndroid Build Coastguard Worker 218*c8dee2aaSAndroid Build Coastguard Worker protected: 219*c8dee2aaSAndroid Build Coastguard Worker static const int kNumConics = 10; 220*c8dee2aaSAndroid Build Coastguard Worker static const int kCellWidth = 128; 221*c8dee2aaSAndroid Build Coastguard Worker static const int kCellHeight = 128; 222*c8dee2aaSAndroid Build Coastguard Worker getName() const223*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("bezier_conic_effects"); } 224*c8dee2aaSAndroid Build Coastguard Worker getISize()225*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kCellWidth, kNumConics * kCellHeight); } 226*c8dee2aaSAndroid Build Coastguard Worker onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)227*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override { 228*c8dee2aaSAndroid Build Coastguard Worker auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas); 229*c8dee2aaSAndroid Build Coastguard Worker if (!sdc) { 230*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = kErrorMsg_DrawSkippedGpuOnly; 231*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip; 232*c8dee2aaSAndroid Build Coastguard Worker } 233*c8dee2aaSAndroid Build Coastguard Worker 234*c8dee2aaSAndroid Build Coastguard Worker const SkScalar w = kCellWidth, h = kCellHeight; 235*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000); 236*c8dee2aaSAndroid Build Coastguard Worker 237*c8dee2aaSAndroid Build Coastguard Worker const SkPoint baseControlPts[kNumConics][3] = { 238*c8dee2aaSAndroid Build Coastguard Worker { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } }, 239*c8dee2aaSAndroid Build Coastguard Worker { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } }, 240*c8dee2aaSAndroid Build Coastguard Worker { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } }, 241*c8dee2aaSAndroid Build Coastguard Worker { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } }, 242*c8dee2aaSAndroid Build Coastguard Worker { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } }, 243*c8dee2aaSAndroid Build Coastguard Worker { { 0.96f * w, 0.65f * h}, { 0.03f * w, 0.79f * h }, { 0.24f * w, 0.56f * h } }, 244*c8dee2aaSAndroid Build Coastguard Worker { { 0.57f * w, 0.12f * h}, { 0.33f * w, 0.67f * h }, { 0.59f * w, 0.33f * h } }, 245*c8dee2aaSAndroid Build Coastguard Worker { { 0.12f * w, 0.72f * h}, { 0.69f * w, 0.85f * h }, { 0.46f * w, 0.32f * h } }, 246*c8dee2aaSAndroid Build Coastguard Worker { { 0.27f * w, 0.49f * h}, { 0.41f * w, 0.02f * h }, { 0.11f * w, 0.42f * h } }, 247*c8dee2aaSAndroid Build Coastguard Worker { { 0.40f * w, 0.13f * h}, { 0.83f * w, 0.30f * h }, { 0.31f * w, 0.68f * h } }, 248*c8dee2aaSAndroid Build Coastguard Worker }; 249*c8dee2aaSAndroid Build Coastguard Worker const SkScalar weights[kNumConics] = { 0.62f, 0.01f, 0.95f, 1.48f, 0.37f, 250*c8dee2aaSAndroid Build Coastguard Worker 0.66f, 0.15f, 0.14f, 0.61f, 1.4f }; 251*c8dee2aaSAndroid Build Coastguard Worker 252*c8dee2aaSAndroid Build Coastguard Worker SkPaint ctrlPtPaint; 253*c8dee2aaSAndroid Build Coastguard Worker ctrlPtPaint.setColor(SK_ColorRED); 254*c8dee2aaSAndroid Build Coastguard Worker 255*c8dee2aaSAndroid Build Coastguard Worker SkPaint choppedPtPaint; 256*c8dee2aaSAndroid Build Coastguard Worker choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 257*c8dee2aaSAndroid Build Coastguard Worker 258*c8dee2aaSAndroid Build Coastguard Worker SkPaint polyPaint; 259*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setColor(0xffA0A0A0); 260*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setStrokeWidth(0); 261*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setStyle(SkPaint::kStroke_Style); 262*c8dee2aaSAndroid Build Coastguard Worker 263*c8dee2aaSAndroid Build Coastguard Worker SkPaint boundsPaint; 264*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setColor(0xff808080); 265*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setStrokeWidth(0); 266*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setStyle(SkPaint::kStroke_Style); 267*c8dee2aaSAndroid Build Coastguard Worker 268*c8dee2aaSAndroid Build Coastguard Worker 269*c8dee2aaSAndroid Build Coastguard Worker for (int row = 0; row < kNumConics; ++row) { 270*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = 0; 271*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = row * h; 272*c8dee2aaSAndroid Build Coastguard Worker SkPoint controlPts[] = { 273*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY}, 274*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY}, 275*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY} 276*c8dee2aaSAndroid Build Coastguard Worker }; 277*c8dee2aaSAndroid Build Coastguard Worker 278*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) { 279*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint); 280*c8dee2aaSAndroid Build Coastguard Worker } 281*c8dee2aaSAndroid Build Coastguard Worker 282*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 283*c8dee2aaSAndroid Build Coastguard Worker 284*c8dee2aaSAndroid Build Coastguard Worker SkConic dst[4]; 285*c8dee2aaSAndroid Build Coastguard Worker SkMatrix klm; 286*c8dee2aaSAndroid Build Coastguard Worker int cnt = ChopConic(controlPts, dst, weights[row]); 287*c8dee2aaSAndroid Build Coastguard Worker GrPathUtils::getConicKLM(controlPts, weights[row], &klm); 288*c8dee2aaSAndroid Build Coastguard Worker 289*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < cnt; ++c) { 290*c8dee2aaSAndroid Build Coastguard Worker SkPoint* pts = dst[c].fPts; 291*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) { 292*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(pts[i], 3.f, choppedPtPaint); 293*c8dee2aaSAndroid Build Coastguard Worker } 294*c8dee2aaSAndroid Build Coastguard Worker 295*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds; 296*c8dee2aaSAndroid Build Coastguard Worker bounds.setBounds(pts, 3); 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(bounds, boundsPaint); 299*c8dee2aaSAndroid Build Coastguard Worker 300*c8dee2aaSAndroid Build Coastguard Worker GrOp::Owner op = BezierConicTestOp::Make(rContext, bounds, 301*c8dee2aaSAndroid Build Coastguard Worker kOpaqueBlack, klm); 302*c8dee2aaSAndroid Build Coastguard Worker sdc->addDrawOp(std::move(op)); 303*c8dee2aaSAndroid Build Coastguard Worker } 304*c8dee2aaSAndroid Build Coastguard Worker } 305*c8dee2aaSAndroid Build Coastguard Worker 306*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 307*c8dee2aaSAndroid Build Coastguard Worker } 308*c8dee2aaSAndroid Build Coastguard Worker 309*c8dee2aaSAndroid Build Coastguard Worker private: 310*c8dee2aaSAndroid Build Coastguard Worker // Uses the max curvature function for quads to estimate 311*c8dee2aaSAndroid Build Coastguard Worker // where to chop the conic. If the max curvature is not 312*c8dee2aaSAndroid Build Coastguard Worker // found along the curve segment it will return 1 and 313*c8dee2aaSAndroid Build Coastguard Worker // dst[0] is the original conic. If it returns 2 the dst[0] 314*c8dee2aaSAndroid Build Coastguard Worker // and dst[1] are the two new conics. SplitConic(const SkPoint src[3],SkConic dst[2],const SkScalar weight)315*c8dee2aaSAndroid Build Coastguard Worker static int SplitConic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 316*c8dee2aaSAndroid Build Coastguard Worker SkScalar t = SkFindQuadMaxCurvature(src); 317*c8dee2aaSAndroid Build Coastguard Worker if (t == 0 || t == 1) { 318*c8dee2aaSAndroid Build Coastguard Worker if (dst) { 319*c8dee2aaSAndroid Build Coastguard Worker dst[0].set(src, weight); 320*c8dee2aaSAndroid Build Coastguard Worker } 321*c8dee2aaSAndroid Build Coastguard Worker return 1; 322*c8dee2aaSAndroid Build Coastguard Worker } else { 323*c8dee2aaSAndroid Build Coastguard Worker if (dst) { 324*c8dee2aaSAndroid Build Coastguard Worker SkConic conic; 325*c8dee2aaSAndroid Build Coastguard Worker conic.set(src, weight); 326*c8dee2aaSAndroid Build Coastguard Worker if (!conic.chopAt(t, dst)) { 327*c8dee2aaSAndroid Build Coastguard Worker dst[0].set(src, weight); 328*c8dee2aaSAndroid Build Coastguard Worker return 1; 329*c8dee2aaSAndroid Build Coastguard Worker } 330*c8dee2aaSAndroid Build Coastguard Worker } 331*c8dee2aaSAndroid Build Coastguard Worker return 2; 332*c8dee2aaSAndroid Build Coastguard Worker } 333*c8dee2aaSAndroid Build Coastguard Worker } 334*c8dee2aaSAndroid Build Coastguard Worker 335*c8dee2aaSAndroid Build Coastguard Worker // Calls SplitConic on the entire conic and then once more on each subsection. 336*c8dee2aaSAndroid Build Coastguard Worker // Most cases will result in either 1 conic (chop point is not within t range) 337*c8dee2aaSAndroid Build Coastguard Worker // or 3 points (split once and then one subsection is split again). ChopConic(const SkPoint src[3],SkConic dst[4],const SkScalar weight)338*c8dee2aaSAndroid Build Coastguard Worker static int ChopConic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 339*c8dee2aaSAndroid Build Coastguard Worker SkConic dstTemp[2]; 340*c8dee2aaSAndroid Build Coastguard Worker int conicCnt = SplitConic(src, dstTemp, weight); 341*c8dee2aaSAndroid Build Coastguard Worker if (2 == conicCnt) { 342*c8dee2aaSAndroid Build Coastguard Worker int conicCnt2 = SplitConic(dstTemp[0].fPts, dst, dstTemp[0].fW); 343*c8dee2aaSAndroid Build Coastguard Worker conicCnt = conicCnt2 + SplitConic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW); 344*c8dee2aaSAndroid Build Coastguard Worker } else { 345*c8dee2aaSAndroid Build Coastguard Worker dst[0] = dstTemp[0]; 346*c8dee2aaSAndroid Build Coastguard Worker } 347*c8dee2aaSAndroid Build Coastguard Worker return conicCnt; 348*c8dee2aaSAndroid Build Coastguard Worker } 349*c8dee2aaSAndroid Build Coastguard Worker 350*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM; 351*c8dee2aaSAndroid Build Coastguard Worker }; 352*c8dee2aaSAndroid Build Coastguard Worker 353*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////// 354*c8dee2aaSAndroid Build Coastguard Worker 355*c8dee2aaSAndroid Build Coastguard Worker class BezierQuadTestOp : public BezierTestOp { 356*c8dee2aaSAndroid Build Coastguard Worker public: 357*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID name() const358*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "BezierQuadTestOp"; } 359*c8dee2aaSAndroid Build Coastguard Worker Make(GrRecordingContext * context,const SkRect & rect,const SkPMColor4f & color,const GrPathUtils::QuadUVMatrix & devToUV)360*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* context, 361*c8dee2aaSAndroid Build Coastguard Worker const SkRect& rect, 362*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& color, 363*c8dee2aaSAndroid Build Coastguard Worker const GrPathUtils::QuadUVMatrix& devToUV) { 364*c8dee2aaSAndroid Build Coastguard Worker return GrOp::Make<BezierQuadTestOp>(context, rect, color, devToUV); 365*c8dee2aaSAndroid Build Coastguard Worker } 366*c8dee2aaSAndroid Build Coastguard Worker 367*c8dee2aaSAndroid Build Coastguard Worker private: 368*c8dee2aaSAndroid Build Coastguard Worker friend class ::GrOp; // for ctor 369*c8dee2aaSAndroid Build Coastguard Worker BezierQuadTestOp(const SkRect & rect,const SkPMColor4f & color,const GrPathUtils::QuadUVMatrix & devToUV)370*c8dee2aaSAndroid Build Coastguard Worker BezierQuadTestOp(const SkRect& rect, const SkPMColor4f& color, 371*c8dee2aaSAndroid Build Coastguard Worker const GrPathUtils::QuadUVMatrix& devToUV) 372*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(rect, color, ClassID()) 373*c8dee2aaSAndroid Build Coastguard Worker , fDevToUV(devToUV) {} 374*c8dee2aaSAndroid Build Coastguard Worker 375*c8dee2aaSAndroid Build Coastguard Worker struct Vertex { 376*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPosition; 377*c8dee2aaSAndroid Build Coastguard Worker float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 378*c8dee2aaSAndroid Build Coastguard Worker }; 379*c8dee2aaSAndroid Build Coastguard Worker makeGP(const GrCaps & caps,SkArenaAlloc * arena)380*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final { 381*c8dee2aaSAndroid Build Coastguard Worker auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(), 382*c8dee2aaSAndroid Build Coastguard Worker false); 383*c8dee2aaSAndroid Build Coastguard Worker if (!tmp) { 384*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 385*c8dee2aaSAndroid Build Coastguard Worker } 386*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tmp->vertexStride() == sizeof(Vertex)); 387*c8dee2aaSAndroid Build Coastguard Worker return tmp; 388*c8dee2aaSAndroid Build Coastguard Worker } 389*c8dee2aaSAndroid Build Coastguard Worker onPrepareDraws(GrMeshDrawTarget * target)390*c8dee2aaSAndroid Build Coastguard Worker void onPrepareDraws(GrMeshDrawTarget* target) final { 391*c8dee2aaSAndroid Build Coastguard Worker QuadHelper helper(target, sizeof(Vertex), 1); 392*c8dee2aaSAndroid Build Coastguard Worker Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices()); 393*c8dee2aaSAndroid Build Coastguard Worker if (!verts) { 394*c8dee2aaSAndroid Build Coastguard Worker return; 395*c8dee2aaSAndroid Build Coastguard Worker } 396*c8dee2aaSAndroid Build Coastguard Worker SkRect rect = this->rect(); 397*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex)); 398*c8dee2aaSAndroid Build Coastguard Worker fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint)); 399*c8dee2aaSAndroid Build Coastguard Worker 400*c8dee2aaSAndroid Build Coastguard Worker fMesh = helper.mesh(); 401*c8dee2aaSAndroid Build Coastguard Worker } 402*c8dee2aaSAndroid Build Coastguard Worker 403*c8dee2aaSAndroid Build Coastguard Worker GrPathUtils::QuadUVMatrix fDevToUV; 404*c8dee2aaSAndroid Build Coastguard Worker 405*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kVertsPerCubic = 4; 406*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kIndicesPerCubic = 6; 407*c8dee2aaSAndroid Build Coastguard Worker 408*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = BezierTestOp; 409*c8dee2aaSAndroid Build Coastguard Worker }; 410*c8dee2aaSAndroid Build Coastguard Worker 411*c8dee2aaSAndroid Build Coastguard Worker /** 412*c8dee2aaSAndroid Build Coastguard Worker * This GM directly exercises effects that draw Bezier quad curves in the GPU backend. 413*c8dee2aaSAndroid Build Coastguard Worker */ 414*c8dee2aaSAndroid Build Coastguard Worker class BezierQuadEffects : public GpuGM { 415*c8dee2aaSAndroid Build Coastguard Worker public: BezierQuadEffects()416*c8dee2aaSAndroid Build Coastguard Worker BezierQuadEffects() { 417*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(0xFFFFFFFF); 418*c8dee2aaSAndroid Build Coastguard Worker } 419*c8dee2aaSAndroid Build Coastguard Worker 420*c8dee2aaSAndroid Build Coastguard Worker protected: 421*c8dee2aaSAndroid Build Coastguard Worker static const int kNumQuads = 5; 422*c8dee2aaSAndroid Build Coastguard Worker static const int kCellWidth = 128; 423*c8dee2aaSAndroid Build Coastguard Worker static const int kCellHeight = 128; 424*c8dee2aaSAndroid Build Coastguard Worker getName() const425*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("bezier_quad_effects"); } 426*c8dee2aaSAndroid Build Coastguard Worker getISize()427*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kCellWidth, kNumQuads * kCellHeight); } 428*c8dee2aaSAndroid Build Coastguard Worker onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)429*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override { 430*c8dee2aaSAndroid Build Coastguard Worker auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas); 431*c8dee2aaSAndroid Build Coastguard Worker if (!sdc) { 432*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = kErrorMsg_DrawSkippedGpuOnly; 433*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip; 434*c8dee2aaSAndroid Build Coastguard Worker } 435*c8dee2aaSAndroid Build Coastguard Worker 436*c8dee2aaSAndroid Build Coastguard Worker const SkScalar w = kCellWidth, h = kCellHeight; 437*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000); 438*c8dee2aaSAndroid Build Coastguard Worker 439*c8dee2aaSAndroid Build Coastguard Worker const SkPoint baseControlPts[kNumQuads][3] = { 440*c8dee2aaSAndroid Build Coastguard Worker { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } }, 441*c8dee2aaSAndroid Build Coastguard Worker { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } }, 442*c8dee2aaSAndroid Build Coastguard Worker { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } }, 443*c8dee2aaSAndroid Build Coastguard Worker { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } }, 444*c8dee2aaSAndroid Build Coastguard Worker { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } }, 445*c8dee2aaSAndroid Build Coastguard Worker }; 446*c8dee2aaSAndroid Build Coastguard Worker 447*c8dee2aaSAndroid Build Coastguard Worker SkPaint ctrlPtPaint; 448*c8dee2aaSAndroid Build Coastguard Worker ctrlPtPaint.setColor(SK_ColorRED); 449*c8dee2aaSAndroid Build Coastguard Worker 450*c8dee2aaSAndroid Build Coastguard Worker SkPaint choppedPtPaint; 451*c8dee2aaSAndroid Build Coastguard Worker choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 452*c8dee2aaSAndroid Build Coastguard Worker 453*c8dee2aaSAndroid Build Coastguard Worker SkPaint polyPaint; 454*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setColor(0xffA0A0A0); 455*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setStrokeWidth(0); 456*c8dee2aaSAndroid Build Coastguard Worker polyPaint.setStyle(SkPaint::kStroke_Style); 457*c8dee2aaSAndroid Build Coastguard Worker 458*c8dee2aaSAndroid Build Coastguard Worker SkPaint boundsPaint; 459*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setColor(0xff808080); 460*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setStrokeWidth(0); 461*c8dee2aaSAndroid Build Coastguard Worker boundsPaint.setStyle(SkPaint::kStroke_Style); 462*c8dee2aaSAndroid Build Coastguard Worker 463*c8dee2aaSAndroid Build Coastguard Worker for (int row = 0; row < kNumQuads; ++row) { 464*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = 0; 465*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = row * h; 466*c8dee2aaSAndroid Build Coastguard Worker SkPoint controlPts[] = { 467*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY}, 468*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY}, 469*c8dee2aaSAndroid Build Coastguard Worker {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY} 470*c8dee2aaSAndroid Build Coastguard Worker }; 471*c8dee2aaSAndroid Build Coastguard Worker 472*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) { 473*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint); 474*c8dee2aaSAndroid Build Coastguard Worker } 475*c8dee2aaSAndroid Build Coastguard Worker 476*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 477*c8dee2aaSAndroid Build Coastguard Worker 478*c8dee2aaSAndroid Build Coastguard Worker SkPoint chopped[5]; 479*c8dee2aaSAndroid Build Coastguard Worker int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped); 480*c8dee2aaSAndroid Build Coastguard Worker 481*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < cnt; ++c) { 482*c8dee2aaSAndroid Build Coastguard Worker SkPoint* pts = chopped + 2 * c; 483*c8dee2aaSAndroid Build Coastguard Worker 484*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) { 485*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(pts[i], 3.f, choppedPtPaint); 486*c8dee2aaSAndroid Build Coastguard Worker } 487*c8dee2aaSAndroid Build Coastguard Worker 488*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds; 489*c8dee2aaSAndroid Build Coastguard Worker bounds.setBounds(pts, 3); 490*c8dee2aaSAndroid Build Coastguard Worker 491*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(bounds, boundsPaint); 492*c8dee2aaSAndroid Build Coastguard Worker 493*c8dee2aaSAndroid Build Coastguard Worker GrPathUtils::QuadUVMatrix DevToUV(pts); 494*c8dee2aaSAndroid Build Coastguard Worker 495*c8dee2aaSAndroid Build Coastguard Worker GrOp::Owner op = BezierQuadTestOp::Make(rContext, bounds, 496*c8dee2aaSAndroid Build Coastguard Worker kOpaqueBlack, DevToUV); 497*c8dee2aaSAndroid Build Coastguard Worker sdc->addDrawOp(std::move(op)); 498*c8dee2aaSAndroid Build Coastguard Worker } 499*c8dee2aaSAndroid Build Coastguard Worker } 500*c8dee2aaSAndroid Build Coastguard Worker 501*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 502*c8dee2aaSAndroid Build Coastguard Worker } 503*c8dee2aaSAndroid Build Coastguard Worker 504*c8dee2aaSAndroid Build Coastguard Worker private: 505*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM; 506*c8dee2aaSAndroid Build Coastguard Worker }; 507*c8dee2aaSAndroid Build Coastguard Worker 508*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new BezierConicEffects;) 509*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new BezierQuadEffects;) 510*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm 511