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

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

Issue 1287433003: Create GrRectBatchFactory (Closed) Base URL: https://skia.googlesource.com/skia.git@batchfactory1
Patch Set: 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
« no previous file with comments | « src/gpu/batches/GrRectBatch.h ('k') | src/gpu/batches/GrRectBatchFactory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "GrRectBatch.h" 8 #include "GrRectBatch.h"
9 9
10 #include "GrBatch.h"
11 #include "GrBatchTarget.h" 10 #include "GrBatchTarget.h"
12 #include "GrBatchTest.h"
13 #include "GrDefaultGeoProcFactory.h" 11 #include "GrDefaultGeoProcFactory.h"
14 #include "GrPrimitiveProcessor.h" 12 #include "GrPrimitiveProcessor.h"
15 13
16 class RectBatch : public GrBatch { 14 void GrRectBatch::initBatchTracker(const GrPipelineInfo& init) {
17 public: 15 // Handle any color overrides
18 struct Geometry { 16 if (!init.readsColor()) {
19 SkMatrix fViewMatrix; 17 fGeoData[0].fColor = GrColor_ILLEGAL;
20 SkRect fRect; 18 }
21 SkRect fLocalRect; 19 init.getOverrideColorIfSet(&fGeoData[0].fColor);
22 SkMatrix fLocalMatrix;
23 GrColor fColor;
24 bool fHasLocalRect;
25 bool fHasLocalMatrix;
26 };
27 20
28 static GrBatch* Create(const Geometry& geometry) { 21 // setup batch properties
29 return SkNEW_ARGS(RectBatch, (geometry)); 22 fBatch.fColorIgnored = !init.readsColor();
23 fBatch.fColor = fGeoData[0].fColor;
24 fBatch.fUsesLocalCoords = init.readsLocalCoords();
25 fBatch.fCoverageIgnored = !init.readsCoverage();
26 }
27
28 void GrRectBatch::generateGeometry(GrBatchTarget* batchTarget) {
29 SkAutoTUnref<const GrGeometryProcessor> gp(this->createRectGP());
30 if (!gp) {
31 SkDebugf("Could not create GrGeometryProcessor\n");
32 return;
30 } 33 }
31 34
32 const char* name() const override { return "RectBatch"; } 35 batchTarget->initDraw(gp, this->pipeline());
33 36
34 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 37 int instanceCount = fGeoData.count();
35 // When this is called on a batch, there is only one geometry bundle 38 size_t vertexStride = gp->getVertexStride();
36 out->setKnownFourComponents(fGeoData[0].fColor); 39 SkASSERT(this->hasLocalRect() ?
40 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalC oordAttr) :
41 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)) ;
42 QuadHelper helper;
43 void* vertices = helper.init(batchTarget, vertexStride, instanceCount);
44
45 if (!vertices) {
46 return;
37 } 47 }
38 48
39 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { 49 for (int i = 0; i < instanceCount; i++) {
40 out->setKnownSingleComponent(0xff); 50 const Geometry& geom = fGeoData[i];
41 }
42 51
43 void initBatchTracker(const GrPipelineInfo& init) override { 52 intptr_t offset = reinterpret_cast<intptr_t>(vertices) +
44 // Handle any color overrides 53 kVerticesPerQuad * i * vertexStride;
45 if (!init.readsColor()) { 54 SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
46 fGeoData[0].fColor = GrColor_ILLEGAL;
47 }
48 init.getOverrideColorIfSet(&fGeoData[0].fColor);
49 55
50 // setup batch properties 56 positions->setRectFan(geom.fRect.fLeft, geom.fRect.fTop,
51 fBatch.fColorIgnored = !init.readsColor(); 57 geom.fRect.fRight, geom.fRect.fBottom, vertexStrid e);
52 fBatch.fColor = fGeoData[0].fColor; 58 geom.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerticesP erQuad);
53 fBatch.fUsesLocalCoords = init.readsLocalCoords();
54 fBatch.fCoverageIgnored = !init.readsCoverage();
55 }
56 59
57 void generateGeometry(GrBatchTarget* batchTarget) override { 60 // TODO we should only do this if local coords are being read
58 SkAutoTUnref<const GrGeometryProcessor> gp(this->createRectGP()); 61 if (geom.fHasLocalRect) {
59 if (!gp) { 62 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
60 SkDebugf("Could not create GrGeometryProcessor\n"); 63 SkPoint* coords = reinterpret_cast<SkPoint*>(offset + kLocalOffset);
61 return; 64 coords->setRectFan(geom.fLocalRect.fLeft, geom.fLocalRect.fTop,
62 } 65 geom.fLocalRect.fRight, geom.fLocalRect.fBottom,
63 66 vertexStride);
64 batchTarget->initDraw(gp, this->pipeline()); 67 if (geom.fHasLocalMatrix) {
65 68 geom.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVer ticesPerQuad);
66 int instanceCount = fGeoData.count();
67 size_t vertexStride = gp->getVertexStride();
68 SkASSERT(this->hasLocalRect() ?
69 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordAttr) :
70 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr));
71 QuadHelper helper;
72 void* vertices = helper.init(batchTarget, vertexStride, instanceCount);
73
74 if (!vertices) {
75 return;
76 }
77
78 for (int i = 0; i < instanceCount; i++) {
79 const Geometry& geom = fGeoData[i];
80
81 intptr_t offset = reinterpret_cast<intptr_t>(vertices) +
82 kVerticesPerQuad * i * vertexStride;
83 SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
84
85 positions->setRectFan(geom.fRect.fLeft, geom.fRect.fTop,
86 geom.fRect.fRight, geom.fRect.fBottom, vertexS tride);
87 geom.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerti cesPerQuad);
88
89 // TODO we should only do this if local coords are being read
90 if (geom.fHasLocalRect) {
91 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor );
92 SkPoint* coords = reinterpret_cast<SkPoint*>(offset + kLocalOffs et);
93 coords->setRectFan(geom.fLocalRect.fLeft, geom.fLocalRect.fTop,
94 geom.fLocalRect.fRight, geom.fLocalRect.fBott om,
95 vertexStride);
96 if (geom.fHasLocalMatrix) {
97 geom.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVerticesPerQuad);
98 }
99 }
100
101 static const int kColorOffset = sizeof(SkPoint);
102 GrColor* vertColor = reinterpret_cast<GrColor*>(offset + kColorOffse t);
103 for (int j = 0; j < 4; ++j) {
104 *vertColor = geom.fColor;
105 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
106 } 69 }
107 } 70 }
108 71
109 helper.issueDraw(batchTarget); 72 static const int kColorOffset = sizeof(SkPoint);
73 GrColor* vertColor = reinterpret_cast<GrColor*>(offset + kColorOffset);
74 for (int j = 0; j < 4; ++j) {
75 *vertColor = geom.fColor;
76 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
77 }
110 } 78 }
111 79
112 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } 80 helper.issueDraw(batchTarget);
81 }
113 82
114 private: 83 bool GrRectBatch::onCombineIfPossible(GrBatch* t) {
115 RectBatch(const Geometry& geometry) { 84 if (!this->pipeline()->isEqual(*t->pipeline())) {
116 this->initClassID<RectBatch>(); 85 return false;
117 fGeoData.push_back(geometry);
118
119 fBounds = geometry.fRect;
120 geometry.fViewMatrix.mapRect(&fBounds);
121 } 86 }
122 87
123 GrColor color() const { return fBatch.fColor; } 88 GrRectBatch* that = t->cast<GrRectBatch>();
124 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
125 bool colorIgnored() const { return fBatch.fColorIgnored; }
126 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
127 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
128 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
129 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
130 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
131 89
132 bool onCombineIfPossible(GrBatch* t) override { 90 if (this->hasLocalRect() != that->hasLocalRect()) {
133 if (!this->pipeline()->isEqual(*t->pipeline())) { 91 return false;
92 }
93
94 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
95 if (!this->hasLocalRect() && this->usesLocalCoords()) {
96 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
134 return false; 97 return false;
135 } 98 }
136 99
137 RectBatch* that = t->cast<RectBatch>(); 100 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
138
139 if (this->hasLocalRect() != that->hasLocalRect()) {
140 return false; 101 return false;
141 } 102 }
142 103
143 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 104 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that->lo calMatrix())) {
144 if (!this->hasLocalRect() && this->usesLocalCoords()) { 105 return false;
145 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
146 return false;
147 }
148
149 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
150 return false;
151 }
152
153 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that ->localMatrix())) {
154 return false;
155 }
156 }
157
158 if (this->color() != that->color()) {
159 fBatch.fColor = GrColor_ILLEGAL;
160 }
161 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
162 this->joinBounds(that->bounds());
163 return true;
164 }
165
166 /** We always use per-vertex colors so that rects can be batched across colo r changes. Sometimes
167 we have explicit local coords and sometimes not. We *could* always prov ide explicit local
168 coords and just duplicate the positions when the caller hasn't provided a local coord rect,
169 but we haven't seen a use case which frequently switches between local r ect and no local
170 rect draws.
171
172 The color param is used to determine whether the opaque hint can be set on the draw state.
173 The caller must populate the vertex colors itself.
174
175 The vertex attrib order is always pos, color, [local coords].
176 */
177 const GrGeometryProcessor* createRectGP() {
178 using namespace GrDefaultGeoProcFactory;
179 Color color(Color::kAttribute_Type);
180 Coverage coverage(this->coverageIgnored() ? Coverage::kNone_Type : Cover age::kSolid_Type);
181
182 // if we have a local rect, then we apply the localMatrix directly to th e localRect to
183 // generate vertex local coords
184 if (this->hasLocalRect()) {
185 LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
186 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I());
187 } else {
188 LocalCoords localCoords(LocalCoords::kUsePosition_Type,
189 this->hasLocalMatrix() ? &this->localMatrix( ) : NULL);
190 return GrDefaultGeoProcFactory::CreateForDeviceSpace(color, coverage , localCoords,
191 this->viewMatri x());
192 } 106 }
193 } 107 }
194 108
195 109 if (this->color() != that->color()) {
196 struct BatchTracker { 110 fBatch.fColor = GrColor_ILLEGAL;
197 GrColor fColor;
198 bool fUsesLocalCoords;
199 bool fColorIgnored;
200 bool fCoverageIgnored;
201 };
202
203 BatchTracker fBatch;
204 SkSTArray<1, Geometry, true> fGeoData;
205 };
206
207 namespace GrRectBatch {
208
209 GrBatch* Create(GrColor color,
210 const SkMatrix& viewMatrix,
211 const SkRect& rect,
212 const SkRect* localRect,
213 const SkMatrix* localMatrix) {
214 RectBatch::Geometry geometry;
215 geometry.fColor = color;
216 geometry.fViewMatrix = viewMatrix;
217 geometry.fRect = rect;
218
219 if (localRect) {
220 geometry.fHasLocalRect = true;
221 geometry.fLocalRect = *localRect;
222 } else {
223 geometry.fHasLocalRect = false;
224 } 111 }
225 112 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
226 if (localMatrix) { 113 this->joinBounds(that->bounds());
227 geometry.fHasLocalMatrix = true; 114 return true;
228 geometry.fLocalMatrix = *localMatrix;
229 } else {
230 geometry.fHasLocalMatrix = false;
231 }
232
233 return RectBatch::Create(geometry);
234 } 115 }
235 116
236 }; 117 /** We always use per-vertex colors so that rects can be batched across color ch anges. Sometimes
118 we have explicit local coords and sometimes not. We *could* always provide explicit local
119 coords and just duplicate the positions when the caller hasn't provided a lo cal coord rect,
120 but we haven't seen a use case which frequently switches between local rect and no local
121 rect draws.
122
123 The color param is used to determine whether the opaque hint can be set on t he draw state.
124 The caller must populate the vertex colors itself.
125
126 The vertex attrib order is always pos, color, [local coords].
127 */
128 const GrGeometryProcessor* GrRectBatch::createRectGP() {
129 using namespace GrDefaultGeoProcFactory;
130 Color color(Color::kAttribute_Type);
131 Coverage coverage(this->coverageIgnored() ? Coverage::kNone_Type : Coverage: :kSolid_Type);
132
133 // if we have a local rect, then we apply the localMatrix directly to the lo calRect to
134 // generate vertex local coords
135 if (this->hasLocalRect()) {
136 LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
137 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkM atrix::I());
138 } else {
139 LocalCoords localCoords(LocalCoords::kUsePosition_Type,
140 this->hasLocalMatrix() ? &this->localMatrix() : NULL);
141 return GrDefaultGeoProcFactory::CreateForDeviceSpace(color, coverage, lo calCoords,
142 this->viewMatrix()) ;
143 }
144 }
237 145
238 //////////////////////////////////////////////////////////////////////////////// /////////////////// 146 //////////////////////////////////////////////////////////////////////////////// ///////////////////
239 147
240 #ifdef GR_TEST_UTILS 148 #ifdef GR_TEST_UTILS
241 149
150 #include "GrBatchTest.h"
151
242 BATCH_TEST_DEFINE(RectBatch) { 152 BATCH_TEST_DEFINE(RectBatch) {
243 GrColor color = GrRandomColor(random); 153 GrRectBatch::Geometry geometry;
154 geometry.fColor = GrRandomColor(random);
244 155
245 SkRect rect = GrTest::TestRect(random); 156 geometry.fRect = GrTest::TestRect(random);
246 SkRect localRect; 157 geometry.fHasLocalRect = random->nextBool();
247 bool hasLocalRect = random->nextBool();
248 bool hasLocalMatrix = random->nextBool();
249 158
250 SkMatrix viewMatrix; 159 if (geometry.fHasLocalRect) {
251 SkMatrix localMatrix; 160 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
252 if (hasLocalRect) { 161 geometry.fLocalRect = GrTest::TestRect(random);
253 viewMatrix = GrTest::TestMatrixInvertible(random);
254 localRect = GrTest::TestRect(random);
255 } else { 162 } else {
256 viewMatrix = GrTest::TestMatrix(random); 163 geometry.fViewMatrix = GrTest::TestMatrix(random);
257 } 164 }
258 165
259 if (hasLocalMatrix) { 166 geometry.fHasLocalMatrix = random->nextBool();
260 localMatrix = GrTest::TestMatrix(random); 167 if (geometry.fHasLocalMatrix) {
168 geometry.fLocalMatrix = GrTest::TestMatrix(random);
261 } 169 }
262 170
263 return GrRectBatch::Create(color, viewMatrix, rect, 171 return GrRectBatch::Create(geometry);
264 hasLocalRect ? &localRect : NULL,
265 hasLocalMatrix ? &localMatrix : NULL);
266 } 172 }
267 173
268 #endif 174 #endif
OLDNEW
« no previous file with comments | « src/gpu/batches/GrRectBatch.h ('k') | src/gpu/batches/GrRectBatchFactory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698