1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2017 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureOp.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrAppliedClip.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrCaps.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrDrawOpTest.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGeometryProcessor.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrMeshDrawOp.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrOpFlushState.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrQuad.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrResourceProvider.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrShaderCaps.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTexture.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTexturePriv.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureProxy.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMathPriv.h"
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPoint.h"
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPoint3.h"
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLColorSpaceXformHelper.h"
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentShaderBuilder.h"
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLGeometryProcessor.h"
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLVarying.h"
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLVertexGeoBuilder.h"
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace {
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Geometry Processor that draws a texture modulated by a vertex color (though, this is meant to be
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * the same value across all vertices of a quad and uses flat interpolation when available). This is
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * used by TextureOp below.
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass TextureGeometryProcessor : public GrGeometryProcessor {
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct Vertex {
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fPosition;
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fTextureCoords;
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrColor fColor;
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct AAVertex {
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fPosition;
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fTextureCoords;
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint3 fEdges[4];
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrColor fColor;
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct MultiTextureVertex {
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fPosition;
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int fTextureIdx;
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fTextureCoords;
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrColor fColor;
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct AAMultiTextureVertex {
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fPosition;
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int fTextureIdx;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint fTextureCoords;
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint3 fEdges[4];
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrColor fColor;
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Maximum number of textures supported by this op. Must also be checked against the caps
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // limit. These numbers were based on some limited experiments on a HP Z840 and Pixel XL 2016
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // and could probably use more tuning.
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_ANDROID
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMaxTextures = 4;
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMaxTextures = 8;
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int SupportsMultitexture(const GrShaderCaps& caps) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return caps.integerSupport() && caps.maxFragmentSamplers() > 1;
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           sk_sp<GrColorSpaceXform> csxf, bool coverageAA,
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const GrSamplerState::Filter filters[],
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const GrShaderCaps& caps) {
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // We use placement new to avoid always allocating space for kMaxTextures TextureSampler
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // instances.
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int samplerCnt = NumSamplersToUse(proxyCnt, caps);
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t size = sizeof(TextureGeometryProcessor) + sizeof(TextureSampler) * (samplerCnt - 1);
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* mem = GrGeometryProcessor::operator new(size);
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return sk_sp<TextureGeometryProcessor>(new (mem) TextureGeometryProcessor(
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                proxies, proxyCnt, samplerCnt, std::move(csxf), coverageAA, filters, caps));
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~TextureGeometryProcessor() override {
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int cnt = this->numTextureSamplers();
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 1; i < cnt; ++i) {
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fSamplers[i].~TextureSampler();
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return "TextureGeometryProcessor"; }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        b->add32(static_cast<uint32_t>(this->usesCoverageEdgeAA()));
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override {
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        class GLSLProcessor : public GrGLSLGeometryProcessor {
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        public:
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         FPCoordTransformIter&& transformIter) override {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const auto& textureGP = proc.cast<TextureGeometryProcessor>();
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (fColorSpaceXformHelper.isValid()) {
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    fColorSpaceXformHelper.setData(pdman, textureGP.fColorSpaceXform.get());
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        private:
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const auto& textureGP = args.fGP.cast<TextureGeometryProcessor>();
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fColorSpaceXformHelper.emitCode(
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fUniformHandler, textureGP.fColorSpaceXform.get());
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                args.fVaryingHandler->setNoPerspective();
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                args.fVaryingHandler->emitAttributes(textureGP);
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->writeOutputPosition(args.fVertBuilder, gpArgs, textureGP.fPositions.fName);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->emitTransforms(args.fVertBuilder,
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     args.fVaryingHandler,
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     args.fUniformHandler,
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     textureGP.fTextureCoords.asShaderVar(),
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     args.fFPCoordTransformHandler);
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (args.fShaderCaps->preferFlatInterpolation()) {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fVaryingHandler->addFlatPassThroughAttribute(&textureGP.fColors,
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      args.fOutputColor);
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fVaryingHandler->addPassThroughAttribute(&textureGP.fColors,
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                  args.fOutputColor);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                args.fFragBuilder->codeAppend("float2 texCoord;");
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords,
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                              "texCoord");
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (textureGP.numTextureSamplers() > 1) {
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(args.fShaderCaps->integerSupport());
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppend("int texIdx;");
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (args.fShaderCaps->flatInterpolationSupport()) {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fVaryingHandler->addFlatPassThroughAttribute(&textureGP.fTextureIdx,
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          "texIdx");
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } else {
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureIdx,
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      "texIdx");
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppend("switch (texIdx) {");
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (int i = 0; i < textureGP.numTextureSamplers(); ++i) {
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fFragBuilder->codeAppendf("case %d: %s = ", i, args.fOutputColor);
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          args.fTexSamplers[i],
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          "texCoord",
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          kFloat2_GrSLType,
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          &fColorSpaceXformHelper);
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fFragBuilder->codeAppend("; break;");
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppend("}");
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      args.fTexSamplers[0],
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      "texCoord",
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      kFloat2_GrSLType,
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      &fColorSpaceXformHelper);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                args.fFragBuilder->codeAppend(";");
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (textureGP.usesCoverageEdgeAA()) {
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    const char* aaDistName = nullptr;
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // When interpolation is innacurate we perform the evaluation of the edge
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // equations in the fragment shader rather than interpolating values computed
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // in the vertex shader.
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!args.fShaderCaps->interpolantsAreInaccurate()) {
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        GrGLSLVarying aaDistVarying(kFloat4_GrSLType,
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    GrGLSLVarying::Scope::kVertToFrag);
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fVertBuilder->codeAppendf(
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                R"(%s = float4(dot(aaEdge0.xy, %s.xy) + aaEdge0.z,
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               dot(aaEdge1.xy, %s.xy) + aaEdge1.z,
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               dot(aaEdge2.xy, %s.xy) + aaEdge2.z,
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               dot(aaEdge3.xy, %s.xy) + aaEdge3.z);)",
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                aaDistVarying.vsOut(), textureGP.fPositions.fName,
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                textureGP.fPositions.fName, textureGP.fPositions.fName,
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                textureGP.fPositions.fName);
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaDistName = aaDistVarying.fsIn();
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } else {
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        GrGLSLVarying aaEdgeVarying[4]{
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                {kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                {kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                {kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                {kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag}
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        };
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        for (int i = 0; i < 4; ++i) {
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkString name;
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            name.printf("aaEdge%d", i);
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fVaryingHandler->addVarying(name.c_str(), &aaEdgeVarying[i]);
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fVertBuilder->codeAppendf(
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    "%s = aaEdge%d;", aaEdgeVarying[i].vsOut(), i);
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        args.fFragBuilder->codeAppendf(
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                R"(float4 aaDists = float4(dot(%s.xy, sk_FragCoord.xy) + %s.z,
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                           dot(%s.xy, sk_FragCoord.xy) + %s.z,
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                           dot(%s.xy, sk_FragCoord.xy) + %s.z,
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                           dot(%s.xy, sk_FragCoord.xy) + %s.z);)",
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaEdgeVarying[0].fsIn(), aaEdgeVarying[0].fsIn(),
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaEdgeVarying[1].fsIn(), aaEdgeVarying[1].fsIn(),
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaEdgeVarying[2].fsIn(), aaEdgeVarying[2].fsIn(),
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaEdgeVarying[3].fsIn(), aaEdgeVarying[3].fsIn());
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        aaDistName = "aaDists";
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppendf(
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            "float mindist = min(min(%s.x, %s.y), min(%s.z, %s.w));",
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            aaDistName, aaDistName, aaDistName, aaDistName);
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppendf("%s = float4(clamp(mindist, 0, 1));",
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   args.fOutputCoverage);
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new GLSLProcessor;
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool usesCoverageEdgeAA() const { return SkToBool(fAAEdges[0].isInitialized()); }
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This exists to reduce the number of shaders generated. It does some rounding of sampler
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // counts.
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int NumSamplersToUse(int numRealProxies, const GrShaderCaps& caps) {
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(numRealProxies > 0 && numRealProxies <= kMaxTextures &&
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                 numRealProxies <= caps.maxFragmentSamplers());
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (1 == numRealProxies) {
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 1;
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (numRealProxies <= 4) {
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return 4;
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Round to the next power of 2 and then clamp to kMaxTextures and the max allowed by caps.
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkTMin(SkNextPow2(numRealProxies), SkTMin(kMaxTextures, caps.maxFragmentSamplers()));
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             sk_sp<GrColorSpaceXform> csxf, bool coverageAA,
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : INHERITED(kTextureGeometryProcessor_ClassID), fColorSpaceXform(std::move(csxf)) {
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt);
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType);
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fSamplers[0].reset(std::move(proxies[0]), filters[0]);
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->addTextureSampler(&fSamplers[0]);
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 1; i < proxyCnt; ++i) {
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This class has one sampler built in, the rest come from memory this processor was
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // placement-newed into and so haven't been constructed.
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            new (&fSamplers[i]) TextureSampler(std::move(proxies[i]), filters[i]);
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->addTextureSampler(&fSamplers[i]);
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (samplerCnt > 1) {
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Here we initialize any extra samplers by repeating the last one samplerCnt - proxyCnt
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // times.
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrTextureProxy* dupeProxy = fSamplers[proxyCnt - 1].proxy();
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = proxyCnt; i < samplerCnt; ++i) {
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                new (&fSamplers[i]) TextureSampler(sk_ref_sp(dupeProxy), filters[proxyCnt - 1]);
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->addTextureSampler(&fSamplers[i]);
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(caps.integerSupport());
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fTextureIdx = this->addVertexAttrib("textureIdx", kInt_GrVertexAttribType);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (coverageAA) {
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAAEdges[0] = this->addVertexAttrib("aaEdge0", kFloat3_GrVertexAttribType);
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAAEdges[1] = this->addVertexAttrib("aaEdge1", kFloat3_GrVertexAttribType);
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAAEdges[2] = this->addVertexAttrib("aaEdge2", kFloat3_GrVertexAttribType);
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fAAEdges[3] = this->addVertexAttrib("aaEdge3", kFloat3_GrVertexAttribType);
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType);
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Attribute fPositions;
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Attribute fTextureIdx;
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Attribute fTextureCoords;
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Attribute fColors;
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Attribute fAAEdges[4];
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrColorSpaceXform> fColorSpaceXform;
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureSampler fSamplers[1];
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrGeometryProcessor INHERITED;
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace {
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This is a class soley so it can be partially specialized (functions cannot be).
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<GrAA, typename Vertex> class VertexAAHandler;
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename Vertex> class VertexAAHandler<GrAA::kNo, Vertex> {
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void AssignPositionsAndTexCoords(Vertex* vertices, const GrQuad& quad,
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            const SkRect& texRect) {
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[0].fPosition = quad.point(0);
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[0].fTextureCoords = {texRect.fLeft, texRect.fTop};
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[1].fPosition = quad.point(1);
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[1].fTextureCoords = {texRect.fLeft, texRect.fBottom};
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[2].fPosition = quad.point(2);
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[2].fTextureCoords = {texRect.fRight, texRect.fTop};
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[3].fPosition = quad.point(3);
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[3].fTextureCoords = {texRect.fRight, texRect.fBottom};
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename Vertex> class VertexAAHandler<GrAA::kYes, Vertex> {
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void AssignPositionsAndTexCoords(Vertex* vertices, const GrQuad& quad,
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            const SkRect& texRect) {
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // We compute the four edge equations for quad, then outset them and compute a new quad
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // as the intersection points of the outset edges.
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GrQuad is in tristip order but we want the points to be in a fan order, so swap 2 and 3.
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f xs(quad.point(0).fX, quad.point(1).fX, quad.point(3).fX, quad.point(2).fX);
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f ys(quad.point(0).fY, quad.point(1).fY, quad.point(3).fY, quad.point(2).fY);
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f xsrot = SkNx_shuffle<1, 2, 3, 0>(xs);
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f ysrot = SkNx_shuffle<1, 2, 3, 0>(ys);
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f normXs = ysrot - ys;
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f normYs = xs - xsrot;
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f ds = xsrot * ys - ysrot * xs;
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f invNormLengths = (normXs * normXs + normYs * normYs).rsqrt();
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        float test = normXs[0] * xs[2] + normYs[0] * ys[2] + ds[0];
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Make sure the edge equations have their normals facing into the quad in device space
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (test < 0) {
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            invNormLengths = -invNormLengths;
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        normXs *= invNormLengths;
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        normYs *= invNormLengths;
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ds *= invNormLengths;
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Here is the bloat. This makes our edge equations compute coverage without requiring a
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // half pixel offset and is also used to compute the bloated quad that will cover all
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // pixels.
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ds += Sk4f(0.5f);
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < 4; ++i) {
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int j = 0; j < 4; ++j) {
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                vertices[j].fEdges[i].fX = normXs[i];
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                vertices[j].fEdges[i].fY = normYs[i];
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                vertices[j].fEdges[i].fZ = ds[i];
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Reverse the process to compute the points of the bloated quad from the edge equations.
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // This time the inputs don't have 1s as their third coord and we want to homogenize rather
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // than normalize the output since we need a GrQuad with 2D points.
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        xsrot = SkNx_shuffle<3, 0, 1, 2>(normXs);
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ysrot = SkNx_shuffle<3, 0, 1, 2>(normYs);
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Sk4f dsrot = SkNx_shuffle<3, 0, 1, 2>(ds);
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        xs = ysrot * ds - normYs * dsrot;
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ys = normXs * dsrot - xsrot * ds;
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ds = xsrot * normYs - ysrot * normXs;
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ds = ds.invert();
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        xs *= ds;
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ys *= ds;
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Go back to tri strip order when writing out the bloated quad to vertex positions.
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[0].fPosition = {xs[0], ys[0]};
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[1].fPosition = {xs[1], ys[1]};
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[3].fPosition = {xs[2], ys[2]};
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[2].fPosition = {xs[3], ys[3]};
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        AssignTexCoords(vertices, quad, texRect);
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void AssignTexCoords(Vertex* vertices, const GrQuad& quad, const SkRect& tex) {
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix q = SkMatrix::MakeAll(quad.point(0).fX, quad.point(1).fX, quad.point(2).fX,
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       quad.point(0).fY, quad.point(1).fY, quad.point(2).fY,
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    1.f,              1.f,              1.f);
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix qinv;
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!q.invert(&qinv)) {
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix t = SkMatrix::MakeAll(tex.fLeft,    tex.fLeft, tex.fRight,
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        tex.fTop,  tex.fBottom,   tex.fTop,
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             1.f,          1.f,        1.f);
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix map;
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        map.setConcat(t, qinv);
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrixPriv::MapPointsWithStride(map, &vertices[0].fTextureCoords, sizeof(Vertex),
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          &vertices[0].fPosition, sizeof(Vertex), 4);
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Vertex, bool IsMultiTex> struct TexIdAssigner;
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Vertex> struct TexIdAssigner<Vertex, true> {
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void Assign(Vertex* vertices, int textureIdx) {
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[0].fTextureIdx = textureIdx;
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[1].fTextureIdx = textureIdx;
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[2].fTextureIdx = textureIdx;
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        vertices[3].fTextureIdx = textureIdx;
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Vertex> struct TexIdAssigner<Vertex, false> {
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void Assign(Vertex* vertices, int textureIdx) {}
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}  // anonymous namespace
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Vertex, bool IsMultiTex, GrAA AA>
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void tessellate_quad(const GrQuad& devQuad, const SkRect& srcRect, GrColor color,
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            GrSurfaceOrigin origin, Vertex* vertices, SkScalar iw, SkScalar ih,
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            int textureIdx) {
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect texRect = {
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iw * srcRect.fLeft,
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ih * srcRect.fTop,
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iw * srcRect.fRight,
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ih * srcRect.fBottom
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (origin == kBottomLeft_GrSurfaceOrigin) {
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        texRect.fTop = 1.f - texRect.fTop;
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        texRect.fBottom = 1.f - texRect.fBottom;
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    VertexAAHandler<AA, Vertex>::AssignPositionsAndTexCoords(vertices, devQuad, texRect);
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    vertices[0].fColor = color;
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    vertices[1].fColor = color;
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    vertices[2].fColor = color;
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    vertices[3].fColor = color;
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TexIdAssigner<Vertex, IsMultiTex>::Assign(vertices, textureIdx);
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Op that implements GrTextureOp::Make. It draws textured quads. Each quad can modulate against a
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * the texture by color. The blend with the destination is always src-over. The edges are non-AA.
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass TextureOp final : public GrMeshDrawOp {
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy,
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          GrSamplerState::Filter filter, GrColor color,
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          const SkRect& srcRect, const SkRect& dstRect,
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          GrAAType aaType, const SkMatrix& viewMatrix,
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          sk_sp<GrColorSpaceXform> csxf, bool allowSRBInputs) {
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return std::unique_ptr<GrDrawOp>(new TextureOp(std::move(proxy), filter, color, srcRect,
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                       dstRect, aaType, viewMatrix, std::move(csxf),
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                       allowSRBInputs));
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~TextureOp() override {
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fFinalized) {
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto proxies = this->proxies();
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < fProxyCnt; ++i) {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                proxies[i]->completedRead();
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fProxyCnt > 1) {
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                delete[] reinterpret_cast<const char*>(proxies);
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(1 == fProxyCnt);
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fProxy0->unref();
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return "TextureOp"; }
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void visitProxies(const VisitProxyFunc& func) const override {
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto proxies = this->proxies();
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fProxyCnt; ++i) {
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            func(proxies[i]);
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString dumpInfo() const override {
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString str;
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendf("AllowSRGBInputs: %d\n", fAllowSRGBInputs);
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendf("# draws: %d\n", fDraws.count());
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto proxies = this->proxies();
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fProxyCnt; ++i) {
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            str.appendf("Proxy ID %d: %d, Filter: %d\n", i, proxies[i]->uniqueID().asUInt(),
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        static_cast<int>(this->filters()[i]));
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fDraws.count(); ++i) {
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const Draw& draw = fDraws[i];
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            str.appendf(
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    "%d: Color: 0x%08x, ProxyIdx: %d, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] "
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    "Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n",
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    i, draw.fColor, draw.fTextureIdx, draw.fSrcRect.fLeft, draw.fSrcRect.fTop,
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw.fSrcRect.fRight, draw.fSrcRect.fBottom, draw.fQuad.points()[0].fX,
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw.fQuad.points()[0].fY, draw.fQuad.points()[1].fX, draw.fQuad.points()[1].fY,
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw.fQuad.points()[2].fX, draw.fQuad.points()[2].fY, draw.fQuad.points()[3].fX,
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw.fQuad.points()[3].fY);
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str += INHERITED::dumpInfo();
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return str;
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                GrPixelConfigIsClamped dstIsClamped) override {
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(!fFinalized);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(1 == fProxyCnt);
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFinalized = true;
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fProxy0->addPendingRead();
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fProxy0->unref();
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return RequiresDstTexture::kNo;
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    FixedFunctionFlags fixedFunctionFlags() const override {
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return this->aaType() == GrAAType::kMSAA ? FixedFunctionFlags::kUsesHWAA
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                 : FixedFunctionFlags::kNone;
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    DEFINE_OP_CLASS_ID
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This is used in a heursitic for choosing a code path. We don't care what happens with
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // really large rects, infs, nans, etc.
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot__attribute__((no_sanitize("float-cast-overflow")))
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t RectSizeAsSizeT(const SkRect& rect) {;
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return static_cast<size_t>(SkTMax(rect.width(), 1.f) * SkTMax(rect.height(), 1.f));
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMaxTextures = TextureGeometryProcessor::kMaxTextures;
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot              const SkRect& srcRect, const SkRect& dstRect, GrAAType aaType,
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot              const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs)
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : INHERITED(ClassID())
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fColorSpaceXform(std::move(csxf))
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fProxy0(proxy.release())
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fFilter0(filter)
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fProxyCnt(1)
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fAAType(static_cast<unsigned>(aaType))
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fFinalized(0)
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fAllowSRGBInputs(allowSRGBInputs ? 1 : 0) {
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(aaType != GrAAType::kMixedSamples);
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Draw& draw = fDraws.push_back();
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw.fSrcRect = srcRect;
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw.fTextureIdx = 0;
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw.fColor = color;
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw.fQuad.setFromMappedRect(dstRect, viewMatrix);
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds;
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds.setBounds(draw.fQuad.points(), 4);
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMaxApproxDstPixelArea = RectSizeAsSizeT(bounds);
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onPrepareDraws(Target* target) override {
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> proxiesSPs[kMaxTextures];
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto proxies = this->proxies();
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto filters = this->filters();
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fProxyCnt; ++i) {
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (!proxies[i]->instantiate(target->resourceProvider())) {
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            proxiesSPs[i] = sk_ref_sp(proxies[i]);
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool coverageAA = GrAAType::kCoverage == this->aaType();
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrGeometryProcessor> gp =
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                TextureGeometryProcessor::Make(proxiesSPs, fProxyCnt, std::move(fColorSpaceXform),
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               coverageAA, filters, *target->caps().shaderCaps());
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPipeline::InitArgs args;
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fProxy = target->proxy();
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fCaps = &target->caps();
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fResourceProvider = target->resourceProvider();
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fFlags = 0;
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fAllowSRGBInputs) {
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            args.fFlags |= GrPipeline::kAllowSRGBInputs_Flag;
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (GrAAType::kMSAA == this->aaType()) {
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            args.fFlags |= GrPipeline::kHWAntialias_Flag;
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const GrPipeline* pipeline = target->allocPipeline(args, GrProcessorSet::MakeEmptySet(),
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                           target->detachAppliedClip());
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int vstart;
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const GrBuffer* vbuffer;
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void* vdata = target->makeVertexSpace(gp->getVertexStride(), 4 * fDraws.count(), &vbuffer,
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              &vstart);
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!vdata) {
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("Could not allocate vertices\n");
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (1 == fProxyCnt) {
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrSurfaceOrigin origin = proxies[0]->origin();
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrTexture* texture = proxies[0]->priv().peekTexture();
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            float iw = 1.f / texture->width();
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            float ih = 1.f / texture->height();
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (coverageAA) {
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::AAVertex));
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto vertices = static_cast<TextureGeometryProcessor::AAVertex*>(vdata);
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < fDraws.count(); ++i) {
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    tessellate_quad<TextureGeometryProcessor::AAVertex, false, GrAA::kYes>(
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            vertices + 4 * i, iw, ih, 0);
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::Vertex));
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto vertices = static_cast<TextureGeometryProcessor::Vertex*>(vdata);
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < fDraws.count(); ++i) {
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    tessellate_quad<TextureGeometryProcessor::Vertex, false, GrAA::kNo>(
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            vertices + 4 * i, iw, ih, 0);
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrTexture* textures[kMaxTextures];
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            float iw[kMaxTextures];
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            float ih[kMaxTextures];
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int t = 0; t < fProxyCnt; ++t) {
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                textures[t] = proxies[t]->priv().peekTexture();
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                iw[t] = 1.f / textures[t]->width();
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                ih[t] = 1.f / textures[t]->height();
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (coverageAA) {
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(gp->getVertexStride() ==
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         sizeof(TextureGeometryProcessor::AAMultiTextureVertex));
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto vertices = static_cast<TextureGeometryProcessor::AAMultiTextureVertex*>(vdata);
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < fDraws.count(); ++i) {
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    auto tidx = fDraws[i].fTextureIdx;
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    GrSurfaceOrigin origin = proxies[tidx]->origin();
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    tessellate_quad<TextureGeometryProcessor::AAMultiTextureVertex, true,
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    GrAA::kYes>(fDraws[i].fQuad, fDraws[i].fSrcRect,
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                fDraws[i].fColor, origin, vertices + 4 * i,
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                iw[tidx], ih[tidx], tidx);
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(gp->getVertexStride() ==
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         sizeof(TextureGeometryProcessor::MultiTextureVertex));
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto vertices = static_cast<TextureGeometryProcessor::MultiTextureVertex*>(vdata);
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < fDraws.count(); ++i) {
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    auto tidx = fDraws[i].fTextureIdx;
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    GrSurfaceOrigin origin = proxies[tidx]->origin();
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    tessellate_quad<TextureGeometryProcessor::MultiTextureVertex, true, GrAA::kNo>(
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            vertices + 4 * i, iw[tidx], ih[tidx], tidx);
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPrimitiveType primitiveType =
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip;
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrMesh mesh(primitiveType);
641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fDraws.count() > 1) {
642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<const GrBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (!ibuffer) {
644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("Could not allocate quad indices\n");
645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            mesh.setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     GrResourceProvider::QuadCountOfQuadBuffer());
649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            mesh.setNonIndexedNonInstanced(4);
651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        mesh.setVertexData(vbuffer, vstart);
653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        target->draw(gp.get(), pipeline, mesh);
654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const auto* that = t->cast<TextureOp>();
658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const auto& shaderCaps = *caps.shaderCaps();
659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (this->aaType() != that->aaType()) {
663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Because of an issue where GrColorSpaceXform adds the same function every time it is used
666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // in a texture lookup, we only allow multiple textures when there is no transform.
667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && !fColorSpaceXform &&
668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold() &&
669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            that->fMaxApproxDstPixelArea <=
670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    shaderCaps.disableImageMultitexturingDstRectAreaThreshold()) {
671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int map[kMaxTextures];
672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int numNewProxies = this->mergeProxies(that, map, shaderCaps);
673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (numNewProxies < 0) {
674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (1 == fProxyCnt && numNewProxies) {
677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                void* mem = new char[(sizeof(GrSamplerState::Filter) + sizeof(GrTextureProxy*)) *
678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     kMaxTextures];
679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto proxies = reinterpret_cast<GrTextureProxy**>(mem);
680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                auto filters = reinterpret_cast<GrSamplerState::Filter*>(proxies + kMaxTextures);
681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                proxies[0] = fProxy0;
682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                filters[0] = fFilter0;
683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fProxyArray = proxies;
684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fProxyCnt += numNewProxies;
686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto thisProxies = fProxyArray;
687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto thatProxies = that->proxies();
688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto thatFilters = that->filters();
689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto thisFilters = reinterpret_cast<GrSamplerState::Filter*>(thisProxies +
690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    kMaxTextures);
691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < that->fProxyCnt; ++i) {
692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (map[i] < 0) {
693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    thatProxies[i]->addPendingRead();
694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    thisProxies[-map[i]] = thatProxies[i];
696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    thisFilters[-map[i]] = thatFilters[i];
697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    map[i] = -map[i];
698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int firstNewDraw = fDraws.count();
701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = firstNewDraw; i < fDraws.count(); ++i) {
703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fDraws[i].fTextureIdx = map[fDraws[i].fTextureIdx];
704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // We can get here when one of the ops is already multitextured but the other cannot
707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // be because of the dst rect size.
708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fProxyCnt > 1 || that->fProxyCnt > 1) {
709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fProxy0->uniqueID() != that->fProxy0->uniqueID() || fFilter0 != that->fFilter0) {
712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->joinBounds(*that);
717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMaxApproxDstPixelArea = SkTMax(that->fMaxApproxDstPixelArea, fMaxApproxDstPixelArea);
718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * Determines a mapping of indices from that's proxy array to this's proxy array. A negative map
723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * value means that's proxy should be added to this's proxy array at the absolute value of
724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * the map entry. If it is determined that the ops shouldn't combine their proxies then a
725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * negative value is returned. Otherwise, return value indicates the number of proxies that have
726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     * to be added to this op or, equivalently, the number of negative entries in map.
727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int mergeProxies(const TextureOp* that, int map[kMaxTextures], const GrShaderCaps& caps) const {
729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::fill_n(map, kMaxTextures, -kMaxTextures);
730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int sharedProxyCnt = 0;
731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto thisProxies = this->proxies();
732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto thisFilters = this->filters();
733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto thatProxies = that->proxies();
734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto thatFilters = that->filters();
735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fProxyCnt; ++i) {
736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int j = 0; j < that->fProxyCnt; ++j) {
737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (thisProxies[i]->uniqueID() == thatProxies[j]->uniqueID()) {
738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (thisFilters[i] != thatFilters[j]) {
739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        // In GL we don't currently support using the same texture with different
740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        // samplers. If we added support for sampler objects and a cap bit to know
741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        // it's ok to use different filter modes then we could support this.
742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        // Otherwise, we could also only allow a single filter mode for each op
743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        // instance.
744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return -1;
745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    map[j] = i;
747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    ++sharedProxyCnt;
748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int actualMaxTextures = SkTMin(caps.maxFragmentSamplers(), kMaxTextures);
753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int newProxyCnt = that->fProxyCnt - sharedProxyCnt;
754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (newProxyCnt + fProxyCnt > actualMaxTextures) {
755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return -1;
756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPixelConfig config = thisProxies[0]->config();
758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int nextSlot = fProxyCnt;
759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int j = 0; j < that->fProxyCnt; ++j) {
760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // We want to avoid making many shaders because of different permutations of shader
761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // based swizzle and sampler types. The approach taken here is to require the configs to
762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // be the same and to only allow already instantiated proxies that have the most
763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // common sampler type. Otherwise we don't merge.
764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (thatProxies[j]->config() != config) {
765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return -1;
766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (GrTexture* tex = thatProxies[j]->priv().peekTexture()) {
768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (tex->texturePriv().samplerType() != kTexture2DSampler_GrSLType) {
769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return -1;
770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (map[j] < 0) {
773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                map[j] = -(nextSlot++);
774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return newProxyCnt;
777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTextureProxy* const* proxies() const { return fProxyCnt > 1 ? fProxyArray : &fProxy0; }
782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrSamplerState::Filter* filters() const {
784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fProxyCnt > 1) {
785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return reinterpret_cast<const GrSamplerState::Filter*>(fProxyArray + kMaxTextures);
786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return &fFilter0;
788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct Draw {
791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect fSrcRect;
792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int fTextureIdx;
793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrQuad fQuad;
794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrColor fColor;
795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkSTArray<1, Draw, true> fDraws;
797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrColorSpaceXform> fColorSpaceXform;
798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Initially we store a single proxy ptr and a single filter. If we grow to have more than
799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // one proxy we instead store pointers to dynamically allocated arrays of size kMaxTextures
800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // followed by kMaxTextures filters.
801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    union {
802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrTextureProxy* fProxy0;
803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrTextureProxy** fProxyArray;
804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t fMaxApproxDstPixelArea;
806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrSamplerState::Filter fFilter0;
807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint8_t fProxyCnt;
808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned fAAType : 2;
809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Used to track whether fProxy is ref'ed or has a pending IO after finalize() is called.
810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned fFinalized : 1;
811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned fAllowSRGBInputs : 1;
812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrMeshDrawOp INHERITED;
814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int TextureGeometryProcessor::kMaxTextures;
817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int TextureOp::kMaxTextures;
818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}  // anonymous namespace
820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace GrTextureOp {
822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter,
824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               GrColor color, const SkRect& srcRect, const SkRect& dstRect,
825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               GrAAType aaType, const SkMatrix& viewMatrix,
826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs) {
827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!viewMatrix.hasPerspective());
828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, aaType, viewMatrix,
829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                           std::move(csxf), allowSRGBInputs);
830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}  // namespace GrTextureOp
833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if GR_TEST_UTILS
835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h"
836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContextPriv.h"
837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrProxyProvider.h"
838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGR_DRAW_OP_TEST_DEFINE(TextureOp) {
840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrSurfaceDesc desc;
841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fConfig = kRGBA_8888_GrPixelConfig;
842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fHeight = random->nextULessThan(90) + 10;
843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fWidth = random->nextULessThan(90) + 10;
844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fOrigin = random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBackingFit fit = random->nextBool() ? SkBackingFit::kApprox : SkBackingFit::kExact;
846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(desc, fit, SkBudgeted::kNo);
849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect rect = GrTest::TestRect(random);
851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect srcRect;
852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    srcRect.fLeft = random->nextRangeScalar(0.f, proxy->width() / 2.f);
853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    srcRect.fRight = random->nextRangeScalar(0.f, proxy->width()) + proxy->width() / 2.f;
854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    srcRect.fTop = random->nextRangeScalar(0.f, proxy->height() / 2.f);
855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    srcRect.fBottom = random->nextRangeScalar(0.f, proxy->height()) + proxy->height() / 2.f;
856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrColor color = SkColorToPremulGrColor(random->nextU());
858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrSamplerState::Filter filter = (GrSamplerState::Filter)random->nextULessThan(
859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto csxf = GrTest::TestColorXform(random);
861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool allowSRGBInputs = random->nextBool();
862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrAAType aaType = GrAAType::kNone;
863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (random->nextBool()) {
864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage;
865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, aaType, viewMatrix,
867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             std::move(csxf), allowSRGBInputs);
868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
871