12ad37be2b1f596a163e889ae0282227055c6b661joshualitt/*
22ad37be2b1f596a163e889ae0282227055c6b661joshualitt * Copyright 2015 Google Inc.
32ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
42ad37be2b1f596a163e889ae0282227055c6b661joshualitt * Use of this source code is governed by a BSD-style license that can be
52ad37be2b1f596a163e889ae0282227055c6b661joshualitt * found in the LICENSE file.
62ad37be2b1f596a163e889ae0282227055c6b661joshualitt */
72ad37be2b1f596a163e889ae0282227055c6b661joshualitt
82ad37be2b1f596a163e889ae0282227055c6b661joshualitt#ifndef GrTInstanceBatch_DEFINED
92ad37be2b1f596a163e889ae0282227055c6b661joshualitt#define GrTInstanceBatch_DEFINED
102ad37be2b1f596a163e889ae0282227055c6b661joshualitt
112ad37be2b1f596a163e889ae0282227055c6b661joshualitt#include "GrVertexBatch.h"
122ad37be2b1f596a163e889ae0282227055c6b661joshualitt
132ad37be2b1f596a163e889ae0282227055c6b661joshualitt#include "GrBatchFlushState.h"
142ad37be2b1f596a163e889ae0282227055c6b661joshualitt
152ad37be2b1f596a163e889ae0282227055c6b661joshualitt/**
162ad37be2b1f596a163e889ae0282227055c6b661joshualitt * GrTInstanceBatch is an optional template to help with writing batches
172ad37be2b1f596a163e889ae0282227055c6b661joshualitt * To use this template, The 'Impl' must define the following statics:
182ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     A Geometry struct
192ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
202ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     static const int kVertsPerInstance
212ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     static const int kIndicesPerInstance
222ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
232ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     const char* Name()
242ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
252244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt *     void InvariantOutputCoverage(GrInitInvariantOutput* out)
262244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt *
272244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt *     void SetBounds(const Geometry& seedGeometry, SkRect* outBounds)
282244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt *
29aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt *     void UpdateBoundsAfterAppend(const Geometry& lastGeometry, SkRect* currentBounds)
30aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt *
312ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     bool CanCombine(const Geometry& mine, const Geometry& theirs,
32ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas *                     const GrXPOverridesForBatch&)
332ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
342ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry,
35ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas *                                         const GrXPOverridesForBatch& overrides)
362ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
372ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     const GrIndexBuffer* GetIndexBuffer(GrResourceProvider*)
382ad37be2b1f596a163e889ae0282227055c6b661joshualitt *
392ad37be2b1f596a163e889ae0282227055c6b661joshualitt *     Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
40ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas *               const GrXPOverridesForBatch& overrides)
412ad37be2b1f596a163e889ae0282227055c6b661joshualitt */
422ad37be2b1f596a163e889ae0282227055c6b661joshualitttemplate <typename Impl>
432ad37be2b1f596a163e889ae0282227055c6b661joshualittclass GrTInstanceBatch : public GrVertexBatch {
442ad37be2b1f596a163e889ae0282227055c6b661joshualittpublic:
451b55a963a2374a14bb82eb887bb99ee91680f0ebreed    DEFINE_BATCH_CLASS_ID
461b55a963a2374a14bb82eb887bb99ee91680f0ebreed
472ad37be2b1f596a163e889ae0282227055c6b661joshualitt    typedef typename Impl::Geometry Geometry;
482ad37be2b1f596a163e889ae0282227055c6b661joshualitt
49385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    static GrTInstanceBatch* Create() { return new GrTInstanceBatch; }
502ad37be2b1f596a163e889ae0282227055c6b661joshualitt
512ad37be2b1f596a163e889ae0282227055c6b661joshualitt    const char* name() const override { return Impl::Name(); }
522ad37be2b1f596a163e889ae0282227055c6b661joshualitt
53e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips    SkString dumpInfo() const override {
54e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        SkString str;
55e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        for (int i = 0; i < fGeoData.count(); ++i) {
56783a4da10ba08187a5029d74cfa1507ac1b13307robertphillips            str.append(Impl::DumpInfo(fGeoData[i], i));
57e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        }
58e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        str.append(INHERITED::dumpInfo());
59e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips        return str;
60e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips    }
61e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips
62ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas    void computePipelineOptimizations(GrInitInvariantOutput* color,
63ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                                      GrInitInvariantOutput* coverage,
64ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                                      GrBatchToXPOverrides* overrides) const override {
652ad37be2b1f596a163e889ae0282227055c6b661joshualitt        // When this is called on a batch, there is only one geometry bundle
66ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        color->setKnownFourComponents(fGeoData[0].fColor);
67ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        Impl::InitInvariantOutputCoverage(coverage);
682ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
692ad37be2b1f596a163e889ae0282227055c6b661joshualitt
70ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
71ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
72ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        fOverrides = overrides;
732ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
742ad37be2b1f596a163e889ae0282227055c6b661joshualitt
752ad37be2b1f596a163e889ae0282227055c6b661joshualitt    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
762ad37be2b1f596a163e889ae0282227055c6b661joshualitt
77aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    // After seeding, the client should call init() so the Batch can initialize itself
782ad37be2b1f596a163e889ae0282227055c6b661joshualitt    void init() {
792ad37be2b1f596a163e889ae0282227055c6b661joshualitt        const Geometry& geo = fGeoData[0];
802244c27ea4db85df305fa09f664b7d75f637e7a9joshualitt        Impl::SetBounds(geo, &fBounds);
812ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
822ad37be2b1f596a163e889ae0282227055c6b661joshualitt
83aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    void updateBoundsAfterAppend() {
84aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        const Geometry& geo = fGeoData.back();
85aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt        Impl::UpdateBoundsAfterAppend(geo, &fBounds);
862ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
872ad37be2b1f596a163e889ae0282227055c6b661joshualitt
88aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualittprivate:
89aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt    GrTInstanceBatch() : INHERITED(ClassID()) {}
90aa37a96d554c5be7907ce04ee1ef843d0521eafbjoshualitt
91144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt    void onPrepareDraws(Target* target) const override {
92ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        SkAutoTUnref<const GrGeometryProcessor> gp(Impl::CreateGP(this->seedGeometry(),
93ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                                                                  fOverrides));
942ad37be2b1f596a163e889ae0282227055c6b661joshualitt        if (!gp) {
952ad37be2b1f596a163e889ae0282227055c6b661joshualitt            SkDebugf("Couldn't create GrGeometryProcessor\n");
962ad37be2b1f596a163e889ae0282227055c6b661joshualitt            return;
972ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
982ad37be2b1f596a163e889ae0282227055c6b661joshualitt
992ad37be2b1f596a163e889ae0282227055c6b661joshualitt        target->initDraw(gp, this->pipeline());
1002ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1012ad37be2b1f596a163e889ae0282227055c6b661joshualitt        size_t vertexStride = gp->getVertexStride();
1022ad37be2b1f596a163e889ae0282227055c6b661joshualitt        int instanceCount = fGeoData.count();
1032ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1042ad37be2b1f596a163e889ae0282227055c6b661joshualitt        SkAutoTUnref<const GrIndexBuffer> indexBuffer(
1052ad37be2b1f596a163e889ae0282227055c6b661joshualitt                Impl::GetIndexBuffer(target->resourceProvider()));
1062ad37be2b1f596a163e889ae0282227055c6b661joshualitt        InstancedHelper helper;
1072ad37be2b1f596a163e889ae0282227055c6b661joshualitt        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
1082ad37be2b1f596a163e889ae0282227055c6b661joshualitt                                     indexBuffer, Impl::kVertsPerInstance,
1092ad37be2b1f596a163e889ae0282227055c6b661joshualitt                                     Impl::kIndicesPerInstance, instanceCount);
1102ad37be2b1f596a163e889ae0282227055c6b661joshualitt        if (!vertices || !indexBuffer) {
1112ad37be2b1f596a163e889ae0282227055c6b661joshualitt            SkDebugf("Could not allocate vertices\n");
1122ad37be2b1f596a163e889ae0282227055c6b661joshualitt            return;
1132ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
1142ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1152ad37be2b1f596a163e889ae0282227055c6b661joshualitt        for (int i = 0; i < instanceCount; i++) {
1162ad37be2b1f596a163e889ae0282227055c6b661joshualitt            intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
1172ad37be2b1f596a163e889ae0282227055c6b661joshualitt                             i * Impl::kVertsPerInstance * vertexStride;
118ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas            Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
1192ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
1202ad37be2b1f596a163e889ae0282227055c6b661joshualitt        helper.recordDraw(target);
1212ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
1222ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1232ad37be2b1f596a163e889ae0282227055c6b661joshualitt    const Geometry& seedGeometry() const { return fGeoData[0]; }
1242ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1252ad37be2b1f596a163e889ae0282227055c6b661joshualitt    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
1262ad37be2b1f596a163e889ae0282227055c6b661joshualitt        GrTInstanceBatch* that = t->cast<GrTInstanceBatch>();
1272ad37be2b1f596a163e889ae0282227055c6b661joshualitt        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
1282ad37be2b1f596a163e889ae0282227055c6b661joshualitt                                    that->bounds(), caps)) {
1292ad37be2b1f596a163e889ae0282227055c6b661joshualitt            return false;
1302ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
1312ad37be2b1f596a163e889ae0282227055c6b661joshualitt
132ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
1332ad37be2b1f596a163e889ae0282227055c6b661joshualitt            return false;
1342ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
1352ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1362ad37be2b1f596a163e889ae0282227055c6b661joshualitt        // In the event of two batches, one who can tweak, one who cannot, we just fall back to
1372ad37be2b1f596a163e889ae0282227055c6b661joshualitt        // not tweaking
138ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
139ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas            fOverrides = that->fOverrides;
1402ad37be2b1f596a163e889ae0282227055c6b661joshualitt        }
1412ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1422ad37be2b1f596a163e889ae0282227055c6b661joshualitt        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
1432ad37be2b1f596a163e889ae0282227055c6b661joshualitt        this->joinBounds(that->bounds());
1442ad37be2b1f596a163e889ae0282227055c6b661joshualitt        return true;
1452ad37be2b1f596a163e889ae0282227055c6b661joshualitt    }
1462ad37be2b1f596a163e889ae0282227055c6b661joshualitt
147ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas    GrXPOverridesForBatch fOverrides;
1482ad37be2b1f596a163e889ae0282227055c6b661joshualitt    SkSTArray<1, Geometry, true> fGeoData;
1491b55a963a2374a14bb82eb887bb99ee91680f0ebreed
1501b55a963a2374a14bb82eb887bb99ee91680f0ebreed    typedef GrVertexBatch INHERITED;
1512ad37be2b1f596a163e889ae0282227055c6b661joshualitt};
1522ad37be2b1f596a163e889ae0282227055c6b661joshualitt
1532ad37be2b1f596a163e889ae0282227055c6b661joshualitt#endif
154