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

Side by Side Diff: src/gpu/GrInOrderDrawBuffer.cpp

Issue 931293002: non-aa rects batch (Closed) Base URL: https://skia.googlesource.com/skia.git@dash
Patch Set: windows angle fix Created 5 years, 10 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 | « no previous file | no next file » | 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 2011 Google Inc. 2 * Copyright 2011 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 "GrInOrderDrawBuffer.h" 8 #include "GrInOrderDrawBuffer.h"
9 9
10 #include "GrBufferAllocPool.h" 10 #include "GrBufferAllocPool.h"
(...skipping 20 matching lines...) Expand all
31 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve); 31 fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
32 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve); 32 fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
33 } 33 }
34 34
35 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { 35 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
36 this->reset(); 36 this->reset();
37 } 37 }
38 38
39 //////////////////////////////////////////////////////////////////////////////// 39 ////////////////////////////////////////////////////////////////////////////////
40 40
41 namespace {
42 void get_vertex_bounds(const void* vertices,
43 size_t vertexSize,
44 int vertexCount,
45 SkRect* bounds) {
46 SkASSERT(vertexSize >= sizeof(SkPoint));
47 SkASSERT(vertexCount > 0);
48 const SkPoint* point = static_cast<const SkPoint*>(vertices);
49 bounds->fLeft = bounds->fRight = point->fX;
50 bounds->fTop = bounds->fBottom = point->fY;
51 for (int i = 1; i < vertexCount; ++i) {
52 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + v ertexSize);
53 bounds->growToInclude(point->fX, point->fY);
54 }
55 }
56 }
57
58 /** We always use per-vertex colors so that rects can be batched across color ch anges. Sometimes we 41 /** We always use per-vertex colors so that rects can be batched across color ch anges. Sometimes we
59 have explicit local coords and sometimes not. We *could* always provide expl icit local coords 42 have explicit local coords and sometimes not. We *could* always provide expl icit local coords
60 and just duplicate the positions when the caller hasn't provided a local coo rd rect, but we 43 and just duplicate the positions when the caller hasn't provided a local coo rd rect, but we
61 haven't seen a use case which frequently switches between local rect and no local rect draws. 44 haven't seen a use case which frequently switches between local rect and no local rect draws.
62 45
63 The color param is used to determine whether the opaque hint can be set on t he draw state. 46 The color param is used to determine whether the opaque hint can be set on t he draw state.
64 The caller must populate the vertex colors itself. 47 The caller must populate the vertex colors itself.
65 48
66 The vertex attrib order is always pos, color, [local coords]. 49 The vertex attrib order is always pos, color, [local coords].
67 */ 50 */
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 // allocated space, and leave enough for 50% growth over last time. 82 // allocated space, and leave enough for 50% growth over last time.
100 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minRese rve) { 83 if (3 * buffer->count() < buffer->reserved() && buffer->reserved() > minRese rve) {
101 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2); 84 int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
102 buffer->reset(); 85 buffer->reset();
103 buffer->setReserve(reserve); 86 buffer->setReserve(reserve);
104 } else { 87 } else {
105 buffer->rewind(); 88 buffer->rewind();
106 } 89 }
107 } 90 }
108 91
92 class RectBatch : public GrBatch {
93 public:
94 struct Geometry {
95 GrColor fColor;
96 SkMatrix fViewMatrix;
97 SkRect fRect;
98 bool fHasLocalRect;
99 bool fHasLocalMatrix;
100 SkRect fLocalRect;
101 SkMatrix fLocalMatrix;
102 };
103
104 static GrBatch* Create(const Geometry& geometry) {
105 return SkNEW_ARGS(RectBatch, (geometry));
106 }
107
108 const char* name() const SK_OVERRIDE { return "RectBatch"; }
109
110 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
111 // When this is called on a batch, there is only one geometry bundle
112 out->setKnownFourComponents(fGeoData[0].fColor);
113 }
114
115 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E {
116 out->setKnownSingleComponent(0xff);
117 }
118
119 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
120 // Handle any color overrides
121 if (init.fColorIgnored) {
122 fGeoData[0].fColor = GrColor_ILLEGAL;
123 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
124 fGeoData[0].fColor = init.fOverrideColor;
125 }
126
127 // setup batch properties
128 fBatch.fColorIgnored = init.fColorIgnored;
129 fBatch.fColor = fGeoData[0].fColor;
130 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
131 fBatch.fCoverageIgnored = init.fCoverageIgnored;
132 }
133
134 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE {
135 // Go to device coords to allow batching across matrix changes
136 SkMatrix invert = SkMatrix::I();
137
138 // if we have a local rect, then we apply the localMatrix directly to th e localRect to
139 // generate vertex local coords
140 bool hasExplicitLocalCoords = this->hasLocalRect();
141 if (!hasExplicitLocalCoords) {
142 if (!this->viewMatrix().isIdentity() && !this->viewMatrix().invert(& invert)) {
143 SkDebugf("Could not invert\n");
144 return;
145 }
146
147 if (this->hasLocalMatrix()) {
148 invert.preConcat(this->localMatrix());
149 }
150 }
151
152 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLoc alCoords,
153 this->color(),
154 &invert));
155
156 batchTarget->initDraw(gp, pipeline);
157
158 // TODO this is hacky, but the only way we have to initialize the GP is to use the
159 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
160 // everywhere we can remove this nastiness
161 GrPipelineInfo init;
162 init.fColorIgnored = fBatch.fColorIgnored;
163 init.fOverrideColor = GrColor_ILLEGAL;
164 init.fCoverageIgnored = fBatch.fCoverageIgnored;
165 init.fUsesLocalCoords = this->usesLocalCoords();
166 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
167
168 size_t vertexStride = gp->getVertexStride();
169
170 SkASSERT(hasExplicitLocalCoords ?
171 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordAttr) :
172 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr));
173
174 int instanceCount = fGeoData.count();
175 int vertexCount = kVertsPerRect * instanceCount;
176
177 const GrVertexBuffer* vertexBuffer;
178 int firstVertex;
179
180 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
181 vertexCount,
182 &vertexBuffer,
183 &firstVertex);
184
185 for (int i = 0; i < instanceCount; i++) {
186 const Geometry& args = fGeoData[i];
187
188 intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i * vertexStride;
189 SkPoint* positions = GrTCast<SkPoint*>(offset);
190
191 positions->setRectFan(args.fRect.fLeft, args.fRect.fTop,
192 args.fRect.fRight, args.fRect.fBottom, vertexS tride);
193 args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerts PerRect);
194
195 if (args.fHasLocalRect) {
196 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor );
197 SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset);
198 coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop,
199 args.fLocalRect.fRight, args.fLocalRect.fBott om,
200 vertexStride);
201 if (args.fHasLocalMatrix) {
202 args.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVertsPerRect);
203 }
204 }
205
206 static const int kColorOffset = sizeof(SkPoint);
207 GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset);
208 for (int j = 0; j < 4; ++j) {
209 *vertColor = args.fColor;
210 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
211 }
212 }
213
214 const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
215
216 GrDrawTarget::DrawInfo drawInfo;
217 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
218 drawInfo.setStartVertex(0);
219 drawInfo.setStartIndex(0);
220 drawInfo.setVerticesPerInstance(kVertsPerRect);
221 drawInfo.setIndicesPerInstance(kIndicesPerRect);
222 drawInfo.adjustStartVertex(firstVertex);
223 drawInfo.setVertexBuffer(vertexBuffer);
224 drawInfo.setIndexBuffer(quadIndexBuffer);
225
226 int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
227 while (instanceCount) {
228 drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw) );
229 drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.vertices PerInstance());
230 drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPe rInstance());
231
232 batchTarget->draw(drawInfo);
233
234 drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCoun t());
235 instanceCount -= drawInfo.instanceCount();
236 }
237 }
238
239 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
240
241 private:
242 RectBatch(const Geometry& geometry) {
243 this->initClassID<RectBatch>();
244 fGeoData.push_back(geometry);
245 }
246
247 GrColor color() const { return fBatch.fColor; }
248 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
249 bool colorIgnored() const { return fBatch.fColorIgnored; }
250 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
251 const SkMatrix& localMatrix() const { return fGeoData[0].fLocalMatrix; }
252 bool hasLocalRect() const { return fGeoData[0].fHasLocalRect; }
253 bool hasLocalMatrix() const { return fGeoData[0].fHasLocalMatrix; }
254
255 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
256 RectBatch* that = t->cast<RectBatch>();
257
258 if (this->hasLocalRect() != that->hasLocalRect()) {
259 return false;
260 }
261
262 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
263 if (!this->hasLocalRect() && this->usesLocalCoords()) {
264 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
265 return false;
266 }
267
268 if (this->hasLocalMatrix() != that->hasLocalMatrix()) {
269 return false;
270 }
271
272 if (this->hasLocalMatrix() && !this->localMatrix().cheapEqualTo(that ->localMatrix())) {
273 return false;
274 }
275 }
276
277 if (this->color() != that->color()) {
278 fBatch.fColor = GrColor_ILLEGAL;
279 }
280 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
281 return true;
282 }
283
284 struct BatchTracker {
285 GrColor fColor;
286 bool fUsesLocalCoords;
287 bool fColorIgnored;
288 bool fCoverageIgnored;
289 };
290
291 const static int kVertsPerRect = 4;
292 const static int kIndicesPerRect = 6;
293
294 BatchTracker fBatch;
295 SkSTArray<1, Geometry, true> fGeoData;
296 };
297
109 void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder, 298 void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
110 GrColor color, 299 GrColor color,
111 const SkMatrix& viewMatrix, 300 const SkMatrix& viewMatrix,
112 const SkRect& rect, 301 const SkRect& rect,
113 const SkRect* localRect, 302 const SkRect* localRect,
114 const SkMatrix* localMatrix) { 303 const SkMatrix* localMatrix) {
115 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); 304 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
116 305 RectBatch::Geometry geometry;
117 // Go to device coords to allow batching across matrix changes 306 geometry.fColor = color;
118 SkMatrix invert = SkMatrix::I(); 307 geometry.fViewMatrix = viewMatrix;
119 308 geometry.fRect = rect;
120 // if we have a local rect, then we apply the localMatrix directly to the lo calRect to generate
121 // vertex local coords
122 bool hasExplicitLocalCoords = SkToBool(localRect);
123 if (!hasExplicitLocalCoords) {
124 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
125 SkDebugf("Could not invert\n");
126 return;
127 }
128
129 if (localMatrix) {
130 invert.preConcat(*localMatrix);
131 }
132 }
133
134 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCo ords,
135 color,
136 &invert));
137
138 size_t vstride = gp->getVertexStride();
139 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) :
140 0));
141 AutoReleaseGeometry geo(this, 4, vstride, 0);
142 if (!geo.succeeded()) {
143 SkDebugf("Failed to get space for vertices!\n");
144 return;
145 }
146
147 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom , vstride);
148 viewMatrix.mapPointsWithStride(geo.positions(), vstride, 4);
149
150 // When the caller has provided an explicit source rect for a stage then we don't want to
151 // modify that stage's matrix. Otherwise if the effect is generating its sou rce rect from
152 // the vertex positions then we have to account for the view matrix
153 SkRect devBounds;
154
155 // since we already computed the dev verts, set the bounds hint. This will h elp us avoid
156 // unnecessary clipping in our onDraw().
157 get_vertex_bounds(geo.vertices(), vstride, 4, &devBounds);
158 309
159 if (localRect) { 310 if (localRect) {
160 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); 311 geometry.fHasLocalRect = true;
161 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset); 312 geometry.fLocalRect = *localRect;
162 coords->setRectFan(localRect->fLeft, localRect->fTop, 313 } else {
163 localRect->fRight, localRect->fBottom, 314 geometry.fHasLocalRect = false;
164 vstride); 315 }
165 if (localMatrix) { 316
166 localMatrix->mapPointsWithStride(coords, vstride, 4); 317 if (localMatrix) {
167 } 318 geometry.fHasLocalMatrix = true;
168 } 319 geometry.fLocalMatrix = *localMatrix;
169 320 } else {
170 static const int kColorOffset = sizeof(SkPoint); 321 geometry.fHasLocalMatrix = false;
171 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + k ColorOffset); 322 }
172 for (int i = 0; i < 4; ++i) { 323
173 *vertColor = color; 324 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry));
174 vertColor = (GrColor*) ((intptr_t) vertColor + vstride); 325
175 } 326 SkRect bounds = rect;
176 327 viewMatrix.mapRect(&bounds);
177 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); 328 this->drawBatch(pipelineBuilder, batch, &bounds);
178 this->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType, 1, 4, 6,
179 &devBounds);
180 } 329 }
181 330
182 int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) { 331 int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
183 SkASSERT(!fCmdBuffer.empty()); 332 SkASSERT(!fCmdBuffer.empty());
184 SkASSERT(info.isInstanced()); 333 SkASSERT(info.isInstanced());
185 334
186 const GeometrySrcState& geomSrc = this->getGeomSrc(); 335 const GeometrySrcState& geomSrc = this->getGeomSrc();
187 336
188 // we only attempt to concat the case when reserved verts are used with a cl ient-specified index 337 // we only attempt to concat the case when reserved verts are used with a cl ient-specified index
189 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated 338 // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 430
282 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder , 431 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder ,
283 const GrPathProcessor* pathProc, 432 const GrPathProcessor* pathProc,
284 const GrPath* path, 433 const GrPath* path,
285 const GrScissorState& scissorState, 434 const GrScissorState& scissorState,
286 const GrStencilSettings& stencilSettings ) { 435 const GrStencilSettings& stencilSettings ) {
287 this->closeBatch(); 436 this->closeBatch();
288 437
289 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, 438 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
290 (path, pipelineBuilder.getRenderT arget())); 439 (path, pipelineBuilder.getRenderT arget()));
440
291 sp->fScissor = scissorState; 441 sp->fScissor = scissorState;
292 sp->fUseHWAA = pipelineBuilder.isHWAntialias(); 442 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
293 sp->fViewMatrix = pathProc->viewMatrix(); 443 sp->fViewMatrix = pathProc->viewMatrix();
294 sp->fStencil = stencilSettings; 444 sp->fStencil = stencilSettings;
295 this->recordTraceMarkersIfNecessary(); 445 this->recordTraceMarkersIfNecessary();
296 } 446 }
297 447
298 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, 448 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
299 const GrPath* path, 449 const GrPath* path,
300 const GrStencilSettings& stencilSettings, 450 const GrStencilSettings& stencilSettings,
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 774 }
625 } 775 }
626 776
627 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, 777 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
628 size_t vertexStride, 778 size_t vertexStride,
629 int indexCount) { 779 int indexCount) {
630 this->closeBatch(); 780 this->closeBatch();
631 781
632 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i ndexCount); 782 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i ndexCount);
633 } 783 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698