blob: b85b3aa13def51cf7f0ee8b7d7e4cd5c5dd2a7fc [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 *
cdalton397536c2016-03-25 12:15:03 -070037 * const GrBuffer* GetIndexBuffer(GrResourceProvider*)
joshualitt2ad37be2015-08-18 10:16:01 -070038 *
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
halcanary9d524f22016-03-29 09:03:52 -070062 void computePipelineOptimizations(GrInitInvariantOutput* color,
ethannicholasff210322015-11-24 12:10:10 -080063 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 {
halcanary9d524f22016-03-29 09:03:52 -070092 SkAutoTUnref<const GrGeometryProcessor> gp(Impl::CreateGP(this->seedGeometry(),
ethannicholasff210322015-11-24 12:10:10 -080093 fOverrides));
joshualitt2ad37be2015-08-18 10:16:01 -070094 if (!gp) {
95 SkDebugf("Couldn't create GrGeometryProcessor\n");
96 return;
97 }
98
joshualitt2ad37be2015-08-18 10:16:01 -070099 size_t vertexStride = gp->getVertexStride();
100 int instanceCount = fGeoData.count();
101
cdalton397536c2016-03-25 12:15:03 -0700102 SkAutoTUnref<const GrBuffer> indexBuffer(
joshualitt2ad37be2015-08-18 10:16:01 -0700103 Impl::GetIndexBuffer(target->resourceProvider()));
104 InstancedHelper helper;
105 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
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;
ethannicholasff210322015-11-24 12:10:10 -0800116 Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
joshualitt2ad37be2015-08-18 10:16:01 -0700117 }
bsalomon342bfc22016-04-01 06:06:20 -0700118 helper.recordDraw(target, gp);
joshualitt2ad37be2015-08-18 10:16:01 -0700119 }
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->pipeline(),
126 that->bounds(), caps)) {
127 return false;
128 }
129
ethannicholasff210322015-11-24 12:10:10 -0800130 if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
joshualitt2ad37be2015-08-18 10:16:01 -0700131 return false;
132 }
133
134 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
135 // not tweaking
ethannicholasff210322015-11-24 12:10:10 -0800136 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
137 fOverrides = that->fOverrides;
joshualitt2ad37be2015-08-18 10:16:01 -0700138 }
139
140 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
141 this->joinBounds(that->bounds());
142 return true;
143 }
144
ethannicholasff210322015-11-24 12:10:10 -0800145 GrXPOverridesForBatch fOverrides;
joshualitt2ad37be2015-08-18 10:16:01 -0700146 SkSTArray<1, Geometry, true> fGeoData;
reed1b55a962015-09-17 20:16:13 -0700147
148 typedef GrVertexBatch INHERITED;
joshualitt2ad37be2015-08-18 10:16:01 -0700149};
150
151#endif