• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrTInstanceBatch_DEFINED
9 #define GrTInstanceBatch_DEFINED
10 
11 #include "GrVertexBatch.h"
12 
13 #include "GrBatchFlushState.h"
14 
15 /**
16  * GrTInstanceBatch is an optional template to help with writing batches
17  * To use this template, The 'Impl' must define the following statics:
18  *     A Geometry struct
19  *
20  *     static const int kVertsPerInstance
21  *     static const int kIndicesPerInstance
22  *
23  *     const char* Name()
24  *
25  *     void InvariantOutputCoverage(GrInitInvariantOutput* out)
26  *
27  *     void SetBounds(const Geometry& seedGeometry, SkRect* outBounds)
28  *
29  *     void UpdateBoundsAfterAppend(const Geometry& lastGeometry, SkRect* currentBounds)
30  *
31  *     bool CanCombine(const Geometry& mine, const Geometry& theirs,
32  *                     const GrXPOverridesForBatch&)
33  *
34  *     const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry,
35  *                                         const GrXPOverridesForBatch& overrides)
36  *
37  *     const GrIndexBuffer* GetIndexBuffer(GrResourceProvider*)
38  *
39  *     Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
40  *               const GrXPOverridesForBatch& overrides)
41  */
42 template <typename Impl>
43 class GrTInstanceBatch : public GrVertexBatch {
44 public:
45     DEFINE_BATCH_CLASS_ID
46 
47     typedef typename Impl::Geometry Geometry;
48 
Create()49     static GrTInstanceBatch* Create() { return new GrTInstanceBatch; }
50 
name()51     const char* name() const override { return Impl::Name(); }
52 
dumpInfo()53     SkString dumpInfo() const override {
54         SkString str;
55         for (int i = 0; i < fGeoData.count(); ++i) {
56             str.append(Impl::DumpInfo(fGeoData[i], i));
57         }
58         str.append(INHERITED::dumpInfo());
59         return str;
60     }
61 
computePipelineOptimizations(GrInitInvariantOutput * color,GrInitInvariantOutput * coverage,GrBatchToXPOverrides * overrides)62     void computePipelineOptimizations(GrInitInvariantOutput* color,
63                                       GrInitInvariantOutput* coverage,
64                                       GrBatchToXPOverrides* overrides) const override {
65         // When this is called on a batch, there is only one geometry bundle
66         color->setKnownFourComponents(fGeoData[0].fColor);
67         Impl::InitInvariantOutputCoverage(coverage);
68     }
69 
initBatchTracker(const GrXPOverridesForBatch & overrides)70     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
71         overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
72         fOverrides = overrides;
73     }
74 
geoData()75     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
76 
77     // After seeding, the client should call init() so the Batch can initialize itself
init()78     void init() {
79         const Geometry& geo = fGeoData[0];
80         Impl::SetBounds(geo, &fBounds);
81     }
82 
updateBoundsAfterAppend()83     void updateBoundsAfterAppend() {
84         const Geometry& geo = fGeoData.back();
85         Impl::UpdateBoundsAfterAppend(geo, &fBounds);
86     }
87 
88 private:
GrTInstanceBatch()89     GrTInstanceBatch() : INHERITED(ClassID()) {}
90 
onPrepareDraws(Target * target)91     void onPrepareDraws(Target* target) const override {
92         SkAutoTUnref<const GrGeometryProcessor> gp(Impl::CreateGP(this->seedGeometry(),
93                                                                   fOverrides));
94         if (!gp) {
95             SkDebugf("Couldn't create GrGeometryProcessor\n");
96             return;
97         }
98 
99         target->initDraw(gp, this->pipeline());
100 
101         size_t vertexStride = gp->getVertexStride();
102         int instanceCount = fGeoData.count();
103 
104         SkAutoTUnref<const GrIndexBuffer> indexBuffer(
105                 Impl::GetIndexBuffer(target->resourceProvider()));
106         InstancedHelper helper;
107         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
108                                      indexBuffer, Impl::kVertsPerInstance,
109                                      Impl::kIndicesPerInstance, instanceCount);
110         if (!vertices || !indexBuffer) {
111             SkDebugf("Could not allocate vertices\n");
112             return;
113         }
114 
115         for (int i = 0; i < instanceCount; i++) {
116             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
117                              i * Impl::kVertsPerInstance * vertexStride;
118             Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
119         }
120         helper.recordDraw(target);
121     }
122 
seedGeometry()123     const Geometry& seedGeometry() const { return fGeoData[0]; }
124 
onCombineIfPossible(GrBatch * t,const GrCaps & caps)125     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
126         GrTInstanceBatch* that = t->cast<GrTInstanceBatch>();
127         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
128                                     that->bounds(), caps)) {
129             return false;
130         }
131 
132         if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
133             return false;
134         }
135 
136         // In the event of two batches, one who can tweak, one who cannot, we just fall back to
137         // not tweaking
138         if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
139             fOverrides = that->fOverrides;
140         }
141 
142         fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
143         this->joinBounds(that->bounds());
144         return true;
145     }
146 
147     GrXPOverridesForBatch fOverrides;
148     SkSTArray<1, Geometry, true> fGeoData;
149 
150     typedef GrVertexBatch INHERITED;
151 };
152 
153 #endif
154