OLD | NEW |
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 "GrDefaultGeoProcFactory.h" | 10 #include "GrDefaultGeoProcFactory.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we | 55 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we |
56 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords | 56 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords |
57 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we | 57 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we |
58 haven't seen a use case which frequently switches between local rect and no
local rect draws. | 58 haven't seen a use case which frequently switches between local rect and no
local rect draws. |
59 | 59 |
60 The color param is used to determine whether the opaque hint can be set on t
he draw state. | 60 The color param is used to determine whether the opaque hint can be set on t
he draw state. |
61 The caller must populate the vertex colors itself. | 61 The caller must populate the vertex colors itself. |
62 | 62 |
63 The vertex attrib order is always pos, color, [local coords]. | 63 The vertex attrib order is always pos, color, [local coords]. |
64 */ | 64 */ |
65 static const GrGeometryProcessor* create_rect_gp(GrDrawState* drawState, | 65 static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G
rColor color) { |
66 bool hasLocalCoords, | |
67 GrColor color) { | |
68 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | 66 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | |
69 GrDefaultGeoProcFactory::kColor_GPType; | 67 GrDefaultGeoProcFactory::kColor_GPType; |
70 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0; | 68 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0; |
71 const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(color, flags
); | 69 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(color, flags
))->unref(); |
72 if (0xFF == GrColorUnpackA(color)) { | 70 if (0xFF == GrColorUnpackA(color)) { |
73 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); | 71 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); |
74 } | 72 } |
75 return gp; | |
76 } | 73 } |
77 | 74 |
78 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { | 75 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { |
79 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; | 76 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; |
80 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | 77 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); |
81 if (isWinding) { | 78 if (isWinding) { |
82 // Double check that it is in fact winding. | 79 // Double check that it is in fact winding. |
83 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); | 80 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); |
84 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); | 81 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); |
85 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); | 82 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); |
(...skipping 26 matching lines...) Expand all Loading... |
112 | 109 |
113 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTr
aceCmdBit); } | 110 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTr
aceCmdBit); } |
114 | 111 |
115 void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, | 112 void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, |
116 GrColor color, | 113 GrColor color, |
117 const SkRect& rect, | 114 const SkRect& rect, |
118 const SkRect* localRect, | 115 const SkRect* localRect, |
119 const SkMatrix* localMatrix) { | 116 const SkMatrix* localMatrix) { |
120 GrDrawState::AutoRestoreEffects are(ds); | 117 GrDrawState::AutoRestoreEffects are(ds); |
121 | 118 |
122 SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(ds, SkToBool(local
Rect), | 119 set_vertex_attributes(ds, SkToBool(localRect), color); |
123 color)); | |
124 | 120 |
125 size_t vstride = gp->getVertexStride(); | 121 size_t vstride = ds->getGeometryProcessor()->getVertexStride(); |
126 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect)
? sizeof(SkPoint) : | 122 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect)
? sizeof(SkPoint) : |
127
0)); | 123
0)); |
128 AutoReleaseGeometry geo(this, 4, vstride, 0); | 124 AutoReleaseGeometry geo(this, 4, vstride, 0); |
129 if (!geo.succeeded()) { | 125 if (!geo.succeeded()) { |
130 SkDebugf("Failed to get space for vertices!\n"); | 126 SkDebugf("Failed to get space for vertices!\n"); |
131 return; | 127 return; |
132 } | 128 } |
133 | 129 |
134 // Go to device coords to allow batching across matrix changes | 130 // Go to device coords to allow batching across matrix changes |
135 SkMatrix matrix = ds->getViewMatrix(); | 131 SkMatrix matrix = ds->getViewMatrix(); |
(...skipping 26 matching lines...) Expand all Loading... |
162 } | 158 } |
163 | 159 |
164 static const int kColorOffset = sizeof(SkPoint); | 160 static const int kColorOffset = sizeof(SkPoint); |
165 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + k
ColorOffset); | 161 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + k
ColorOffset); |
166 for (int i = 0; i < 4; ++i) { | 162 for (int i = 0; i < 4; ++i) { |
167 *vertColor = color; | 163 *vertColor = color; |
168 vertColor = (GrColor*) ((intptr_t) vertColor + vstride); | 164 vertColor = (GrColor*) ((intptr_t) vertColor + vstride); |
169 } | 165 } |
170 | 166 |
171 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); | 167 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); |
172 this->drawIndexedInstances(ds, gp, kTriangles_GrPrimitiveType, 1, 4, 6, &dev
Bounds); | 168 this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBoun
ds); |
173 } | 169 } |
174 | 170 |
175 int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawIn
fo& info) { | 171 int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds, const DrawIn
fo& info) { |
176 SkASSERT(!fCmdBuffer.empty()); | 172 SkASSERT(!fCmdBuffer.empty()); |
177 SkASSERT(info.isInstanced()); | 173 SkASSERT(info.isInstanced()); |
178 | 174 |
179 const GeometrySrcState& geomSrc = this->getGeomSrc(); | 175 const GeometrySrcState& geomSrc = this->getGeomSrc(); |
180 | 176 |
181 // we only attempt to concat the case when reserved verts are used with a cl
ient-specified index | 177 // we only attempt to concat the case when reserved verts are used with a cl
ient-specified index |
182 // buffer. To make this work with client-specified VBs we'd need to know if
the VB was updated | 178 // buffer. To make this work with client-specified VBs we'd need to know if
the VB was updated |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } else { | 214 } else { |
219 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers()); | 215 fGpuCmdMarkers.push_back(this->getActiveTraceMarkers()); |
220 draw->fType = add_trace_bit(draw->fType); | 216 draw->fType = add_trace_bit(draw->fType); |
221 } | 217 } |
222 } | 218 } |
223 | 219 |
224 return instancesToConcat; | 220 return instancesToConcat; |
225 } | 221 } |
226 | 222 |
227 void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds, | 223 void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds, |
228 const GrGeometryProcessor* gp, | |
229 const DrawInfo& info, | 224 const DrawInfo& info, |
230 const ScissorState& scissorState, | 225 const ScissorState& scissorState, |
231 const GrDeviceCoordTexture* dstCopy) { | 226 const GrDeviceCoordTexture* dstCopy) { |
232 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); | 227 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); |
233 | 228 |
234 if (!this->recordStateAndShouldDraw(ds, gp, NULL, | 229 const GrGeometryProcessor* gp = ds.getGeometryProcessor(); |
| 230 if (!this->recordStateAndShouldDraw(ds, gp->getColor(), gp->getCoverage(), |
235 GrGpu::PrimTypeToDrawType(info.primitive
Type()), | 231 GrGpu::PrimTypeToDrawType(info.primitive
Type()), |
236 scissorState, dstCopy)) { | 232 scissorState, dstCopy)) { |
237 return; | 233 return; |
238 } | 234 } |
239 | 235 |
240 Draw* draw; | 236 Draw* draw; |
241 if (info.isInstanced()) { | 237 if (info.isInstanced()) { |
242 int instancesConcated = this->concatInstancedDraw(ds, info); | 238 int instancesConcated = this->concatInstancedDraw(ds, info); |
243 if (info.instanceCount() > instancesConcated) { | 239 if (info.instanceCount() > instancesConcated) { |
244 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 240 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
245 draw->fInfo.adjustInstanceCount(-instancesConcated); | 241 draw->fInfo.adjustInstanceCount(-instancesConcated); |
246 } else { | 242 } else { |
247 return; | 243 return; |
248 } | 244 } |
249 } else { | 245 } else { |
250 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 246 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
251 } | 247 } |
252 this->recordTraceMarkersIfNecessary(); | 248 this->recordTraceMarkersIfNecessary(); |
253 } | 249 } |
254 | 250 |
255 void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds, | 251 void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds, |
256 const GrPathProcessor* pathProc, | |
257 const GrPath* path, | 252 const GrPath* path, |
258 const GrClipMaskManager::ScissorState& s
cissorState, | 253 const GrClipMaskManager::ScissorState& s
cissorState, |
259 const GrStencilSettings& stencilSettings
) { | 254 const GrStencilSettings& stencilSettings
) { |
260 // Only compare the subset of GrDrawState relevant to path stenciling? | 255 // Only compare the subset of GrDrawState relevant to path stenciling? |
261 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kStencilPath_
DrawType, | 256 if (!this->recordStateAndShouldDraw(ds, GrColor_WHITE, 0xff, GrGpu::kStencil
Path_DrawType, |
262 scissorState, NULL)) { | 257 scissorState, NULL)) { |
263 return; | 258 return; |
264 } | 259 } |
265 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path)); | 260 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path)); |
266 sp->fStencilSettings = stencilSettings; | 261 sp->fStencilSettings = stencilSettings; |
267 this->recordTraceMarkersIfNecessary(); | 262 this->recordTraceMarkersIfNecessary(); |
268 } | 263 } |
269 | 264 |
270 void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds, | 265 void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds, |
271 const GrPathProcessor* pathProc, | 266 GrColor color, |
272 const GrPath* path, | 267 const GrPath* path, |
273 const GrClipMaskManager::ScissorState& scis
sorState, | 268 const GrClipMaskManager::ScissorState& scis
sorState, |
274 const GrStencilSettings& stencilSettings, | 269 const GrStencilSettings& stencilSettings, |
275 const GrDeviceCoordTexture* dstCopy) { | 270 const GrDeviceCoordTexture* dstCopy) { |
276 // TODO: Only compare the subset of GrDrawState relevant to path covering? | 271 // TODO: Only compare the subset of GrDrawState relevant to path covering? |
277 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_Dra
wType, | 272 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawTy
pe, scissorState, |
278 scissorState, dstCopy)) { | 273 dstCopy)) { |
279 return; | 274 return; |
280 } | 275 } |
281 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); | 276 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); |
282 dp->fStencilSettings = stencilSettings; | 277 dp->fStencilSettings = stencilSettings; |
283 this->recordTraceMarkersIfNecessary(); | 278 this->recordTraceMarkersIfNecessary(); |
284 } | 279 } |
285 | 280 |
286 void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds, | 281 void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds, |
287 const GrPathProcessor* pathProc, | 282 GrColor color, |
288 const GrPathRange* pathRange, | 283 const GrPathRange* pathRange, |
289 const void* indices, | 284 const void* indices, |
290 PathIndexType indexType, | 285 PathIndexType indexType, |
291 const float transformValues[], | 286 const float transformValues[], |
292 PathTransformType transformType, | 287 PathTransformType transformType, |
293 int count, | 288 int count, |
294 const GrClipMaskManager::ScissorState& sci
ssorState, | 289 const GrClipMaskManager::ScissorState& sci
ssorState, |
295 const GrStencilSettings& stencilSettings, | 290 const GrStencilSettings& stencilSettings, |
296 const GrDeviceCoordTexture* dstCopy) { | 291 const GrDeviceCoordTexture* dstCopy) { |
297 SkASSERT(pathRange); | 292 SkASSERT(pathRange); |
298 SkASSERT(indices); | 293 SkASSERT(indices); |
299 SkASSERT(transformValues); | 294 SkASSERT(transformValues); |
300 | 295 |
301 if (!this->recordStateAndShouldDraw(ds, NULL, pathProc, GrGpu::kDrawPath_Dra
wType, scissorState, | 296 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawTy
pe, scissorState, |
302 dstCopy)) { | 297 dstCopy)) { |
303 return; | 298 return; |
304 } | 299 } |
305 | 300 |
306 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); | 301 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); |
307 if (int misalign = fPathIndexBuffer.count() % indexBytes) { | 302 if (int misalign = fPathIndexBuffer.count() % indexBytes) { |
308 // Add padding to the index buffer so the indices are aligned properly. | 303 // Add padding to the index buffer so the indices are aligned properly. |
309 fPathIndexBuffer.append(indexBytes - misalign); | 304 fPathIndexBuffer.append(indexBytes - misalign); |
310 } | 305 } |
311 | 306 |
(...skipping 10 matching lines...) Expand all Loading... |
322 // and the combined calls may also cancel each other's winding numbers i
n some | 317 // and the combined calls may also cancel each other's winding numbers i
n some |
323 // places. For now the winding numbers are only an issue if the fill is
even/odd, | 318 // places. For now the winding numbers are only an issue if the fill is
even/odd, |
324 // because DrawPaths is currently only used for glyphs, and glyphs in th
e same | 319 // because DrawPaths is currently only used for glyphs, and glyphs in th
e same |
325 // font tend to all wind in the same direction. | 320 // font tend to all wind in the same direction. |
326 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | 321 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); |
327 if (pathRange == previous->pathRange() && | 322 if (pathRange == previous->pathRange() && |
328 indexType == previous->fIndexType && | 323 indexType == previous->fIndexType && |
329 transformType == previous->fTransformType && | 324 transformType == previous->fTransformType && |
330 stencilSettings == previous->fStencilSettings && | 325 stencilSettings == previous->fStencilSettings && |
331 path_fill_type_is_winding(stencilSettings) && | 326 path_fill_type_is_winding(stencilSettings) && |
332 !ds.willBlendWithDst(pathProc)) { | 327 !ds.willBlendWithDst(color, GrColor_WHITE)) { |
333 // Fold this DrawPaths call into the one previous. | 328 // Fold this DrawPaths call into the one previous. |
334 previous->fCount += count; | 329 previous->fCount += count; |
335 return; | 330 return; |
336 } | 331 } |
337 } | 332 } |
338 | 333 |
339 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | 334 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; |
340 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin(); | 335 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin(); |
341 dp->fIndexType = indexType; | 336 dp->fIndexType = indexType; |
342 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin(); | 337 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin(); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); | 483 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); |
489 cs->fSrcRect = srcRect; | 484 cs->fSrcRect = srcRect; |
490 cs->fDstPoint = dstPoint; | 485 cs->fDstPoint = dstPoint; |
491 this->recordTraceMarkersIfNecessary(); | 486 this->recordTraceMarkersIfNecessary(); |
492 return true; | 487 return true; |
493 } | 488 } |
494 return false; | 489 return false; |
495 } | 490 } |
496 | 491 |
497 bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds, | 492 bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds, |
498 const GrGeometryProcessor* gp
, | 493 GrColor color, |
499 const GrPathProcessor* pathPr
oc, | 494 uint8_t coverage, |
500 GrGpu::DrawType drawType, | 495 GrGpu::DrawType drawType, |
501 const GrClipMaskManager::Scis
sorState& scissor, | 496 const GrClipMaskManager::Scis
sorState& scissor, |
502 const GrDeviceCoordTexture* d
stCopy) { | 497 const GrDeviceCoordTexture* d
stCopy) { |
503 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, | 498 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, |
504 (ds, gp, pathProc, *this->getGpu()->
caps(), scissor, | 499 (ds, color, coverage, *this->getGpu(
)->caps(), scissor, |
505 dstCopy, drawType)); | 500 dstCopy, drawType)); |
506 if (ss->fState.mustSkip()) { | 501 if (ss->fState.mustSkip()) { |
507 fCmdBuffer.pop_back(); | 502 fCmdBuffer.pop_back(); |
508 return false; | 503 return false; |
509 } | 504 } |
510 if (fPrevState && *fPrevState == ss->fState) { | 505 if (fPrevState && *fPrevState == ss->fState) { |
511 fCmdBuffer.pop_back(); | 506 fCmdBuffer.pop_back(); |
512 } else { | 507 } else { |
513 fPrevState = &ss->fState; | 508 fPrevState = &ss->fState; |
514 this->recordTraceMarkersIfNecessary(); | 509 this->recordTraceMarkersIfNecessary(); |
515 } | 510 } |
516 return true; | 511 return true; |
517 } | 512 } |
518 | 513 |
519 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { | 514 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { |
520 SkASSERT(!fCmdBuffer.empty()); | 515 SkASSERT(!fCmdBuffer.empty()); |
521 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); | 516 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); |
522 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | 517 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); |
523 if (activeTraceMarkers.count() > 0) { | 518 if (activeTraceMarkers.count() > 0) { |
524 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); | 519 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); |
525 fGpuCmdMarkers.push_back(activeTraceMarkers); | 520 fGpuCmdMarkers.push_back(activeTraceMarkers); |
526 } | 521 } |
527 } | 522 } |
OLD | NEW |