OLD | NEW |
| (Empty) |
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* curren
tBounds) | |
30 * | |
31 * bool CanCombine(const Geometry& mine, const Geometry& theirs, | |
32 * const GrXPOverridesForBatch&) | |
33 * | |
34 * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, | |
35 * const GrXPOverridesForBatch& override
s) | |
36 * | |
37 * const GrBuffer* 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 | |
49 static GrTInstanceBatch* Create() { return new GrTInstanceBatch; } | |
50 | |
51 const char* name() const override { return Impl::Name(); } | |
52 | |
53 SkString dumpInfo() const override { | |
54 SkString str; | |
55 str.appendf("# batched: %d\n", fGeoData.count()); | |
56 for (int i = 0; i < fGeoData.count(); ++i) { | |
57 str.append(Impl::DumpInfo(fGeoData[i], i)); | |
58 } | |
59 str.append(INHERITED::dumpInfo()); | |
60 return str; | |
61 } | |
62 | |
63 void computePipelineOptimizations(GrInitInvariantOutput* color, | |
64 GrInitInvariantOutput* coverage, | |
65 GrBatchToXPOverrides* overrides) const ove
rride { | |
66 // When this is called on a batch, there is only one geometry bundle | |
67 color->setKnownFourComponents(fGeoData[0].fColor); | |
68 Impl::InitInvariantOutputCoverage(coverage); | |
69 } | |
70 | |
71 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | |
72 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | |
73 fOverrides = overrides; | |
74 } | |
75 | |
76 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
77 | |
78 // After seeding, the client should call init() so the Batch can initialize
itself | |
79 void init() { | |
80 const Geometry& geo = fGeoData[0]; | |
81 Impl::SetBounds(geo, &fBounds); | |
82 } | |
83 | |
84 void updateBoundsAfterAppend() { | |
85 const Geometry& geo = fGeoData.back(); | |
86 Impl::UpdateBoundsAfterAppend(geo, &fBounds); | |
87 } | |
88 | |
89 private: | |
90 GrTInstanceBatch() : INHERITED(ClassID()) {} | |
91 | |
92 void onPrepareDraws(Target* target) const override { | |
93 sk_sp<GrGeometryProcessor> gp(Impl::MakeGP(this->seedGeometry(), fOverri
des)); | |
94 if (!gp) { | |
95 SkDebugf("Couldn't create GrGeometryProcessor\n"); | |
96 return; | |
97 } | |
98 | |
99 size_t vertexStride = gp->getVertexStride(); | |
100 int instanceCount = fGeoData.count(); | |
101 | |
102 SkAutoTUnref<const GrBuffer> indexBuffer( | |
103 Impl::GetIndexBuffer(target->resourceProvider())); | |
104 InstancedHelper helper; | |
105 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexS
tride, | |
106 indexBuffer, Impl::kVertsPerInstance, | |
107 Impl::kIndicesPerInstance, instanceCount); | |
108 if (!vertices || !indexBuffer) { | |
109 SkDebugf("Could not allocate vertices\n"); | |
110 return; | |
111 } | |
112 | |
113 for (int i = 0; i < instanceCount; i++) { | |
114 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + | |
115 i * Impl::kVertsPerInstance * vertexStride; | |
116 Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides); | |
117 } | |
118 helper.recordDraw(target, gp.get()); | |
119 } | |
120 | |
121 const Geometry& seedGeometry() const { return fGeoData[0]; } | |
122 | |
123 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | |
124 GrTInstanceBatch* that = t->cast<GrTInstanceBatch>(); | |
125 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | |
126 that->bounds(), caps)) { | |
127 return false; | |
128 } | |
129 | |
130 if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverr
ides)) { | |
131 return false; | |
132 } | |
133 | |
134 // In the event of two batches, one who can tweak, one who cannot, we ju
st fall back to | |
135 // not tweaking | |
136 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakA
lphaForCoverage()) { | |
137 fOverrides = that->fOverrides; | |
138 } | |
139 | |
140 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | |
141 this->joinBounds(that->bounds()); | |
142 return true; | |
143 } | |
144 | |
145 GrXPOverridesForBatch fOverrides; | |
146 SkSTArray<1, Geometry, true> fGeoData; | |
147 | |
148 typedef GrVertexBatch INHERITED; | |
149 }; | |
150 | |
151 #endif | |
OLD | NEW |