Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: src/gpu/batches/GrBWFillRectBatch.cpp

Issue 1295773003: fill rect batch refactor into separate batches (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweaks Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrBWFillRectBatch.h" 8 #include "GrBWFillRectBatch.h"
9 9
10 #include "GrBatchFlushState.h" 10 #include "GrBatchFlushState.h"
11 #include "GrColor.h" 11 #include "GrColor.h"
12 #include "GrDefaultGeoProcFactory.h" 12 #include "GrDefaultGeoProcFactory.h"
13 #include "GrPrimitiveProcessor.h" 13 #include "GrPrimitiveProcessor.h"
14 #include "GrResourceProvider.h"
15 #include "GrTInstanceBatch.h"
14 #include "GrVertexBatch.h" 16 #include "GrVertexBatch.h"
15 17
16 class GrBatchFlushState; 18 // Common functions
17 class SkMatrix; 19 class BWFillRectBatchBase {
18 struct SkRect; 20 public:
19 21 static const int kVertsPerInstance = 4;
20 class BWFillRectBatch : public GrVertexBatch { 22 static const int kIndicesPerInstance = 6;
23
24 inline static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* rp) {
25 return rp->refQuadIndexBuffer();
26 }
27
28 template <typename Geometry>
29 inline static void SetBounds(const Geometry& geo, SkRect* outBounds) {
30 geo.fViewMatrix.mapRect(outBounds, geo.fRect);
31 }
32 };
33
34 /** We always use per-vertex colors so that rects can be batched across color ch anges. Sometimes
35 we have explicit local coords and sometimes not. We *could* always provide explicit local
36 coords and just duplicate the positions when the caller hasn't provided a lo cal coord rect,
37 but we haven't seen a use case which frequently switches between local rect and no local
38 rect draws.
39
40 The color param is used to determine whether the opaque hint can be set on t he draw state.
41 The caller must populate the vertex colors itself.
42
43 The vertex attrib order is always pos, color, [local coords].
44 */
45 static const GrGeometryProcessor* create_gp(const SkMatrix& viewMatrix,
46 bool readsCoverage,
47 bool hasExplicitLocalCoords,
48 const SkMatrix* localMatrix) {
49 using namespace GrDefaultGeoProcFactory;
50 Color color(Color::kAttribute_Type);
51 Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Ty pe);
52
53 // if we have a local rect, then we apply the localMatrix directly to the lo calRect to
54 // generate vertex local coords
55 if (hasExplicitLocalCoords) {
56 LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
57 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkM atrix::I());
58 } else {
59 LocalCoords localCoords(LocalCoords::kUsePosition_Type, localMatrix ? lo calMatrix : NULL);
60 return GrDefaultGeoProcFactory::CreateForDeviceSpace(color, coverage, lo calCoords,
61 viewMatrix);
62 }
63 }
64
65 static void tesselate(intptr_t vertices,
66 size_t vertexStride,
67 GrColor color,
68 const SkMatrix& viewMatrix,
69 const SkRect& rect,
70 const SkRect* localRect,
71 const SkMatrix* localMatrix) {
72 SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
73
74 positions->setRectFan(rect.fLeft, rect.fTop,
75 rect.fRight, rect.fBottom, vertexStride);
76 viewMatrix.mapPointsWithStride(positions, vertexStride, BWFillRectBatchBase: :kVertsPerInstance);
77
78 // TODO we should only do this if local coords are being read
79 if (localRect) {
80 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
81 SkPoint* coords = reinterpret_cast<SkPoint*>(vertices + kLocalOffset);
82 coords->setRectFan(localRect->fLeft, localRect->fTop,
83 localRect->fRight, localRect->fBottom,
84 vertexStride);
85 if (localMatrix) {
86 localMatrix->mapPointsWithStride(coords, vertexStride,
87 BWFillRectBatchBase::kVertsPerInsta nce);
88 }
89 }
90
91 static const int kColorOffset = sizeof(SkPoint);
92 GrColor* vertColor = reinterpret_cast<GrColor*>(vertices + kColorOffset);
93 for (int j = 0; j < 4; ++j) {
94 *vertColor = color;
95 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
96 }
97 }
98
99 class BWFillRectBatchNoLocalMatrixImp : public BWFillRectBatchBase {
100 public:
101 struct Geometry {
102 SkMatrix fViewMatrix;
103 SkRect fRect;
104 GrColor fColor;
105 };
106
107 inline static const char* Name() { return "BWFillRectBatchNoLocalMatrix"; }
108
109 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs,
110 const GrPipelineOptimizations& opts) {
111 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
112 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
113 // using vertex attributes in these cases, but haven't investigated that
114 return !opts.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs. fViewMatrix);
115 }
116
117 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo,
118 const GrPipelineOptimizati ons& opts) {
119 const GrGeometryProcessor* gp = create_gp(geo.fViewMatrix, opts.readsCov erage(), false,
120 NULL);
121
122 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi onColorAttr));
123 return gp;
124 }
125
126 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G eometry& geo,
127 const GrPipelineOptimizations& opts) {
128 tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect , NULL, NULL);
129 }
130 };
131
132 class BWFillRectBatchLocalMatrixImp : public BWFillRectBatchBase {
133 public:
134 struct Geometry {
135 SkMatrix fViewMatrix;
136 SkMatrix fLocalMatrix;
137 SkRect fRect;
138 GrColor fColor;
139 };
140
141 inline static const char* Name() { return "BWFillRectBatchLocalMatrix"; }
142
143 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs,
144 const GrPipelineOptimizations& opts) {
145 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
146 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
147 // using vertex attributes in these cases, but haven't investigated that
148 return !opts.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs. fViewMatrix);
149 }
150
151 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo,
152 const GrPipelineOptimizati ons& opts) {
153 const GrGeometryProcessor* gp = create_gp(geo.fViewMatrix, opts.readsCov erage(), false,
154 &geo.fLocalMatrix);
155
156 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi onColorAttr));
157 return gp;
158 }
159
160 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G eometry& geo,
161 const GrPipelineOptimizations& opts) {
162 tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect , NULL,
163 &geo.fLocalMatrix);
164 }
165 };
166
167 class BWFillRectBatchLocalRectImp : public BWFillRectBatchBase {
21 public: 168 public:
22 struct Geometry { 169 struct Geometry {
23 SkMatrix fViewMatrix; 170 SkMatrix fViewMatrix;
24 SkRect fRect; 171 SkRect fRect;
25 SkRect fLocalRect; 172 SkRect fLocalRect;
173 GrColor fColor;
174 };
175
176 inline static const char* Name() { return "BWFillRectBatchLocalRect"; }
177
178 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs,
179 const GrPipelineOptimizations& opts) {
180 return true;
181 }
182
183 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo,
184 const GrPipelineOptimizati ons& opts) {
185 const GrGeometryProcessor* gp = create_gp(geo.fViewMatrix, opts.readsCov erage(), true,
186 NULL);
187
188 SkASSERT(gp->getVertexStride() ==
189 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
190 return gp;
191 }
192
193 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G eometry& geo,
194 const GrPipelineOptimizations& opts) {
195 tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect , &geo.fLocalRect,
196 NULL);
197 }
198 };
199
200 class BWFillRectBatchLocalMatrixLocalRectImp : public BWFillRectBatchBase {
201 public:
202 struct Geometry {
203 SkMatrix fViewMatrix;
26 SkMatrix fLocalMatrix; 204 SkMatrix fLocalMatrix;
27 GrColor fColor; 205 SkRect fRect;
28 bool fHasLocalRect; 206 SkRect fLocalRect;
29 bool fHasLocalMatrix; 207 GrColor fColor;
30 }; 208 };
31 209
32 static GrDrawBatch* Create(const Geometry& geometry) { 210 inline static const char* Name() { return "BWFillRectBatchLocalMatrixLocalRe ct"; }
33 return SkNEW_ARGS(BWFillRectBatch, (geometry)); 211
34 } 212 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs,
35 213 const GrPipelineOptimizations& opts) {
36 const char* name() const override { return "RectBatch"; }
37
38 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
39 // When this is called on a batch, there is only one geometry bundle
40 out->setKnownFourComponents(fGeoData[0].fColor);
41 }
42
43 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
44 out->setKnownSingleComponent(0xff);
45 }
46
47 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
48
49 private:
50 BWFillRectBatch(const Geometry& geometry) {
51 this->initClassID<BWFillRectBatch>();
52 fGeoData.push_back(geometry);
53
54 fBounds = geometry.fRect;
55 geometry.fViewMatrix.mapRect(&fBounds);
56 }
57
58 GrColor color() const { return fBatch.fColor; }
59 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
60 bool colorIgnored() const { return fBatch.fColorIgnored; }
61 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
62 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
63 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
64 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
65 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
66
67 void initBatchTracker(const GrPipelineOptimizations& init) override {
68 // Handle any color overrides
69 if (!init.readsColor()) {
70 fGeoData[0].fColor = GrColor_ILLEGAL;
71 }
72 init.getOverrideColorIfSet(&fGeoData[0].fColor);
73
74 // setup batch properties
75 fBatch.fColorIgnored = !init.readsColor();
76 fBatch.fColor = fGeoData[0].fColor;
77 fBatch.fUsesLocalCoords = init.readsLocalCoords();
78 fBatch.fCoverageIgnored = !init.readsCoverage();
79 }
80
81 void onPrepareDraws(Target* target) override {
82 SkAutoTUnref<const GrGeometryProcessor> gp(this->createRectGP());
83 if (!gp) {
84 SkDebugf("Could not create GrGeometryProcessor\n");
85 return;
86 }
87
88 target->initDraw(gp, this->pipeline());
89
90 int instanceCount = fGeoData.count();
91 size_t vertexStride = gp->getVertexStride();
92 SkASSERT(this->hasLocalRect() ?
93 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordAttr) :
94 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr));
95 QuadHelper helper;
96 void* vertices = helper.init(target, vertexStride, instanceCount);
97
98 if (!vertices) {
99 return;
100 }
101
102 for (int i = 0; i < instanceCount; i++) {
103 const Geometry& geom = fGeoData[i];
104
105 intptr_t offset = reinterpret_cast<intptr_t>(vertices) +
106 kVerticesPerQuad * i * vertexStride;
107 SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
108
109 positions->setRectFan(geom.fRect.fLeft, geom.fRect.fTop,
110 geom.fRect.fRight, geom.fRect.fBottom, vertexS tride);
111 geom.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerti cesPerQuad);
112
113 // TODO we should only do this if local coords are being read
114 if (geom.fHasLocalRect) {
115 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor );
116 SkPoint* coords = reinterpret_cast<SkPoint*>(offset + kLocalOffs et);
117 coords->setRectFan(geom.fLocalRect.fLeft, geom.fLocalRect.fTop,
118 geom.fLocalRect.fRight, geom.fLocalRect.fBott om,
119 vertexStride);
120 if (geom.fHasLocalMatrix) {
121 geom.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVerticesPerQuad);
122 }
123 }
124
125 static const int kColorOffset = sizeof(SkPoint);
126 GrColor* vertColor = reinterpret_cast<GrColor*>(offset + kColorOffse t);
127 for (int j = 0; j < 4; ++j) {
128 *vertColor = geom.fColor;
129 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
130 }
131 }
132
133 helper.recordDraw(target);
134 }
135
136 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
137 BWFillRectBatch* that = t->cast<BWFillRectBatch>();
138 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
139 that->bounds(), caps)) {
140 return false;
141 }
142
143 if (this->hasLocalRect() != that->hasLocalRect()) {
144 return false;
145 }
146
147 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
148 if (!this->hasLocalRect() && this->usesLocalCoords()) {
149 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
150 return false;
151 }
152
153 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
154 return false;
155 }
156
157 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that ->localMatrix())) {
158 return false;
159 }
160 }
161
162 if (this->color() != that->color()) {
163 fBatch.fColor = GrColor_ILLEGAL;
164 }
165 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
166 this->joinBounds(that->bounds());
167 return true; 214 return true;
168 } 215 }
169 216
170 217 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo,
171 /** We always use per-vertex colors so that rects can be batched across colo r changes. Sometimes 218 const GrPipelineOptimizati ons& opts) {
172 we have explicit local coords and sometimes not. We *could* always prov ide explicit local 219 const GrGeometryProcessor* gp = create_gp(geo.fViewMatrix, opts.readsCov erage(), true,
173 coords and just duplicate the positions when the caller hasn't provided a local coord rect, 220 NULL);
174 but we haven't seen a use case which frequently switches between local r ect and no local 221
175 rect draws. 222 SkASSERT(gp->getVertexStride() ==
176 223 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
177 The color param is used to determine whether the opaque hint can be set on the draw state. 224 return gp;
178 The caller must populate the vertex colors itself. 225 }
179 226
180 The vertex attrib order is always pos, color, [local coords]. 227 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G eometry& geo,
181 */ 228 const GrPipelineOptimizations& opts) {
182 const GrGeometryProcessor* createRectGP() const { 229 tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect , &geo.fLocalRect,
183 using namespace GrDefaultGeoProcFactory; 230 &geo.fLocalMatrix);
184 Color color(Color::kAttribute_Type); 231 }
185 Coverage coverage(this->coverageIgnored() ? Coverage::kNone_Type : Cover age::kSolid_Type); 232 };
186 233
187 // if we have a local rect, then we apply the localMatrix directly to th e localRect to 234 typedef GrTInstanceBatch<BWFillRectBatchNoLocalMatrixImp> BWFillRectBatchSimple;
188 // generate vertex local coords 235 typedef GrTInstanceBatch<BWFillRectBatchLocalMatrixImp> BWFillRectBatchLocalMatr ix;
189 if (this->hasLocalRect()) { 236 typedef GrTInstanceBatch<BWFillRectBatchLocalRectImp> BWFillRectBatchLocalRect;
190 LocalCoords localCoords(LocalCoords::kHasExplicit_Type); 237 typedef GrTInstanceBatch<BWFillRectBatchLocalMatrixLocalRectImp> BWFillRectBatch LocalMatrixLocalRect;
191 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I());
192 } else {
193 LocalCoords localCoords(LocalCoords::kUsePosition_Type,
194 this->hasLocalMatrix() ? &this->localMatrix( ) : NULL);
195 return GrDefaultGeoProcFactory::CreateForDeviceSpace(color, coverage , localCoords,
196 this->viewMatri x());
197 }
198 }
199
200 struct BatchTracker {
201 GrColor fColor;
202 bool fUsesLocalCoords;
203 bool fColorIgnored;
204 bool fCoverageIgnored;
205 };
206
207 BatchTracker fBatch;
208 SkSTArray<1, Geometry, true> fGeoData;
209 };
210 238
211 namespace GrBWFillRectBatch { 239 namespace GrBWFillRectBatch {
212 GrDrawBatch* Create(GrColor color, 240 GrDrawBatch* Create(GrColor color,
213 const SkMatrix& viewMatrix, 241 const SkMatrix& viewMatrix,
214 const SkRect& rect, 242 const SkRect& rect,
215 const SkRect* localRect, 243 const SkRect* localRect,
216 const SkMatrix* localMatrix) { 244 const SkMatrix* localMatrix) {
217 BWFillRectBatch::Geometry geometry; 245 // TODO bubble these up as separate calls
218 geometry.fColor = color; 246 if (localRect && localMatrix) {
219 geometry.fViewMatrix = viewMatrix; 247 BWFillRectBatchLocalMatrixLocalRect* batch = BWFillRectBatchLocalMatrixL ocalRect::Create();
220 geometry.fRect = rect; 248 BWFillRectBatchLocalMatrixLocalRect::Geometry& geo = *batch->geometry();
221 249 geo.fColor = color;
222 if (localRect) { 250 geo.fViewMatrix = viewMatrix;
223 geometry.fHasLocalRect = true; 251 geo.fLocalMatrix = *localMatrix;
224 geometry.fLocalRect = *localRect; 252 geo.fRect = rect;
253 geo.fLocalRect = *localRect;
254 batch->init();
255 return batch;
256 } else if (localRect) {
257 BWFillRectBatchLocalRect* batch = BWFillRectBatchLocalRect::Create();
258 BWFillRectBatchLocalRect::Geometry& geo = *batch->geometry();
259 geo.fColor = color;
260 geo.fViewMatrix = viewMatrix;
261 geo.fRect = rect;
262 geo.fLocalRect = *localRect;
263 batch->init();
264 return batch;
265 } else if (localMatrix) {
266 BWFillRectBatchLocalMatrix* batch = BWFillRectBatchLocalMatrix::Create() ;
267 BWFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry();
268 geo.fColor = color;
269 geo.fViewMatrix = viewMatrix;
270 geo.fLocalMatrix = *localMatrix;
271 geo.fRect = rect;
272 batch->init();
273 return batch;
225 } else { 274 } else {
226 geometry.fHasLocalRect = false; 275 BWFillRectBatchSimple* batch = BWFillRectBatchSimple::Create();
227 } 276 BWFillRectBatchSimple::Geometry& geo = *batch->geometry();
228 277 geo.fColor = color;
229 if (localMatrix) { 278 geo.fViewMatrix = viewMatrix;
230 geometry.fHasLocalMatrix = true; 279 geo.fRect = rect;
231 geometry.fLocalMatrix = *localMatrix; 280 batch->init();
232 } else { 281 return batch;
233 geometry.fHasLocalMatrix = false; 282 }
234 }
235
236 return BWFillRectBatch::Create(geometry);
237 } 283 }
238 }; 284 };
239 285
240 //////////////////////////////////////////////////////////////////////////////// /////////////////// 286 //////////////////////////////////////////////////////////////////////////////// ///////////////////
241 287
242 #ifdef GR_TEST_UTILS 288 #ifdef GR_TEST_UTILS
243 289
244 #include "GrBatchTest.h" 290 #include "GrBatchTest.h"
245 291
246 DRAW_BATCH_TEST_DEFINE(RectBatch) { 292 DRAW_BATCH_TEST_DEFINE(RectBatch) {
247 BWFillRectBatch::Geometry geometry; 293 GrColor color = GrRandomColor(random);
248 geometry.fColor = GrRandomColor(random); 294 SkRect rect = GrTest::TestRect(random);
295 SkRect localRect = GrTest::TestRect(random);
296 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
297 SkMatrix localMatrix = GrTest::TestMatrix(random);
249 298
250 geometry.fRect = GrTest::TestRect(random); 299 bool hasLocalRect = random->nextBool();
251 geometry.fHasLocalRect = random->nextBool(); 300 bool hasLocalMatrix = random->nextBool();
252 301 return GrBWFillRectBatch::Create(color, viewMatrix, rect, hasLocalRect ? &lo calRect : nullptr,
253 if (geometry.fHasLocalRect) { 302 hasLocalMatrix ? &localMatrix : nullptr);
254 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
255 geometry.fLocalRect = GrTest::TestRect(random);
256 } else {
257 geometry.fViewMatrix = GrTest::TestMatrix(random);
258 }
259
260 geometry.fHasLocalMatrix = random->nextBool();
261 if (geometry.fHasLocalMatrix) {
262 geometry.fLocalMatrix = GrTest::TestMatrix(random);
263 }
264
265 return BWFillRectBatch::Create(geometry);
266 } 303 }
267 304
268 #endif 305 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698