| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G
rColor color) { | 65 static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G
rColor color) { |
| 66 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | 66 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | |
| 67 GrDefaultGeoProcFactory::kColor_GPType; | 67 GrDefaultGeoProcFactory::kColor_GPType; |
| 68 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0; | 68 flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0; |
| 69 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unr
ef(); | 69 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(color, flags
))->unref(); |
| 70 if (0xFF == GrColorUnpackA(color)) { | 70 if (0xFF == GrColorUnpackA(color)) { |
| 71 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); | 71 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { | 75 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { |
| 76 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; | 76 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; |
| 77 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | 77 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); |
| 78 if (isWinding) { | 78 if (isWinding) { |
| 79 // Double check that it is in fact winding. | 79 // Double check that it is in fact winding. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 103 kCmdMask = 0x7f, | 103 kCmdMask = 0x7f, |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; } | 106 static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; } |
| 107 | 107 |
| 108 static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; } | 108 static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; } |
| 109 | 109 |
| 110 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); } |
| 111 | 111 |
| 112 void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, | 112 void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, |
| 113 GrColor color, |
| 113 const SkRect& rect, | 114 const SkRect& rect, |
| 114 const SkRect* localRect, | 115 const SkRect* localRect, |
| 115 const SkMatrix* localMatrix) { | 116 const SkMatrix* localMatrix) { |
| 116 GrDrawState::AutoRestoreEffects are(ds); | 117 GrDrawState::AutoRestoreEffects are(ds); |
| 117 | 118 |
| 118 GrColor color = ds->getColor(); | |
| 119 set_vertex_attributes(ds, SkToBool(localRect), color); | 119 set_vertex_attributes(ds, SkToBool(localRect), color); |
| 120 | 120 |
| 121 size_t vstride = ds->getGeometryProcessor()->getVertexStride(); | 121 size_t vstride = ds->getGeometryProcessor()->getVertexStride(); |
| 122 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect)
? sizeof(SkPoint) : | 122 SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect)
? sizeof(SkPoint) : |
| 123
0)); | 123
0)); |
| 124 AutoReleaseGeometry geo(this, 4, vstride, 0); | 124 AutoReleaseGeometry geo(this, 4, vstride, 0); |
| 125 if (!geo.succeeded()) { | 125 if (!geo.succeeded()) { |
| 126 SkDebugf("Failed to get space for vertices!\n"); | 126 SkDebugf("Failed to get space for vertices!\n"); |
| 127 return; | 127 return; |
| 128 } | 128 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 219 |
| 220 return instancesToConcat; | 220 return instancesToConcat; |
| 221 } | 221 } |
| 222 | 222 |
| 223 void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds, | 223 void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds, |
| 224 const DrawInfo& info, | 224 const DrawInfo& info, |
| 225 const ScissorState& scissorState, | 225 const ScissorState& scissorState, |
| 226 const GrDeviceCoordTexture* dstCopy) { | 226 const GrDeviceCoordTexture* dstCopy) { |
| 227 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); | 227 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); |
| 228 | 228 |
| 229 if (!this->recordStateAndShouldDraw(ds, GrGpu::PrimTypeToDrawType(info.primi
tiveType()), | 229 const GrGeometryProcessor* gp = ds.getGeometryProcessor(); |
| 230 if (!this->recordStateAndShouldDraw(ds, gp->getColor(), gp->getCoverage(), |
| 231 GrGpu::PrimTypeToDrawType(info.primitive
Type()), |
| 230 scissorState, dstCopy)) { | 232 scissorState, dstCopy)) { |
| 231 return; | 233 return; |
| 232 } | 234 } |
| 233 | 235 |
| 234 Draw* draw; | 236 Draw* draw; |
| 235 if (info.isInstanced()) { | 237 if (info.isInstanced()) { |
| 236 int instancesConcated = this->concatInstancedDraw(ds, info); | 238 int instancesConcated = this->concatInstancedDraw(ds, info); |
| 237 if (info.instanceCount() > instancesConcated) { | 239 if (info.instanceCount() > instancesConcated) { |
| 238 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 240 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
| 239 draw->fInfo.adjustInstanceCount(-instancesConcated); | 241 draw->fInfo.adjustInstanceCount(-instancesConcated); |
| 240 } else { | 242 } else { |
| 241 return; | 243 return; |
| 242 } | 244 } |
| 243 } else { | 245 } else { |
| 244 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | 246 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); |
| 245 } | 247 } |
| 246 this->recordTraceMarkersIfNecessary(); | 248 this->recordTraceMarkersIfNecessary(); |
| 247 } | 249 } |
| 248 | 250 |
| 249 void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds, | 251 void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds, |
| 250 const GrPath* path, | 252 const GrPath* path, |
| 251 const GrClipMaskManager::ScissorState& s
cissorState, | 253 const GrClipMaskManager::ScissorState& s
cissorState, |
| 252 const GrStencilSettings& stencilSettings
) { | 254 const GrStencilSettings& stencilSettings
) { |
| 253 // Only compare the subset of GrDrawState relevant to path stenciling? | 255 // Only compare the subset of GrDrawState relevant to path stenciling? |
| 254 if (!this->recordStateAndShouldDraw(ds, GrGpu::kStencilPath_DrawType, scisso
rState, NULL)) { | 256 if (!this->recordStateAndShouldDraw(ds, GrColor_WHITE, 0xff, GrGpu::kStencil
Path_DrawType, |
| 257 scissorState, NULL)) { |
| 255 return; | 258 return; |
| 256 } | 259 } |
| 257 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path)); | 260 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path)); |
| 258 sp->fStencilSettings = stencilSettings; | 261 sp->fStencilSettings = stencilSettings; |
| 259 this->recordTraceMarkersIfNecessary(); | 262 this->recordTraceMarkersIfNecessary(); |
| 260 } | 263 } |
| 261 | 264 |
| 262 void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds, | 265 void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds, |
| 266 GrColor color, |
| 263 const GrPath* path, | 267 const GrPath* path, |
| 264 const GrClipMaskManager::ScissorState& scis
sorState, | 268 const GrClipMaskManager::ScissorState& scis
sorState, |
| 265 const GrStencilSettings& stencilSettings, | 269 const GrStencilSettings& stencilSettings, |
| 266 const GrDeviceCoordTexture* dstCopy) { | 270 const GrDeviceCoordTexture* dstCopy) { |
| 267 // TODO: Only compare the subset of GrDrawState relevant to path covering? | 271 // TODO: Only compare the subset of GrDrawState relevant to path covering? |
| 268 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorSt
ate, dstCopy)) { | 272 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawTy
pe, scissorState, |
| 273 dstCopy)) { |
| 269 return; | 274 return; |
| 270 } | 275 } |
| 271 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); | 276 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); |
| 272 dp->fStencilSettings = stencilSettings; | 277 dp->fStencilSettings = stencilSettings; |
| 273 this->recordTraceMarkersIfNecessary(); | 278 this->recordTraceMarkersIfNecessary(); |
| 274 } | 279 } |
| 275 | 280 |
| 276 void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds, | 281 void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds, |
| 282 GrColor color, |
| 277 const GrPathRange* pathRange, | 283 const GrPathRange* pathRange, |
| 278 const void* indices, | 284 const void* indices, |
| 279 PathIndexType indexType, | 285 PathIndexType indexType, |
| 280 const float transformValues[], | 286 const float transformValues[], |
| 281 PathTransformType transformType, | 287 PathTransformType transformType, |
| 282 int count, | 288 int count, |
| 283 const GrClipMaskManager::ScissorState& sci
ssorState, | 289 const GrClipMaskManager::ScissorState& sci
ssorState, |
| 284 const GrStencilSettings& stencilSettings, | 290 const GrStencilSettings& stencilSettings, |
| 285 const GrDeviceCoordTexture* dstCopy) { | 291 const GrDeviceCoordTexture* dstCopy) { |
| 286 SkASSERT(pathRange); | 292 SkASSERT(pathRange); |
| 287 SkASSERT(indices); | 293 SkASSERT(indices); |
| 288 SkASSERT(transformValues); | 294 SkASSERT(transformValues); |
| 289 | 295 |
| 290 if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorSt
ate, dstCopy)) { | 296 if (!this->recordStateAndShouldDraw(ds, color, 0xff, GrGpu::kDrawPath_DrawTy
pe, scissorState, |
| 297 dstCopy)) { |
| 291 return; | 298 return; |
| 292 } | 299 } |
| 293 | 300 |
| 294 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); | 301 int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); |
| 295 if (int misalign = fPathIndexBuffer.count() % indexBytes) { | 302 if (int misalign = fPathIndexBuffer.count() % indexBytes) { |
| 296 // 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. |
| 297 fPathIndexBuffer.append(indexBytes - misalign); | 304 fPathIndexBuffer.append(indexBytes - misalign); |
| 298 } | 305 } |
| 299 | 306 |
| 300 char* savedIndices = fPathIndexBuffer.append(count * indexBytes, | 307 char* savedIndices = fPathIndexBuffer.append(count * indexBytes, |
| 301 reinterpret_cast<const char*>(i
ndices)); | 308 reinterpret_cast<const char*>(i
ndices)); |
| 302 float* savedTransforms = fPathTransformBuffer.append( | 309 float* savedTransforms = fPathTransformBuffer.append( |
| 303 count * GrPathRendering::PathTransformSize(tran
sformType), | 310 count * GrPathRendering::PathTransformSize(tran
sformType), |
| 304 transformValues); | 311 transformValues); |
| 305 | 312 |
| 306 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) { | 313 if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) { |
| 307 // The previous command was also DrawPaths. Try to collapse this call in
to the one | 314 // The previous command was also DrawPaths. Try to collapse this call in
to the one |
| 308 // before. Note that stenciling all the paths at once, then covering, ma
y not be | 315 // before. Note that stenciling all the paths at once, then covering, ma
y not be |
| 309 // equivalent to two separate draw calls if there is overlap. Blending w
on't work, | 316 // equivalent to two separate draw calls if there is overlap. Blending w
on't work, |
| 310 // 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 |
| 311 // 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, |
| 312 // 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 |
| 313 // font tend to all wind in the same direction. | 320 // font tend to all wind in the same direction. |
| 314 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | 321 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); |
| 315 if (pathRange == previous->pathRange() && | 322 if (pathRange == previous->pathRange() && |
| 316 indexType == previous->fIndexType && | 323 indexType == previous->fIndexType && |
| 317 transformType == previous->fTransformType && | 324 transformType == previous->fTransformType && |
| 318 stencilSettings == previous->fStencilSettings && | 325 stencilSettings == previous->fStencilSettings && |
| 319 path_fill_type_is_winding(stencilSettings) && | 326 path_fill_type_is_winding(stencilSettings) && |
| 320 !ds.willBlendWithDst()) { | 327 !ds.willBlendWithDst(color, GrColor_WHITE)) { |
| 321 // Fold this DrawPaths call into the one previous. | 328 // Fold this DrawPaths call into the one previous. |
| 322 previous->fCount += count; | 329 previous->fCount += count; |
| 323 return; | 330 return; |
| 324 } | 331 } |
| 325 } | 332 } |
| 326 | 333 |
| 327 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | 334 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; |
| 328 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin(); | 335 dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin(); |
| 329 dp->fIndexType = indexType; | 336 dp->fIndexType = indexType; |
| 330 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin(); | 337 dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); | 483 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); |
| 477 cs->fSrcRect = srcRect; | 484 cs->fSrcRect = srcRect; |
| 478 cs->fDstPoint = dstPoint; | 485 cs->fDstPoint = dstPoint; |
| 479 this->recordTraceMarkersIfNecessary(); | 486 this->recordTraceMarkersIfNecessary(); |
| 480 return true; | 487 return true; |
| 481 } | 488 } |
| 482 return false; | 489 return false; |
| 483 } | 490 } |
| 484 | 491 |
| 485 bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds, | 492 bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds, |
| 493 GrColor color, |
| 494 uint8_t coverage, |
| 486 GrGpu::DrawType drawType, | 495 GrGpu::DrawType drawType, |
| 487 const GrClipMaskManager::Scis
sorState& scissor, | 496 const GrClipMaskManager::Scis
sorState& scissor, |
| 488 const GrDeviceCoordTexture* d
stCopy) { | 497 const GrDeviceCoordTexture* d
stCopy) { |
| 489 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, | 498 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, |
| 490 (ds, *this->getGpu()->caps(), scisso
r, dstCopy, | 499 (ds, color, coverage, *this->getGpu(
)->caps(), scissor, |
| 491 drawType)); | 500 dstCopy, drawType)); |
| 492 if (ss->fState.mustSkip()) { | 501 if (ss->fState.mustSkip()) { |
| 493 fCmdBuffer.pop_back(); | 502 fCmdBuffer.pop_back(); |
| 494 return false; | 503 return false; |
| 495 } | 504 } |
| 496 if (fPrevState && *fPrevState == ss->fState) { | 505 if (fPrevState && *fPrevState == ss->fState) { |
| 497 fCmdBuffer.pop_back(); | 506 fCmdBuffer.pop_back(); |
| 498 } else { | 507 } else { |
| 499 fPrevState = &ss->fState; | 508 fPrevState = &ss->fState; |
| 500 this->recordTraceMarkersIfNecessary(); | 509 this->recordTraceMarkersIfNecessary(); |
| 501 } | 510 } |
| 502 return true; | 511 return true; |
| 503 } | 512 } |
| 504 | 513 |
| 505 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { | 514 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() { |
| 506 SkASSERT(!fCmdBuffer.empty()); | 515 SkASSERT(!fCmdBuffer.empty()); |
| 507 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); | 516 SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType)); |
| 508 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | 517 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); |
| 509 if (activeTraceMarkers.count() > 0) { | 518 if (activeTraceMarkers.count() > 0) { |
| 510 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); | 519 fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType); |
| 511 fGpuCmdMarkers.push_back(activeTraceMarkers); | 520 fGpuCmdMarkers.push_back(activeTraceMarkers); |
| 512 } | 521 } |
| 513 } | 522 } |
| OLD | NEW |