GrNonAAFillRectOp.cpp revision 08d141534cb24a491edbf5db31cdc7b966ec8d72
19c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt/*
29c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt * Copyright 2015 Google Inc.
39c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt *
49c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt * Use of this source code is governed by a BSD-style license that can be
59c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt * found in the LICENSE file.
69c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt */
79c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
8bcf33d5c06f7560039797b6023f14466c75598edjoshualitt#include "GrNonAAFillRectBatch.h"
99c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
107539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon#include "GrBatchFlushState.h"
119c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#include "GrColor.h"
129c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#include "GrDefaultGeoProcFactory.h"
139c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#include "GrPrimitiveProcessor.h"
142244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt#include "GrResourceProvider.h"
15ae5b2c623b22b24ea7c0d6200298e5bc366faa63joshualitt#include "GrQuad.h"
1616b991390bb988b194a868ab8de66db4c21c7c13bsalomon#include "GrVertexBatch.h"
179c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
1808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonstatic const int kVertsPerInstance = 4;
1908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonstatic const int kIndicesPerInstance = 6;
202244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
212244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes
222244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    we  have explicit local coords and sometimes not. We *could* always provide explicit local
232244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    coords and just duplicate the positions when the caller hasn't provided a local coord rect,
242244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    but we haven't seen a use case which frequently switches between local rect and no local
252244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    rect draws.
262244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
272244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    The vertex attrib order is always pos, color, [local coords].
282244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt */
2906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemanstatic sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix,
3006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                          bool readsCoverage,
3106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                          bool hasExplicitLocalCoords,
3206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                          const SkMatrix* localMatrix) {
332244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    using namespace GrDefaultGeoProcFactory;
342244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    Color color(Color::kAttribute_Type);
352244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
362244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
378cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    // If we have perspective on the viewMatrix then we won't map on the CPU, nor will we map
388cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    // the local rect on the cpu (in case the localMatrix also has perspective).
398cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    // Otherwise, if we have a local rect, then we apply the localMatrix directly to the localRect
408cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    // to generate vertex local coords
418cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    if (viewMatrix.hasPerspective()) {
428cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        LocalCoords localCoords(hasExplicitLocalCoords ? LocalCoords::kHasExplicit_Type :
438cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt                                                         LocalCoords::kUsePosition_Type,
448cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt                                localMatrix);
4506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, viewMatrix);
468cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    } else if (hasExplicitLocalCoords) {
472244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
4806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
492244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    } else {
502244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        LocalCoords localCoords(LocalCoords::kUsePosition_Type, localMatrix);
5106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        return GrDefaultGeoProcFactory::MakeForDeviceSpace(color, coverage, localCoords,
5206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                           viewMatrix);
532244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
542244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt}
552244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
562244c27ea4db85df305fa09f664b7d75f637e7a9joshualittstatic void tesselate(intptr_t vertices,
572244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                      size_t vertexStride,
582244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                      GrColor color,
592244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                      const SkMatrix& viewMatrix,
602244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                      const SkRect& rect,
618cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt                      const GrQuad* localQuad) {
622244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
632244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
642244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    positions->setRectFan(rect.fLeft, rect.fTop,
652244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                          rect.fRight, rect.fBottom, vertexStride);
669c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
678cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    if (!viewMatrix.hasPerspective()) {
6808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        viewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerInstance);
698cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    }
708cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt
718cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    // Setup local coords
722244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    // TODO we should only do this if local coords are being read
738cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt    if (localQuad) {
742244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
7508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        for (int i = 0; i < kVertsPerInstance; i++) {
768cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt            SkPoint* coords = reinterpret_cast<SkPoint*>(vertices + kLocalOffset +
778cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt                              i * vertexStride);
788cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt            *coords = localQuad->point(i);
792244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        }
802244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
812244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
822244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    static const int kColorOffset = sizeof(SkPoint);
832244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    GrColor* vertColor = reinterpret_cast<GrColor*>(vertices + kColorOffset);
842244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    for (int j = 0; j < 4; ++j) {
852244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        *vertColor = color;
862244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
872244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
882244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt}
892244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
9008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonclass NonAAFillRectBatch : public GrVertexBatch {
919c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualittpublic:
9208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    DEFINE_BATCH_CLASS_ID
9308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
949c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt    struct Geometry {
959c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt        SkMatrix fViewMatrix;
969c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt        SkRect fRect;
978cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        GrQuad fLocalQuad;
989c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt        GrColor fColor;
999c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt    };
1009c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
10108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static NonAAFillRectBatch* Create() { return new NonAAFillRectBatch; }
10208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
10308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    const char* name() const override { return Name(); }
10408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
10508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkString dumpInfo() const override {
10608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkString str;
10708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        str.appendf("# batched: %d\n", fGeoData.count());
10808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        for (int i = 0; i < fGeoData.count(); ++i) {
10908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            str.append(DumpInfo(fGeoData[i], i));
11008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
11108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        str.append(INHERITED::dumpInfo());
11208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return str;
11308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
11408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
11508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void computePipelineOptimizations(GrInitInvariantOutput* color,
11608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                      GrInitInvariantOutput* coverage,
11708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                      GrBatchToXPOverrides* overrides) const override {
11808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // When this is called on a batch, there is only one geometry bundle
11908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        color->setKnownFourComponents(fGeoData[0].fColor);
12008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        InitInvariantOutputCoverage(coverage);
12108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
12208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
12308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
12408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
12508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        fOverrides = overrides;
12608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
12708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
12808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
12908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
13008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    // After seeding, the client should call init() so the Batch can initialize itself
13108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void init() {
13208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        const Geometry& geo = fGeoData[0];
13308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SetBounds(geo, &fBounds);
13408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
13508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
13608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void updateBoundsAfterAppend() {
13708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        const Geometry& geo = fGeoData.back();
13808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        UpdateBoundsAfterAppend(geo, &fBounds);
13908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
14008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
14108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonprivate:
142bcf33d5c06f7560039797b6023f14466c75598edjoshualitt    static const char* Name() { return "NonAAFillRectBatch"; }
1432244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
144783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips    static SkString DumpInfo(const Geometry& geo, int index) {
145e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        SkString str;
146783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
147783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips                    index,
148e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips                    geo.fColor,
149e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
150e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        return str;
151e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips    }
152e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips
1532244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
154ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                           const GrXPOverridesForBatch& overrides) {
1552244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        return true;
156ae41b3834301444cf27b8aa729b8ad36666bdc08joshualitt    }
1579c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
15806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
15906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                             const GrXPOverridesForBatch& overrides) {
16006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        sk_sp<GrGeometryProcessor> gp = make_gp(geo.fViewMatrix, overrides.readsCoverage(), true,
16106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                nullptr);
1629c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
1632244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        SkASSERT(gp->getVertexStride() ==
1642244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt                sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
1652244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        return gp;
1662244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
16787e4752fc1f7b079a65208e4b3543925a35c3e54joshualitt
1682244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
169ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                          const GrXPOverridesForBatch& overrides) {
1708cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &geo.fLocalQuad);
1712244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
17208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
17308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
17408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        out->setKnownSingleComponent(0xff);
17508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
17608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
17708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
17808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return rp->refQuadIndexBuffer();
17908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
18008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
18108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
18208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        geo.fViewMatrix.mapRect(outBounds, geo.fRect);
18308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
18408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
18508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
18608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkRect bounds = geo.fRect;
18708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        geo.fViewMatrix.mapRect(&bounds);
18808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        outBounds->join(bounds);
18908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
19008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
19108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectBatch() : INHERITED(ClassID()) {}
19208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
19308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void onPrepareDraws(Target* target) const override {
19408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
19508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!gp) {
19608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            SkDebugf("Couldn't create GrGeometryProcessor\n");
19708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return;
19808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
19908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
20008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        size_t vertexStride = gp->getVertexStride();
20108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        int instanceCount = fGeoData.count();
20208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
20308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
20408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        InstancedHelper helper;
20508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
20608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                     indexBuffer, kVertsPerInstance,
20708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                     kIndicesPerInstance, instanceCount);
20808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!vertices || !indexBuffer) {
20908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            SkDebugf("Could not allocate vertices\n");
21008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return;
21108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
21208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
21308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        for (int i = 0; i < instanceCount; i++) {
21408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
21508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                             i * kVertsPerInstance * vertexStride;
21608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
21708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
21808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        helper.recordDraw(target, gp.get());
21908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
22008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
22108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    const Geometry& seedGeometry() const { return fGeoData[0]; }
22208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
22308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
22408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        NonAAFillRectBatch* that = t->cast<NonAAFillRectBatch>();
22508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
22608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                    that->bounds(), caps)) {
22708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return false;
22808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
22908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
23008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
23108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return false;
23208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
23308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
23408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // In the event of two batches, one who can tweak, one who cannot, we just fall back to
23508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // not tweaking
23608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
23708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            fOverrides = that->fOverrides;
23808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
23908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
24008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
24108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        this->joinBounds(that->bounds());
24208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return true;
24308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
24408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
24508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    GrXPOverridesForBatch fOverrides;
24608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkSTArray<1, Geometry, true> fGeoData;
24708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
24808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    typedef GrVertexBatch INHERITED;
2492244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt};
2509c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
2518cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt// We handle perspective in the local matrix or viewmatrix with special batches
25208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonclass NonAAFillRectPerspectiveBatch : public GrVertexBatch {
2532244c27ea4db85df305fa09f664b7d75f637e7a9joshualittpublic:
25408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    DEFINE_BATCH_CLASS_ID
25508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
2562244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    struct Geometry {
2572244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        SkMatrix fViewMatrix;
2582244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        SkMatrix fLocalMatrix;
2592244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        SkRect fRect;
2602244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        SkRect fLocalRect;
2612244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        GrColor fColor;
2628cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        bool fHasLocalMatrix;
2638cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        bool fHasLocalRect;
2642244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    };
26587e4752fc1f7b079a65208e4b3543925a35c3e54joshualitt
26608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static NonAAFillRectPerspectiveBatch* Create() { return new NonAAFillRectPerspectiveBatch; }
26708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
26808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    const char* name() const override { return Name(); }
26908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
27008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkString dumpInfo() const override {
27108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkString str;
27208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        str.appendf("# batched: %d\n", fGeoData.count());
27308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        for (int i = 0; i < fGeoData.count(); ++i) {
27408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            str.append(DumpInfo(fGeoData[i], i));
27508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
27608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        str.append(INHERITED::dumpInfo());
27708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return str;
27808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
27908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
28008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void computePipelineOptimizations(GrInitInvariantOutput* color,
28108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                      GrInitInvariantOutput* coverage,
28208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                      GrBatchToXPOverrides* overrides) const override {
28308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // When this is called on a batch, there is only one geometry bundle
28408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        color->setKnownFourComponents(fGeoData[0].fColor);
28508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        InitInvariantOutputCoverage(coverage);
28608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
28708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
28808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
28908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
29008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        fOverrides = overrides;
29108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
29208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
29308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
29408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
29508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    // After seeding, the client should call init() so the Batch can initialize itself
29608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void init() {
29708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        const Geometry& geo = fGeoData[0];
29808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SetBounds(geo, &fBounds);
29908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
30008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
30108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void updateBoundsAfterAppend() {
30208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        const Geometry& geo = fGeoData.back();
30308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        UpdateBoundsAfterAppend(geo, &fBounds);
30408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
30508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
30608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomonprivate:
30708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static const char* Name() { return "NonAAFillRectPerspectiveBatch"; }
3089c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
309783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips    static SkString DumpInfo(const Geometry& geo, int index) {
310e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        SkString str;
311783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
312783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips                    index,
313e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips                    geo.fColor,
314e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
315e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        return str;
316e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips    }
317e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips
3182244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
319ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                           const GrXPOverridesForBatch& overrides) {
3208cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        // We could batch across perspective vm changes if we really wanted to
3218cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        return mine.fViewMatrix.cheapEqualTo(theirs.fViewMatrix) &&
3222120b6f2cc3070b16800bfb2ff05cf114c8e40b9joshualitt               mine.fHasLocalRect == theirs.fHasLocalRect &&
3238cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt               (!mine.fHasLocalMatrix || mine.fLocalMatrix.cheapEqualTo(theirs.fLocalMatrix));
3249c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt    }
3259c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
32606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
32706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                             const GrXPOverridesForBatch& overrides) {
32806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        sk_sp<GrGeometryProcessor> gp = make_gp(geo.fViewMatrix, overrides.readsCoverage(),
32906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                geo.fHasLocalRect,
33006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                geo.fHasLocalMatrix ? &geo.fLocalMatrix
33106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                                                                    : nullptr);
3328cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt
3338cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        SkASSERT(geo.fHasLocalRect ?
3348cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt             gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
3358cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt             gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
3362244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        return gp;
3379c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt    }
3389c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
3392244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
340ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                          const GrXPOverridesForBatch& overrides) {
3418cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        if (geo.fHasLocalRect) {
3428cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt            GrQuad quad(geo.fLocalRect);
3438cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt            tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &quad);
3448cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        } else {
3458cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt            tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, nullptr);
3468cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt        }
3472244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    }
348ae41b3834301444cf27b8aa729b8ad36666bdc08joshualitt
34908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
35008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        out->setKnownSingleComponent(0xff);
35108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
35208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
35308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
35408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return rp->refQuadIndexBuffer();
35508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
35608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
35708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
35808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        geo.fViewMatrix.mapRect(outBounds, geo.fRect);
35908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
36008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
36108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
36208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkRect bounds = geo.fRect;
36308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        geo.fViewMatrix.mapRect(&bounds);
36408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        outBounds->join(bounds);
36508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
36608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
36708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectPerspectiveBatch() : INHERITED(ClassID()) {}
36808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
36908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    void onPrepareDraws(Target* target) const override {
37008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
37108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!gp) {
37208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            SkDebugf("Couldn't create GrGeometryProcessor\n");
37308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return;
37408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
37508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
37608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        size_t vertexStride = gp->getVertexStride();
37708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        int instanceCount = fGeoData.count();
37808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
37908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
38008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        InstancedHelper helper;
38108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
38208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                     indexBuffer, kVertsPerInstance,
38308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                     kIndicesPerInstance, instanceCount);
38408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!vertices || !indexBuffer) {
38508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            SkDebugf("Could not allocate vertices\n");
38608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return;
38708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
38808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
38908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        for (int i = 0; i < instanceCount; i++) {
39008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
39108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                             i * kVertsPerInstance * vertexStride;
39208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
39308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
39408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        helper.recordDraw(target, gp.get());
39508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
39608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
39708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    const Geometry& seedGeometry() const { return fGeoData[0]; }
39808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
39908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
40008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        NonAAFillRectPerspectiveBatch* that = t->cast<NonAAFillRectPerspectiveBatch>();
40108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
40208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon                                    that->bounds(), caps)) {
40308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return false;
40408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
40508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
40608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
40708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            return false;
40808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
40908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
41008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // In the event of two batches, one who can tweak, one who cannot, we just fall back to
41108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        // not tweaking
41208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
41308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon            fOverrides = that->fOverrides;
41408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        }
41508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
41608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
41708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        this->joinBounds(that->bounds());
41808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        return true;
41908d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    }
42008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
42108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    GrXPOverridesForBatch fOverrides;
42208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    SkSTArray<1, Geometry, true> fGeoData;
42308d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon
42408d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    typedef GrVertexBatch INHERITED;
42508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon};
4262244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
42708d141534cb24a491edbf5db31cdc7b966ec8d72bsalomoninline static void append_to_batch(NonAAFillRectBatch* batch, GrColor color,
428aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkMatrix& viewMatrix, const SkRect& rect,
429aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkRect* localRect, const SkMatrix* localMatrix) {
4303566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    SkASSERT(!viewMatrix.hasPerspective() && (!localMatrix || !localMatrix->hasPerspective()));
43108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectBatch::Geometry& geo = batch->geoData()->push_back();
4323566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt
4333566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fColor = color;
4343566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fViewMatrix = viewMatrix;
4353566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fRect = rect;
4363566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt
4373566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    if (localRect && localMatrix) {
4383566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalQuad.setFromMappedRect(*localRect, *localMatrix);
4393566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    } else if (localRect) {
4403566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalQuad.set(*localRect);
4413566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    } else if (localMatrix) {
4423566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalQuad.setFromMappedRect(rect, *localMatrix);
44387e4752fc1f7b079a65208e4b3543925a35c3e54joshualitt    } else {
4443566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalQuad.set(rect);
4453566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    }
4463566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt}
4478cce8f139e4b91783722f11ccb6ac9bbdf8327e7joshualitt
44808d141534cb24a491edbf5db31cdc7b966ec8d72bsalomoninline static void append_to_batch(NonAAFillRectPerspectiveBatch* batch, GrColor color,
449aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkMatrix& viewMatrix, const SkRect& rect,
450aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkRect* localRect, const SkMatrix* localMatrix) {
4513566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    SkASSERT(viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective()));
45208d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectPerspectiveBatch::Geometry& geo = batch->geoData()->push_back();
4533566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt
4543566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fColor = color;
4553566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fViewMatrix = viewMatrix;
4563566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fRect = rect;
4573566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fHasLocalRect = SkToBool(localRect);
4583566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    geo.fHasLocalMatrix = SkToBool(localMatrix);
4593566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    if (localMatrix) {
4603566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalMatrix = *localMatrix;
46187e4752fc1f7b079a65208e4b3543925a35c3e54joshualitt    }
4623566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    if (localRect) {
4633566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt        geo.fLocalRect = *localRect;
4643566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    }
4653566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt
466aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt}
467aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
468aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualittnamespace GrNonAAFillRectBatch {
469aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
470aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualittGrDrawBatch* Create(GrColor color,
471aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                    const SkMatrix& viewMatrix,
472aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                    const SkRect& rect,
473aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                    const SkRect* localRect,
474aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                    const SkMatrix* localMatrix) {
47508d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectBatch* batch = NonAAFillRectBatch::Create();
476aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix);
477aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    batch->init();
478aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    return batch;
479aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt}
480aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
481aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualittGrDrawBatch* CreateWithPerspective(GrColor color,
482aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkMatrix& viewMatrix,
483aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkRect& rect,
484aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkRect* localRect,
485aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                                   const SkMatrix* localMatrix) {
48608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    NonAAFillRectPerspectiveBatch* batch = NonAAFillRectPerspectiveBatch::Create();
487aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix);
4883566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    batch->init();
4893566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt    return batch;
4909c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt}
4913566d44d852b2fc1773e41e80c0c19610aa6d43bjoshualitt
492aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualittbool Append(GrBatch* origBatch,
493aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            GrColor color,
494aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            const SkMatrix& viewMatrix,
495aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            const SkRect& rect,
496aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            const SkRect* localRect,
497aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            const SkMatrix* localMatrix) {
498aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    bool usePerspective = viewMatrix.hasPerspective() ||
499aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt                          (localMatrix && localMatrix->hasPerspective());
500aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
50108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon    if (usePerspective && origBatch->classID() != NonAAFillRectPerspectiveBatch::ClassID()) {
502aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        return false;
503aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    }
504aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
505aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    if (!usePerspective) {
50608d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        NonAAFillRectBatch* batch = origBatch->cast<NonAAFillRectBatch>();
507aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix);
508aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        batch->updateBoundsAfterAppend();
509aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    } else {
51008d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        NonAAFillRectPerspectiveBatch* batch = origBatch->cast<NonAAFillRectPerspectiveBatch>();
51108d141534cb24a491edbf5db31cdc7b966ec8d72bsalomon        const NonAAFillRectPerspectiveBatch::Geometry& geo = batch->geoData()->back();
512aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
513aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        if (!geo.fViewMatrix.cheapEqualTo(viewMatrix) ||
514aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            geo.fHasLocalRect != SkToBool(localRect) ||
515aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            geo.fHasLocalMatrix != SkToBool(localMatrix) ||
516aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            (geo.fHasLocalMatrix && !geo.fLocalMatrix.cheapEqualTo(*localMatrix))) {
517aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt            return false;
518aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        }
519aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
520aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix);
521aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        batch->updateBoundsAfterAppend();
522aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    }
523aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
524aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    return true;
525aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt}
526aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
5279c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt};
5289c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
5299c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt///////////////////////////////////////////////////////////////////////////////////////////////////
5309c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
5319c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#ifdef GR_TEST_UTILS
5329c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
5339c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#include "GrBatchTest.h"
5349c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
535abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonDRAW_BATCH_TEST_DEFINE(RectBatch) {
5362244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    GrColor color = GrRandomColor(random);
5372244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    SkRect rect = GrTest::TestRect(random);
5382244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    SkRect localRect = GrTest::TestRect(random);
5392244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
5402244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    SkMatrix localMatrix = GrTest::TestMatrix(random);
5412244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt
5422244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    bool hasLocalRect = random->nextBool();
5432244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt    bool hasLocalMatrix = random->nextBool();
544bcf33d5c06f7560039797b6023f14466c75598edjoshualitt    return GrNonAAFillRectBatch::Create(color, viewMatrix, rect,
545bcf33d5c06f7560039797b6023f14466c75598edjoshualitt                                        hasLocalRect ? &localRect : nullptr,
546bcf33d5c06f7560039797b6023f14466c75598edjoshualitt                                        hasLocalMatrix ? &localMatrix : nullptr);
5479c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt}
5489c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt
5499c80b5ff592caf1c18b43e98c85bc8340b3ac531joshualitt#endif
550