blob: 22d4f527920feb9d62a879f2d51e3d9a0f84a384 [file] [log] [blame]
joshualitt2ad37be2015-08-18 10:16:01 -07001/*
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 *
joshualitt2244c272015-08-21 10:33:15 -070025 * void InvariantOutputCoverage(GrInitInvariantOutput* out)
26 *
27 * void SetBounds(const Geometry& seedGeometry, SkRect* outBounds)
28 *
joshualittaa37a962015-09-18 13:03:25 -070029 * void UpdateBoundsAfterAppend(const Geometry& lastGeometry, SkRect* currentBounds)
30 *
joshualitt2ad37be2015-08-18 10:16:01 -070031 * bool CanCombine(const Geometry& mine, const Geometry& theirs,
ethannicholasff210322015-11-24 12:10:10 -080032 * const GrXPOverridesForBatch&)
joshualitt2ad37be2015-08-18 10:16:01 -070033 *
34 * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry,
ethannicholasff210322015-11-24 12:10:10 -080035 * const GrXPOverridesForBatch& overrides)
joshualitt2ad37be2015-08-18 10:16:01 -070036 *
37 * const GrIndexBuffer* GetIndexBuffer(GrResourceProvider*)
38 *
39 * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -080040 * const GrXPOverridesForBatch& overrides)
joshualitt2ad37be2015-08-18 10:16:01 -070041 */
42template <typename Impl>
43class GrTInstanceBatch : public GrVertexBatch {
44public:
reed1b55a962015-09-17 20:16:13 -070045 DEFINE_BATCH_CLASS_ID
46
joshualitt2ad37be2015-08-18 10:16:01 -070047 typedef typename Impl::Geometry Geometry;
48
halcanary385fe4d2015-08-26 13:07:48 -070049 static GrTInstanceBatch* Create() { return new GrTInstanceBatch; }
joshualitt2ad37be2015-08-18 10:16:01 -070050
51 const char* name() const override { return Impl::Name(); }
52
robertphillipse004bfc2015-11-16 09:06:59 -080053 SkString dumpInfo() const override {
54 SkString str;
55 for (int i = 0; i < fGeoData.count(); ++i) {
robertphillips783a4da2015-11-19 14:00:02 -080056 str.append(Impl::DumpInfo(fGeoData[i], i));
robertphillipse004bfc2015-11-16 09:06:59 -080057 }
58 str.append(INHERITED::dumpInfo());
59 return str;
60 }
61
ethannicholasff210322015-11-24 12:10:10 -080062 void computePipelineOptimizations(GrInitInvariantOutput* color,
63 GrInitInvariantOutput* coverage,
64 GrBatchToXPOverrides* overrides) const override {
joshualitt2ad37be2015-08-18 10:16:01 -070065 // When this is called on a batch, there is only one geometry bundle
ethannicholasff210322015-11-24 12:10:10 -080066 color->setKnownFourComponents(fGeoData[0].fColor);
67 Impl::InitInvariantOutputCoverage(coverage);
joshualitt2ad37be2015-08-18 10:16:01 -070068 }
69
ethannicholasff210322015-11-24 12:10:10 -080070 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
71 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
72 fOverrides = overrides;
joshualitt2ad37be2015-08-18 10:16:01 -070073 }
74
75 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
76
joshualittaa37a962015-09-18 13:03:25 -070077 // After seeding, the client should call init() so the Batch can initialize itself
joshualitt2ad37be2015-08-18 10:16:01 -070078 void init() {
79 const Geometry& geo = fGeoData[0];
joshualitt2244c272015-08-21 10:33:15 -070080 Impl::SetBounds(geo, &fBounds);
joshualitt2ad37be2015-08-18 10:16:01 -070081 }
82
joshualittaa37a962015-09-18 13:03:25 -070083 void updateBoundsAfterAppend() {
84 const Geometry& geo = fGeoData.back();
85 Impl::UpdateBoundsAfterAppend(geo, &fBounds);
joshualitt2ad37be2015-08-18 10:16:01 -070086 }
87
joshualittaa37a962015-09-18 13:03:25 -070088private:
89 GrTInstanceBatch() : INHERITED(ClassID()) {}
90
joshualitt144c3c82015-11-30 12:30:13 -080091 void onPrepareDraws(Target* target) const override {
ethannicholasff210322015-11-24 12:10:10 -080092 SkAutoTUnref<const GrGeometryProcessor> gp(Impl::CreateGP(this->seedGeometry(),
93 fOverrides));
joshualitt2ad37be2015-08-18 10:16:01 -070094 if (!gp) {
95 SkDebugf("Couldn't create GrGeometryProcessor\n");
96 return;
97 }
98
egdaniel0e1853c2016-03-17 11:35:45 -070099 target->initDraw(gp);
joshualitt2ad37be2015-08-18 10:16:01 -0700100
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;
ethannicholasff210322015-11-24 12:10:10 -0800118 Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
joshualitt2ad37be2015-08-18 10:16:01 -0700119 }
120 helper.recordDraw(target);
121 }
122
123 const Geometry& seedGeometry() const { return fGeoData[0]; }
124
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
ethannicholasff210322015-11-24 12:10:10 -0800132 if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
joshualitt2ad37be2015-08-18 10:16:01 -0700133 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
ethannicholasff210322015-11-24 12:10:10 -0800138 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
139 fOverrides = that->fOverrides;
joshualitt2ad37be2015-08-18 10:16:01 -0700140 }
141
142 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
143 this->joinBounds(that->bounds());
144 return true;
145 }
146
ethannicholasff210322015-11-24 12:10:10 -0800147 GrXPOverridesForBatch fOverrides;
joshualitt2ad37be2015-08-18 10:16:01 -0700148 SkSTArray<1, Geometry, true> fGeoData;
reed1b55a962015-09-17 20:16:13 -0700149
150 typedef GrVertexBatch INHERITED;
joshualitt2ad37be2015-08-18 10:16:01 -0700151};
152
153#endif