178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org/*
278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org * Copyright 2013 Google Inc.
378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org *
478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org * found in the LICENSE file.
678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org */
778a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
878a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org// This test only works with the GPU backend.
978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
1078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#include "gm.h"
1178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
1253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org#if SK_SUPPORT_GPU
1378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
1478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#include "GrContext.h"
15477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon#include "GrOpFlushState.h"
1678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#include "GrPathUtils.h"
17477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon#include "GrRenderTargetContextPriv.h"
1878a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#include "GrTest.h"
1978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#include "SkColorPriv.h"
2053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org#include "SkGeometry.h"
21e4442cb0b537720ab32106b3b5353dbb78f11b26Cary Clark#include "SkPoint3.h"
2274f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark#include "SkPointPriv.h"
2353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org#include "effects/GrBezierEffect.h"
24477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon#include "ops/GrMeshDrawOp.h"
2578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
2678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.orgnamespace skiagm {
2795964c670b577d5f49c5eab7af277ad987fd0519joshualitt
28477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonclass BezierTestOp : public GrMeshDrawOp {
29477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonpublic:
30477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
31477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
329a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
339a725dd9485654155e2e4196c32d372360bcdb61Brian Osman                                GrPixelConfigIsClamped dstIsClamped) override {
34477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        auto analysis = fProcessorSet.finalize(fColor, GrProcessorAnalysisCoverage::kSingleChannel,
359a725dd9485654155e2e4196c32d372360bcdb61Brian Osman                                               clip, false, caps, dstIsClamped, &fColor);
36477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
37477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    }
38477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
39f1748f5a9238a0d3e189d50fc5e57ae8b8ec087cRobert Phillips    void visitProxies(const VisitProxyFunc& func) const override {
40b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips        fProcessorSet.visitProxies(func);
41b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips    }
42b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips
43477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonprotected:
44477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    BezierTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color, int32_t classID)
45477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            : INHERITED(classID)
46477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            , fRect(rect)
47477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            , fColor(color)
48477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            , fGeometryProcessor(std::move(gp))
49477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            , fProcessorSet(SkBlendMode::kSrc) {
50477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
51477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    }
52477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
5391326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    const GrPipeline* makePipeline(Target* target) {
54bfd18cdd5421b6fac063bd07a96a5b9b1afa6a88Brian Salomon        return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip());
55477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    }
56477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
57477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    const GrGeometryProcessor* gp() const { return fGeometryProcessor.get(); }
58477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
59477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    const SkRect& rect() const { return fRect; }
60477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    GrColor color() const { return fColor; }
61477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
62477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonprivate:
63477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    bool onCombineIfPossible(GrOp* op, const GrCaps& caps) override { return false; }
64477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
65477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    SkRect fRect;
66477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    GrColor fColor;
67477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    sk_sp<GrGeometryProcessor> fGeometryProcessor;
68477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    GrProcessorSet fProcessorSet;
69477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
70477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    typedef GrMeshDrawOp INHERITED;
71477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon};
72477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
73477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonclass BezierCubicTestOp : public BezierTestOp {
7495964c670b577d5f49c5eab7af277ad987fd0519joshualittpublic:
7525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
7695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
77febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    const char* name() const override { return "BezierCubicTestOp"; }
7895964c670b577d5f49c5eab7af277ad987fd0519joshualitt
79477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
80477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                                          GrColor color) {
81477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        return std::unique_ptr<GrDrawOp>(new BezierCubicTestOp(std::move(gp), rect, color));
826b316e9e20d67f0f13021ca62f4270105c6151b1Brian Salomon    }
836b316e9e20d67f0f13021ca62f4270105c6151b1Brian Salomon
846b316e9e20d67f0f13021ca62f4270105c6151b1Brian Salomonprivate:
85febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    BezierCubicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
86477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            : INHERITED(std::move(gp), rect, color, ClassID()) {}
8795964c670b577d5f49c5eab7af277ad987fd0519joshualitt
8891326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    void onPrepareDraws(Target* target) override {
89b5238a7571c243ba4a154a62575570c3078b3741bsalomon        QuadHelper helper;
90477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        size_t vertexStride = this->gp()->getVertexStride();
91febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        SkASSERT(vertexStride == sizeof(SkPoint));
92febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        SkPoint* pts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
93febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        if (!pts) {
944b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            return;
954b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt        }
96477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        SkRect rect = this->rect();
9774f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark        SkPointPriv::SetRectTriStrip(pts, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
98477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        helper.recordDraw(target, this->gp(), this->makePipeline(target));
9995964c670b577d5f49c5eab7af277ad987fd0519joshualitt    }
10095964c670b577d5f49c5eab7af277ad987fd0519joshualitt
101dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kVertsPerCubic = 4;
102dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kIndicesPerCubic = 6;
10395964c670b577d5f49c5eab7af277ad987fd0519joshualitt
104477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    typedef BezierTestOp INHERITED;
10595964c670b577d5f49c5eab7af277ad987fd0519joshualitt};
10695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
10778a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org/**
10878a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org * This GM directly exercises effects that draw Bezier curves in the GPU backend.
10978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org */
11053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgclass BezierCubicEffects : public GM {
11178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.orgpublic:
11253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    BezierCubicEffects() {
11378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        this->setBGColor(0xFFFFFFFF);
11478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org    }
11578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
11678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.orgprotected:
11736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
11853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        return SkString("bezier_cubic_effects");
11978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org    }
12078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
12136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override {
122f539318f0d3dba743ec1886d5d9df0fb1be628a1tfarina        return SkISize::Make(800, 800);
12378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org    }
12478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
12536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
1261105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        GrRenderTargetContext* renderTargetContext =
1271105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman            canvas->internal_private_accessTopLayerRenderTargetContext();
1281105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        if (!renderTargetContext) {
1292a24338c777462e04a2b26295f9c034155ee8f3ehalcanary            skiagm::GM::DrawGpuOnlyMessage(canvas);
13078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            return;
13178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        }
13278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
133175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        GrContext* context = canvas->getGrContext();
134175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        if (!context) {
135f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt            return;
136f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt        }
137f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt
13878a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        struct Vertex {
13978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            SkPoint fPosition;
14078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            float   fKLM[4]; // The last value is ignored. The effect expects a vec4f.
14178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        };
14278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
143dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kNumCubics = 15;
144e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org        SkRandom rand;
14578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
14653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        // Mult by 3 for each edge effect type
14753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
14853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
1491105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
1501105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
15178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        int row = 0;
15278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        int col = 0;
153dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr GrColor color = 0xff000000;
15478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
15578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        for (int i = 0; i < kNumCubics; ++i) {
15653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkPoint baseControlPts[] = {
15753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
15853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
15953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
16053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
16178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            };
1621706f842086c089ebc496dfc7f45c959e5eda01eEthan Nicholas            for(GrClipEdgeType edgeType : {GrClipEdgeType::kFillBW,
1631706f842086c089ebc496dfc7f45c959e5eda01eEthan Nicholas                                           GrClipEdgeType::kFillAA,
1641706f842086c089ebc496dfc7f45c959e5eda01eEthan Nicholas                                           GrClipEdgeType::kHairlineAA}) {
165df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar x = col * w;
166df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar y = row * h;
16753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPoint controlPts[] = {
16853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
16953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
17053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
17153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
17253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                };
17353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPoint chopped[10];
174cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton                SkMatrix klm;
1758199d94c0812a05320064f5f864b4208ffb25dbaGreg Daniel                int loopIndex;
17653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
17753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                                                                   chopped,
178cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton                                                                   &klm,
1798199d94c0812a05320064f5f864b4208ffb25dbaGreg Daniel                                                                   &loopIndex);
18053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
18153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint ctrlPtPaint;
18253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
18323e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
1848199d94c0812a05320064f5f864b4208ffb25dbaGreg Daniel                for (int i = 1; i < 4; ++i) {
18523e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                    canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
18653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
18753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
18853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint polyPaint;
18953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setColor(0xffA0A0A0);
19053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStrokeWidth(0);
19153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStyle(SkPaint::kStroke_Style);
19253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
19353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
19453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint choppedPtPaint;
19553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
19653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
19753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                for (int c = 0; c < cnt; ++c) {
19853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPoint* pts = chopped + 3 * c;
19953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
20053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    for (int i = 0; i < 4; ++i) {
20123e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                        canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
20253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    }
20353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
20453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkRect bounds;
20553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    bounds.set(pts, 4);
20653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
20753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPaint boundsPaint;
20853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setColor(0xff808080);
20953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStrokeWidth(0);
21053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStyle(SkPaint::kStroke_Style);
21153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    canvas->drawRect(bounds, boundsPaint);
21253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
21350408adfd23994cdbb5c531ff6366e4e9d29ee6djoshualitt
214febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                    bool flipKL = (c == loopIndex && cnt != 3);
215febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                    sk_sp<GrGeometryProcessor> gp = GrCubicEffect::Make(color, SkMatrix::I(), klm,
216febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                                                                        flipKL, edgeType,
217febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                                                                        *context->caps());
218febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                    if (!gp) {
219febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                        break;
2208199d94c0812a05320064f5f864b4208ffb25dbaGreg Daniel                    }
2218199d94c0812a05320064f5f864b4208ffb25dbaGreg Daniel
222477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    std::unique_ptr<GrDrawOp> op =
223febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                            BezierCubicTestOp::Make(std::move(gp), bounds, color);
224477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
22553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
22653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ++col;
22753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                if (numCols == col) {
22853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    col = 0;
22953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    ++row;
23053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
23178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            }
23253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
23353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
23478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
23553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgprivate:
23653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    typedef GM INHERITED;
23753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org};
23853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
23953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
24053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
241477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonclass BezierConicTestOp : public BezierTestOp {
242febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Daltonpublic:
243febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    DEFINE_OP_CLASS_ID
244febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
245febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    const char* name() const override { return "BezierConicTestOp"; }
246febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
247477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
248477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                                          GrColor color, const SkMatrix& klm) {
249477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        return std::unique_ptr<GrMeshDrawOp>(
250477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                new BezierConicTestOp(std::move(gp), rect, color, klm));
251febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    }
252febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
253febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Daltonprivate:
254febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    BezierConicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
255febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                      const SkMatrix& klm)
256477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
257477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon
258febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    struct Vertex {
259febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        SkPoint fPosition;
260febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        float   fKLM[4]; // The last value is ignored. The effect expects a vec4f.
261febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    };
262febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
26391326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    void onPrepareDraws(Target* target) override {
264febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        QuadHelper helper;
265477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        size_t vertexStride = this->gp()->getVertexStride();
266febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        SkASSERT(vertexStride == sizeof(Vertex));
267febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
268febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        if (!verts) {
269febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton            return;
270febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        }
271477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        SkRect rect = this->rect();
27274f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark        SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
27374f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark                                     rect.fBottom, sizeof(Vertex));
274febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        for (int v = 0; v < 4; ++v) {
275e4442cb0b537720ab32106b3b5353dbb78f11b26Cary Clark            SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
276e4442cb0b537720ab32106b3b5353dbb78f11b26Cary Clark            fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
277febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton        }
278477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        helper.recordDraw(target, this->gp(), this->makePipeline(target));
279febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    }
280febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
281febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    SkMatrix fKLM;
282febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
283febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    static constexpr int kVertsPerCubic = 4;
284febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    static constexpr int kIndicesPerCubic = 6;
285febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
286477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    typedef BezierTestOp INHERITED;
287febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton};
288febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
289febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
29053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org/**
29153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org * This GM directly exercises effects that draw Bezier curves in the GPU backend.
29253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org */
29353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgclass BezierConicEffects : public GM {
29453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgpublic:
29553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    BezierConicEffects() {
29653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        this->setBGColor(0xFFFFFFFF);
29753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
29878a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
29953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgprotected:
30036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
30153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        return SkString("bezier_conic_effects");
30253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
30378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
30436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override {
305f539318f0d3dba743ec1886d5d9df0fb1be628a1tfarina        return SkISize::Make(800, 800);
30653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
30778a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
30853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
30936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
3101105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        GrRenderTargetContext* renderTargetContext =
3111105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman            canvas->internal_private_accessTopLayerRenderTargetContext();
3121105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        if (!renderTargetContext) {
3132a24338c777462e04a2b26295f9c034155ee8f3ehalcanary            skiagm::GM::DrawGpuOnlyMessage(canvas);
31453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            return;
31553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
31653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
317175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        GrContext* context = canvas->getGrContext();
318175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        if (!context) {
319f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt            return;
320f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt        }
321f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt
32253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        struct Vertex {
32353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkPoint fPosition;
32453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            float   fKLM[4]; // The last value is ignored. The effect expects a vec4f.
32553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        };
32678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
327dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kNumConics = 10;
328e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org        SkRandom rand;
32953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
33053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        // Mult by 3 for each edge effect type
33153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
33253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
3331105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
3341105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
33553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int row = 0;
33653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int col = 0;
337dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr GrColor color = 0xff000000;
33853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
33953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        for (int i = 0; i < kNumConics; ++i) {
34053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkPoint baseControlPts[] = {
34153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
34253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
34353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
34453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            };
34553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkScalar weight = rand.nextRangeF(0.f, 2.f);
3461706f842086c089ebc496dfc7f45c959e5eda01eEthan Nicholas            for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
34706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                sk_sp<GrGeometryProcessor> gp;
3480f3c73220a25eba9bf11583db3d0f76a2c4f6331Ethan Nicholas                GrClipEdgeType et = (GrClipEdgeType)edgeType;
34906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                gp = GrConicEffect::Make(color, SkMatrix::I(), et,
35006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                         *context->caps(), SkMatrix::I(), false);
351f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt                if (!gp) {
352f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt                    continue;
353cabf4b2f3664b98c1084fbb94a999af15ddfb52dcommit-bot@chromium.org                }
354cabf4b2f3664b98c1084fbb94a999af15ddfb52dcommit-bot@chromium.org
355df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar x = col * w;
356df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar y = row * h;
35753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPoint controlPts[] = {
35853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
35953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
36053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
36153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                };
36253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkConic dst[4];
363cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton                SkMatrix klm;
36453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                int cnt = chop_conic(controlPts, dst, weight);
365cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton                GrPathUtils::getConicKLM(controlPts, weight, &klm);
36653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
36753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint ctrlPtPaint;
36853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
36953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                for (int i = 0; i < 3; ++i) {
37023e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                    canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
37178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org                }
37278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
37353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint polyPaint;
37453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setColor(0xffA0A0A0);
37553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStrokeWidth(0);
37653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStyle(SkPaint::kStroke_Style);
37753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
37853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
37953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint choppedPtPaint;
38053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
38153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
38253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                for (int c = 0; c < cnt; ++c) {
38353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPoint* pts = dst[c].fPts;
38453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    for (int i = 0; i < 3; ++i) {
38523e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                        canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
38653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    }
38753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
38853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkRect bounds;
38953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
39053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    //bounds.set(bPts, 2);
39153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    bounds.set(pts, 3);
39253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
39353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPaint boundsPaint;
39453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setColor(0xff808080);
39553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStrokeWidth(0);
39653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStyle(SkPaint::kStroke_Style);
39753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    canvas->drawRect(bounds, boundsPaint);
39853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
399477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(gp, bounds, color, klm);
400477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
40178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org                }
40253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ++col;
40353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                if (numCols == col) {
40453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    col = 0;
40553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    ++row;
40678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org                }
40753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            }
40853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
40953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
41078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
41153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgprivate:
41253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // Uses the max curvature function for quads to estimate
41353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // where to chop the conic. If the max curvature is not
41453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // found along the curve segment it will return 1 and
41553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // dst[0] is the original conic. If it returns 2 the dst[0]
41653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // and dst[1] are the two new conics.
41753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
41853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        SkScalar t = SkFindQuadMaxCurvature(src);
41953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        if (t == 0) {
42053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            if (dst) {
42153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                dst[0].set(src, weight);
42278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            }
42353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            return 1;
42453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        } else {
42553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            if (dst) {
42653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkConic conic;
42753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                conic.set(src, weight);
428414c4295f951d43068666b6294df15b2fd2ba85ccaryclark                if (!conic.chopAt(t, dst)) {
429414c4295f951d43068666b6294df15b2fd2ba85ccaryclark                    dst[0].set(src, weight);
430414c4295f951d43068666b6294df15b2fd2ba85ccaryclark                    return 1;
431414c4295f951d43068666b6294df15b2fd2ba85ccaryclark                }
43278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org            }
43353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            return 2;
43478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org        }
43578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org    }
43678a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
43753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // Calls split_conic on the entire conic and then once more on each subsection.
43853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // Most cases will result in either 1 conic (chop point is not within t range)
43953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    // or 3 points (split once and then one subsection is split again).
44053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
44153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        SkConic dstTemp[2];
44253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int conicCnt = split_conic(src, dstTemp, weight);
44353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        if (2 == conicCnt) {
44453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
44553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
44653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        } else {
44753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            dst[0] = dstTemp[0];
44853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
44953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        return conicCnt;
45053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
45153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
45278a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org    typedef GM INHERITED;
45378a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org};
45478a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
45578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
45695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
457477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomonclass BezierQuadTestOp : public BezierTestOp {
45895964c670b577d5f49c5eab7af277ad987fd0519joshualittpublic:
45925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
4606b316e9e20d67f0f13021ca62f4270105c6151b1Brian Salomon    const char* name() const override { return "BezierQuadTestOp"; }
46195964c670b577d5f49c5eab7af277ad987fd0519joshualitt
462477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
463477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                                          GrColor color, const GrPathUtils::QuadUVMatrix& devToUV) {
464477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        return std::unique_ptr<GrDrawOp>(new BezierQuadTestOp(std::move(gp), rect, color, devToUV));
46595964c670b577d5f49c5eab7af277ad987fd0519joshualitt    }
46695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
46795964c670b577d5f49c5eab7af277ad987fd0519joshualittprivate:
4689e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    BezierQuadTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
4696b316e9e20d67f0f13021ca62f4270105c6151b1Brian Salomon                     const GrPathUtils::QuadUVMatrix& devToUV)
470477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon            : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
47195964c670b577d5f49c5eab7af277ad987fd0519joshualitt
47295964c670b577d5f49c5eab7af277ad987fd0519joshualitt    struct Vertex {
47395964c670b577d5f49c5eab7af277ad987fd0519joshualitt        SkPoint fPosition;
47495964c670b577d5f49c5eab7af277ad987fd0519joshualitt        float   fKLM[4]; // The last value is ignored. The effect expects a vec4f.
47595964c670b577d5f49c5eab7af277ad987fd0519joshualitt    };
47695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
47791326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    void onPrepareDraws(Target* target) override {
478b5238a7571c243ba4a154a62575570c3078b3741bsalomon        QuadHelper helper;
479477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        size_t vertexStride = this->gp()->getVertexStride();
480b5238a7571c243ba4a154a62575570c3078b3741bsalomon        SkASSERT(vertexStride == sizeof(Vertex));
4817539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
482b5238a7571c243ba4a154a62575570c3078b3741bsalomon        if (!verts) {
4834b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            return;
4844b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt        }
485477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        SkRect rect = this->rect();
48674f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark        SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
48774f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark                                     rect.fBottom, sizeof(Vertex));
48895964c670b577d5f49c5eab7af277ad987fd0519joshualitt        fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
489477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon        helper.recordDraw(target, this->gp(), this->makePipeline(target));
49095964c670b577d5f49c5eab7af277ad987fd0519joshualitt    }
49195964c670b577d5f49c5eab7af277ad987fd0519joshualitt
4929e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    GrPathUtils::QuadUVMatrix fDevToUV;
49395964c670b577d5f49c5eab7af277ad987fd0519joshualitt
494dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kVertsPerCubic = 4;
495dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kIndicesPerCubic = 6;
49695964c670b577d5f49c5eab7af277ad987fd0519joshualitt
497477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon    typedef BezierTestOp INHERITED;
49895964c670b577d5f49c5eab7af277ad987fd0519joshualitt};
49995964c670b577d5f49c5eab7af277ad987fd0519joshualitt
50053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org/**
50153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
50253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org */
50353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgclass BezierQuadEffects : public GM {
50453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgpublic:
50553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    BezierQuadEffects() {
50653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        this->setBGColor(0xFFFFFFFF);
50753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
50853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
50953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgprotected:
51036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
51153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        return SkString("bezier_quad_effects");
51253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
51353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
51436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override {
515f539318f0d3dba743ec1886d5d9df0fb1be628a1tfarina        return SkISize::Make(800, 800);
51653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
51753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
51853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
51936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
5201105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        GrRenderTargetContext* renderTargetContext =
5211105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman            canvas->internal_private_accessTopLayerRenderTargetContext();
5221105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        if (!renderTargetContext) {
5232a24338c777462e04a2b26295f9c034155ee8f3ehalcanary            skiagm::GM::DrawGpuOnlyMessage(canvas);
52453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            return;
52553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
52653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
527175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        GrContext* context = canvas->getGrContext();
528175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips        if (!context) {
529f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt            return;
530f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt        }
531f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt
53253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        struct Vertex {
53353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkPoint fPosition;
53453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            float   fUV[4]; // The last two values are ignored. The effect expects a vec4f.
53553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        };
53653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
537dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr int kNumQuads = 5;
538e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org        SkRandom rand;
53953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
54053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
54153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
5421105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
5431105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman        SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
54453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int row = 0;
54553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        int col = 0;
546dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr GrColor color = 0xff000000;
54753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
54853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        for (int i = 0; i < kNumQuads; ++i) {
54953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            SkPoint baseControlPts[] = {
55053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
55153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
55253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
55353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            };
5541706f842086c089ebc496dfc7f45c959e5eda01eEthan Nicholas            for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
55506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                sk_sp<GrGeometryProcessor> gp;
5560f3c73220a25eba9bf11583db3d0f76a2c4f6331Ethan Nicholas                GrClipEdgeType et = (GrClipEdgeType)edgeType;
55706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                gp = GrQuadEffect::Make(color, SkMatrix::I(), et,
55806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                        *context->caps(), SkMatrix::I(), false);
559f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt                if (!gp) {
560f5883a6d75a18c581507214d3057b5c721ed1ffcjoshualitt                    continue;
561cabf4b2f3664b98c1084fbb94a999af15ddfb52dcommit-bot@chromium.org                }
562cabf4b2f3664b98c1084fbb94a999af15ddfb52dcommit-bot@chromium.org
563df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar x = col * w;
564df85c38163245c7fc3c23cad3a4ad104949f3a62Mike Reed                SkScalar y = row * h;
56553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPoint controlPts[] = {
56653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
56753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
56853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
56953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                };
57053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPoint chopped[5];
57153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
57253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
57353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint ctrlPtPaint;
57453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
57553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                for (int i = 0; i < 3; ++i) {
57623e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                    canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
57753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
57853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
57953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint polyPaint;
58053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setColor(0xffA0A0A0);
58153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStrokeWidth(0);
58253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                polyPaint.setStyle(SkPaint::kStroke_Style);
58353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
58453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
58553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                SkPaint choppedPtPaint;
58653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
58753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
58853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                for (int c = 0; c < cnt; ++c) {
58953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPoint* pts = chopped + 2 * c;
59053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
59153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    for (int i = 0; i < 3; ++i) {
59223e474cb7331c5d2389d97dce2d9e5c93c58f39fHal Canary                        canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
59353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    }
59453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
59553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkRect bounds;
59653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    bounds.set(pts, 3);
59753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
59853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    SkPaint boundsPaint;
59953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setColor(0xff808080);
60053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStrokeWidth(0);
60153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    boundsPaint.setStyle(SkPaint::kStroke_Style);
60253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    canvas->drawRect(bounds, boundsPaint);
60353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
60428a838e532250fcca9673aca6c4616193a5a139drobertphillips                    GrPaint grPaint;
605a16339297859f37df69230e64f05624cef511ad3Brian Salomon                    grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
6063f284d7758d7f35b59d93a22d126f7cd8423be44joshualitt
60794dff15404a6c82873f3f5092023426937274cc1joshualitt                    GrPathUtils::QuadUVMatrix DevToUV(pts);
60894dff15404a6c82873f3f5092023426937274cc1joshualitt
609477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    std::unique_ptr<GrDrawOp> op =
610f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                            BezierQuadTestOp::Make(gp, bounds, color, DevToUV);
611477d0efcf2d90c70a87c5a126349e76ac57d9649Brian Salomon                    renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
61253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
61353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                ++col;
61453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                if (numCols == col) {
61553a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    col = 0;
61653a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                    ++row;
61753a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org                }
61853a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org            }
61953a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org        }
62053a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    }
62153a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org
62253a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.orgprivate:
62353a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org    typedef GM INHERITED;
62453a0b6cc191639925798c01e9bce853723517419commit-bot@chromium.org};
62578a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
626385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM(return new BezierCubicEffects;)
627385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM(return new BezierConicEffects;)
628385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM(return new BezierQuadEffects;)
62978a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org}
63078a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org
63178a1078f17f4f0ae63415298517262a64f706af6commit-bot@chromium.org#endif
632