133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt/*
233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt * Copyright 2015 Google Inc.
333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt *
433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt * Use of this source code is governed by a BSD-style license that can be
533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt * found in the LICENSE file.
633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt */
733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
8fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon#include "GrLatticeOp.h"
933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#include "GrDefaultGeoProcFactory.h"
10815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon#include "GrDrawOpTest.h"
11dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrMeshDrawOp.h"
12742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
1333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#include "GrResourceProvider.h"
14815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon#include "GrSimpleMeshDrawOpHelper.h"
1533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#include "SkBitmap.h"
16c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h"
17fa3783f17dba971e3204ba950965d9c65eb8711dBrian Salomon#include "SkMatrixPriv.h"
1874f623d1617e0ccf3eddf37aeecabd0ac72369fdCary Clark#include "SkPointPriv.h"
1933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#include "SkRect.h"
2038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III#include "glsl/GrGLSLColorSpaceXformHelper.h"
2138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III#include "glsl/GrGLSLGeometryProcessor.h"
2238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III#include "glsl/GrGLSLVarying.h"
2333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
24815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomonnamespace {
25815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
2638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins IIIclass LatticeGP : public GrGeometryProcessor {
2738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins IIIpublic:
2838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    struct Vertex {
2938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        SkPoint fPosition;
3038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        SkPoint fTextureCoords;
3138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        SkRect fTextureDomain;
3238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        GrColor fColor;
3338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    };
3438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
3538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxy,
3638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                           sk_sp<GrColorSpaceXform> csxf,
3738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                           GrSamplerState::Filter filter) {
3838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        return sk_sp<GrGeometryProcessor>(new LatticeGP(std::move(proxy), std::move(csxf), filter));
3938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    }
4038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
4138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    const char* name() const override { return "LatticeGP"; }
4238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
4338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
4438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
4538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    }
4638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
4738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override {
4838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        class GLSLProcessor : public GrGLSLGeometryProcessor {
4938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        public:
5038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
5138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                         FPCoordTransformIter&& transformIter) override {
5238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                const auto& latticeGP = proc.cast<LatticeGP>();
5338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
5438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                if (fColorSpaceXformHelper.isValid()) {
5538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                    fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get());
5638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                }
5738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            }
5838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
5938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        private:
6038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
6138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                using Interpolation = GrGLSLVaryingHandler::Interpolation;
6238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                const auto& latticeGP = args.fGP.cast<LatticeGP>();
6338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                fColorSpaceXformHelper.emitCode(args.fUniformHandler,
6438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                                latticeGP.fColorSpaceXform.get());
6538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
6638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fVaryingHandler->emitAttributes(latticeGP);
6738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fPositions.fName);
6838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                this->emitTransforms(args.fVertBuilder,
6938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                     args.fVaryingHandler,
7038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                     args.fUniformHandler,
7138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                     latticeGP.fTextureCoords.asShaderVar(),
7238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                     args.fFPCoordTransformHandler);
7338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->codeAppend("float2 textureCoords;");
7438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fTextureCoords,
7538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                                              "textureCoords");
7638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->codeAppend("float4 textureDomain;");
7738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fVaryingHandler->addPassThroughAttribute(
7838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        &latticeGP.fTextureDomain, "textureDomain", Interpolation::kCanBeFlat);
7938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fColors, args.fOutputColor,
8038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                                              Interpolation::kCanBeFlat);
8138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
8238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->appendTextureLookupAndModulate(
8338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        args.fOutputColor,
8438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        args.fTexSamplers[0],
8538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        "clamp(textureCoords, textureDomain.xy, textureDomain.zw)",
8638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        kFloat2_GrSLType,
8738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        &fColorSpaceXformHelper);
8838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->codeAppend(";");
8938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
9038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            }
9138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
9238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        };
9338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        return new GLSLProcessor;
9438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    }
9538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
9638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins IIIprivate:
9738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    LatticeGP(sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> csxf,
9838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III              GrSamplerState::Filter filter)
9938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            : INHERITED(kLatticeGP_ClassID), fColorSpaceXform(std::move(csxf)) {
10038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType);
10138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        fSampler.reset(std::move(proxy), filter);
10238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        this->addTextureSampler(&fSampler);
10338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType);
10438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        fTextureDomain = this->addVertexAttrib("textureDomain", kFloat4_GrVertexAttribType);
10538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType);
10638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    }
10738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
10838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    Attribute fPositions;
10938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    Attribute fTextureCoords;
11038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    Attribute fTextureDomain;
11138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    Attribute fColors;
11238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    sk_sp<GrColorSpaceXform> fColorSpaceXform;
11338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    TextureSampler fSampler;
11438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
11538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    typedef GrGeometryProcessor INHERITED;
11638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III};
11738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
118815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomonclass NonAALatticeOp final : public GrMeshDrawOp {
119815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomonprivate:
120815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    using Helper = GrSimpleMeshDrawOpHelper;
121815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
12233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualittpublic:
12325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
12433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
12533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    static const int kVertsPerRect = 4;
12633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    static const int kIndicesPerRect = 6;
12733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
128815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
12938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                          sk_sp<GrTextureProxy> proxy,
13038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                          sk_sp<GrColorSpaceXform> colorSpaceXForm,
13138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                          GrSamplerState::Filter filter,
132815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon                                          std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
13338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        return Helper::FactoryHelper<NonAALatticeOp>(std::move(paint), viewMatrix, std::move(proxy),
13438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                                     std::move(colorSpaceXForm), filter,
13538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                                     std::move(iter), dst);
136815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    }
137815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
138815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    NonAALatticeOp(Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
13938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                   sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> colorSpaceXform,
14038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                   GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter,
141815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon                   const SkRect& dst)
14238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            : INHERITED(ClassID())
14338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            , fHelper(helperArgs, GrAAType::kNone)
14438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            , fProxy(std::move(proxy))
14538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            , fColorSpaceXform(std::move(colorSpaceXform))
14638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            , fFilter(filter) {
147a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        Patch& patch = fPatches.push_back();
148a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        patch.fViewMatrix = viewMatrix;
149a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        patch.fColor = color;
15010e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        patch.fIter = std::move(iter);
151a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        patch.fDst = dst;
15233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
15333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        // setup bounds
15488cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->setTransformedBounds(patch.fDst, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
15533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
15633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
157fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon    const char* name() const override { return "NonAALatticeOp"; }
158783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips
159f1748f5a9238a0d3e189d50fc5e57ae8b8ec087cRobert Phillips    void visitProxies(const VisitProxyFunc& func) const override {
160b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips        fHelper.visitProxies(func);
161b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips    }
162b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips
163783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips    SkString dumpInfo() const override {
164783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips        SkString str;
165783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips
166a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        for (int i = 0; i < fPatches.count(); ++i) {
167fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon            str.appendf("%d: Color: 0x%08x Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
168fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                        fPatches[i].fColor, fPatches[i].fDst.fLeft, fPatches[i].fDst.fTop,
169a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon                        fPatches[i].fDst.fRight, fPatches[i].fDst.fBottom);
170783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips        }
171783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips
172815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        str += fHelper.dumpInfo();
173815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        str += INHERITED::dumpInfo();
174783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips        return str;
175783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips    }
17633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
177815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
17892aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon
1799a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
1809a725dd9485654155e2e4196c32d372360bcdb61Brian Osman                                GrPixelConfigIsClamped dstIsClamped) override {
18138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        auto opaque = GrColorIsOpaque(fPatches[0].fColor) && GrPixelConfigIsOpaque(fProxy->config())
18238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                              ? GrProcessorAnalysisColor::Opaque::kYes
18338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                              : GrProcessorAnalysisColor::Opaque::kNo;
18438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        auto analysisColor = GrProcessorAnalysisColor(opaque);
18538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        auto result = fHelper.xpRequiresDstTexture(
18638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                caps, clip, dstIsClamped, GrProcessorAnalysisCoverage::kNone, &analysisColor);
18738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        analysisColor.isConstant(&fPatches[0].fColor);
18838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        return result;
18933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
19033a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
191815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomonprivate:
19291326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    void onPrepareDraws(Target* target) override {
19338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        auto gp = LatticeGP::Make(fProxy, fColorSpaceXform, fFilter);
19433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        if (!gp) {
19533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            SkDebugf("Couldn't create GrGeometryProcessor\n");
19633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            return;
19733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        }
19833a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
19933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        size_t vertexStride = gp->getVertexStride();
200a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        int patchCnt = fPatches.count();
20110e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        int numRects = 0;
20210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        for (int i = 0; i < patchCnt; i++) {
2030764efe6a9ae65ad83992f614f57ca9db5b1f191msarett            numRects += fPatches[i].fIter->numRectsToDraw();
20410e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        }
20533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
2060db1b53a849ae145a32cd1315c9f4f03430e90cbBrian Salomon        if (!numRects) {
2070db1b53a849ae145a32cd1315c9f4f03430e90cbBrian Salomon            return;
2080db1b53a849ae145a32cd1315c9f4f03430e90cbBrian Salomon        }
2090db1b53a849ae145a32cd1315c9f4f03430e90cbBrian Salomon
210d28a79d49549568c3ebac36288ea3965496333f8Brian Salomon        sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
2113809bab7ed344ad140346c38e149dabf10bd525fChris Dalton        PatternHelper helper(GrPrimitiveType::kTriangles);
212bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton        void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
213bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton                                     kIndicesPerRect, numRects);
21433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        if (!vertices || !indexBuffer) {
21533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            SkDebugf("Could not allocate vertices\n");
21633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            return;
21733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        }
21833a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
21910e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        intptr_t verts = reinterpret_cast<intptr_t>(vertices);
220a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        for (int i = 0; i < patchCnt; i++) {
2217fc08585d0d4daada1c8600b6cdef970ee6c2369msarett            const Patch& patch = fPatches[i];
22210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett
22310e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            // Apply the view matrix here if it is scale-translate.  Otherwise, we need to
22410e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            // wait until we've created the dst rects.
22510e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            bool isScaleTranslate = patch.fViewMatrix.isScaleTranslate();
22610e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            if (isScaleTranslate) {
22710e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett                patch.fIter->mapDstScaleTranslate(patch.fViewMatrix);
22810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            }
22933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
23038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            SkIRect srcR;
23138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            SkRect dstR;
23210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            intptr_t patchVerts = verts;
23338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            Sk4f scales(1.f / fProxy->width(), 1.f / fProxy->height(),
23438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                        1.f / fProxy->width(), 1.f / fProxy->height());
23538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            static const Sk4f kDomainOffsets(0.5f, 0.5f, -0.5f, -0.5f);
23638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            static const Sk4f kFlipOffsets(0.f, 1, 0.f, 1.f);
23738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            static const Sk4f kFlipMuls(1.f, -1.f, 1.f, -1.f);
23810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            while (patch.fIter->next(&srcR, &dstR)) {
23938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                auto vertices = reinterpret_cast<LatticeGP::Vertex*>(verts);
24038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                SkPointPriv::SetRectTriStrip(&vertices->fPosition, dstR.fLeft, dstR.fTop,
24138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                             dstR.fRight, dstR.fBottom, vertexStride);
24238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                Sk4f coords(SkIntToScalar(srcR.fLeft), SkIntToScalar(srcR.fTop),
24338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                            SkIntToScalar(srcR.fRight), SkIntToScalar(srcR.fBottom));
24438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                Sk4f domain = coords + kDomainOffsets;
24538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                coords *= scales;
24638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                domain *= scales;
24738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                if (fProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
24838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                    coords = kFlipMuls * coords + kFlipOffsets;
24938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                    domain = SkNx_shuffle<0, 3, 2, 1>(kFlipMuls * domain + kFlipOffsets);
25038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                }
25138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                SkPointPriv::SetRectTriStrip(&vertices->fTextureCoords, coords[0], coords[1],
25238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                             coords[2], coords[3], vertexStride);
25338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                for (int j = 0; j < kVertsPerRect; ++j) {
25438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                    vertices[j].fTextureDomain = {domain[0], domain[1], domain[2], domain[3]};
25538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                }
25638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
25738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                for (int j = 0; j < kVertsPerRect; ++j) {
25838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                    vertices[j].fColor = patch.fColor;
25933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt                }
26033a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt                verts += kVertsPerRect * vertexStride;
26133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            }
26210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett
26310e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            // If we didn't handle it above, apply the matrix here.
26410e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            if (!isScaleTranslate) {
26510e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett                SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
266fa3783f17dba971e3204ba950965d9c65eb8711dBrian Salomon                SkMatrixPriv::MapPointsWithStride(patch.fViewMatrix, positions, vertexStride,
267fa3783f17dba971e3204ba950965d9c65eb8711dBrian Salomon                                                  kVertsPerRect * patch.fIter->numRectsToDraw());
26810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett            }
26933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        }
270815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        helper.recordDraw(target, gp.get(), fHelper.makePipeline(target));
27133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
27233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
27325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
274fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon        NonAALatticeOp* that = t->cast<NonAALatticeOp>();
27538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        if (fProxy != that->fProxy) {
27638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            return false;
27738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        }
27838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        if (fFilter != that->fFilter) {
27938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            return false;
28038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        }
28138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        if (GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
28238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            return false;
28338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        }
284815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
28533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt            return false;
28633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        }
28733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
28810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin());
28988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->joinBounds(*that);
29033a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        return true;
29133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
29233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
293a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon    struct Patch {
294a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        SkMatrix fViewMatrix;
29510e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett        std::unique_ptr<SkLatticeIter> fIter;
296a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        SkRect fDst;
297a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon        GrColor fColor;
298a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon    };
299a71b89866deeea26eb7fd9d41eb3d28ce60ee92absalomon
300815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    Helper fHelper;
301815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    SkSTArray<1, Patch, true> fPatches;
30238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    sk_sp<GrTextureProxy> fProxy;
30338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    sk_sp<GrColorSpaceXform> fColorSpaceXform;
30438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    GrSamplerState::Filter fFilter;
30533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
306815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    typedef GrMeshDrawOp INHERITED;
30733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt};
30833a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
309815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon}  // anonymous namespace
310815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
311fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonnamespace GrLatticeOp {
31238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins IIIstd::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&& paint, const SkMatrix& viewMatrix,
31338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                    sk_sp<GrTextureProxy> proxy,
31438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                    sk_sp<GrColorSpaceXform> colorSpaceXform,
31538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                    GrSamplerState::Filter filter,
31638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                    std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
31738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy),
31838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                std::move(colorSpaceXform), filter, std::move(iter), dst);
31933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt}
32033a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt};
321815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
322815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon#if GR_TEST_UTILS
32338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III#include "GrContextPriv.h"
32438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III#include "GrProxyProvider.h"
325815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
326815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon/** Randomly divides subset into count divs. */
327815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomonstatic void init_random_divs(int divs[], int count, int subsetStart, int subsetStop,
328815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon                             SkRandom* random) {
329815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // Rules for lattice divs: Must be strictly increasing and in the range
330815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // [subsetStart, subsetStop).
331815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // Not terribly efficient alg for generating random divs:
332815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 1) Start with minimum legal pixels between each div.
333815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 2) Randomly assign the remaining pixels of the subset to divs.
334815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 3) Convert from pixel counts to div offsets.
335815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
336815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 1) Initially each divs[i] represents the number of pixels between
337815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // div i-1 and i. The initial div is allowed to be at subsetStart. There
338815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // must be one pixel spacing between subsequent divs.
339815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    divs[0] = 0;
340815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    for (int i = 1; i < count; ++i) {
341815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        divs[i] = 1;
342815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    }
343815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 2) Assign the remaining subset pixels to fall
344815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    int subsetLength = subsetStop - subsetStart;
345815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    for (int i = 0; i < subsetLength - count; ++i) {
346815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        // +1 because count divs means count+1 intervals.
347815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        int entry = random->nextULessThan(count + 1);
348815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        // We don't have an entry to  to store the count after the last div
349815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        if (entry < count) {
350815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon            divs[entry]++;
351815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        }
352815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    }
353815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    // 3) Now convert the counts between divs to pixel indices, incorporating the subset's offset.
354815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    int offset = subsetStart;
355815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    for (int i = 0; i < count; ++i) {
356815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        divs[i] += offset;
357815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        offset = divs[i];
358815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    }
359815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon}
360815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
361815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian SalomonGR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) {
362815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    SkCanvas::Lattice lattice;
36318df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    // We loop because our random lattice code can produce an invalid lattice in the case where
36418df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    // there is a single div separator in both x and y and both are aligned with the left and top
36518df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    // edge of the image subset, respectively.
36618df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    std::unique_ptr<int[]> xdivs;
36718df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    std::unique_ptr<int[]> ydivs;
368ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev    std::unique_ptr<SkCanvas::Lattice::RectType[]> flags;
369ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev    std::unique_ptr<SkColor[]> colors;
37018df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    SkIRect subset;
37138784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    GrSurfaceDesc desc;
37238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    desc.fConfig = kRGBA_8888_GrPixelConfig;
37338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    desc.fWidth = random->nextRangeU(1, 1000);
37438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    desc.fHeight = random->nextRangeU(1, 1000);
37538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    desc.fOrigin =
37638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
37738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    auto proxy = context->contextPriv().proxyProvider()->createProxy(
37838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            desc, SkBackingFit::kExact, SkBudgeted::kYes);
37938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III
38018df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon    do {
38118df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        if (random->nextBool()) {
38238784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            subset.fLeft = random->nextULessThan(desc.fWidth);
38338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            subset.fRight = random->nextRangeU(subset.fLeft + 1, desc.fWidth);
38438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            subset.fTop = random->nextULessThan(desc.fHeight);
38538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            subset.fBottom = random->nextRangeU(subset.fTop + 1, desc.fHeight);
38618df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        } else {
38738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            subset.setXYWH(0, 0, desc.fWidth, desc.fHeight);
388815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon        }
38938784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        // SkCanvas::Lattice allows bounds to be null. However, SkCanvas creates a temp Lattice with
39038784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III        // a non-null bounds before creating a SkLatticeIter since SkLatticeIter requires a bounds.
39118df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        lattice.fBounds = &subset;
39218df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        lattice.fXCount = random->nextRangeU(1, subset.width());
39318df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        lattice.fYCount = random->nextRangeU(1, subset.height());
39418df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        xdivs.reset(new int[lattice.fXCount]);
39518df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        ydivs.reset(new int[lattice.fYCount]);
39618df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        init_random_divs(xdivs.get(), lattice.fXCount, subset.fLeft, subset.fRight, random);
39718df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        init_random_divs(ydivs.get(), lattice.fYCount, subset.fTop, subset.fBottom, random);
39818df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        lattice.fXDivs = xdivs.get();
39918df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        lattice.fYDivs = ydivs.get();
40018df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        bool hasFlags = random->nextBool();
40118df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        if (hasFlags) {
40218df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon            int n = (lattice.fXCount + 1) * (lattice.fYCount + 1);
403ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            flags.reset(new SkCanvas::Lattice::RectType[n]);
404ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            colors.reset(new SkColor[n]);
40518df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon            for (int i = 0; i < n; ++i) {
406ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev                flags[i] = random->nextBool() ? SkCanvas::Lattice::kTransparent
407ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev                                              : SkCanvas::Lattice::kDefault;
40818df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon            }
409ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            lattice.fRectTypes = flags.get();
410ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            lattice.fColors = colors.get();
41118df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        } else {
412ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            lattice.fRectTypes = nullptr;
413ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev            lattice.fColors = nullptr;
41418df763be8257ad2561d9dbcb3813c7557fedc8fBrian Salomon        }
41538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    } while (!SkLatticeIter::Valid(desc.fWidth, desc.fHeight, lattice));
416815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    SkRect dst;
417815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    dst.fLeft = random->nextRangeScalar(-2000.5f, 1000.f);
418815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    dst.fTop = random->nextRangeScalar(-2000.5f, 1000.f);
419815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    dst.fRight = dst.fLeft + random->nextRangeScalar(0.5f, 1000.f);
420815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    dst.fBottom = dst.fTop + random->nextRangeScalar(0.5f, 1000.f);
421815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    std::unique_ptr<SkLatticeIter> iter(new SkLatticeIter(lattice, dst));
422815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon    SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
42338784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    auto csxf = GrTest::TestColorXform(random);
42438784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    GrSamplerState::Filter filter =
42538784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III            random->nextBool() ? GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp;
42638784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III    return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy), std::move(csxf),
42738784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III                                filter, std::move(iter), dst);
428815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon}
429815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon
430815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon#endif
431