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 "GrBufferAllocPool.h" | |
11 #include "GrDefaultGeoProcFactory.h" | 10 #include "GrDefaultGeoProcFactory.h" |
12 #include "GrDrawTargetCaps.h" | |
13 #include "GrGpu.h" | |
14 #include "GrTemplates.h" | 11 #include "GrTemplates.h" |
15 #include "GrFontCache.h" | |
16 #include "GrTexture.h" | |
17 | 12 |
18 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, | 13 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu, |
19 GrVertexBufferAllocPool* vertexPool, | 14 GrVertexBufferAllocPool* vertexPool, |
20 GrIndexBufferAllocPool* indexPool) | 15 GrIndexBufferAllocPool* indexPool) |
21 : INHERITED(gpu, vertexPool, indexPool) | 16 : INHERITED(gpu, vertexPool, indexPool) |
22 , fCommands(gpu, vertexPool, indexPool) | 17 , fCommands(gpu, vertexPool, indexPool) |
23 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) | 18 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) |
24 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) | 19 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) |
25 , fDrawID(0) { | 20 , fDrawID(0) { |
26 | 21 |
27 SkASSERT(vertexPool); | 22 SkASSERT(vertexPool); |
28 SkASSERT(indexPool); | 23 SkASSERT(indexPool); |
29 } | 24 } |
30 | 25 |
31 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { | 26 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { |
32 this->reset(); | 27 this->reset(); |
33 } | 28 } |
34 | 29 |
35 void GrTargetCommands::closeBatch() { | |
36 if (fDrawBatch) { | |
37 fBatchTarget.resetNumberOfDraws(); | |
38 fDrawBatch->execute(NULL, fPrevState); | |
39 fDrawBatch->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws()); | |
40 fDrawBatch = NULL; | |
41 } | |
42 } | |
43 | |
44 //////////////////////////////////////////////////////////////////////////////// | 30 //////////////////////////////////////////////////////////////////////////////// |
45 | 31 |
46 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we | 32 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we |
47 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords | 33 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords |
48 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we | 34 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we |
49 haven't seen a use case which frequently switches between local rect and no
local rect draws. | 35 haven't seen a use case which frequently switches between local rect and no
local rect draws. |
50 | 36 |
51 The color param is used to determine whether the opaque hint can be set on t
he draw state. | 37 The color param is used to determine whether the opaque hint can be set on t
he draw state. |
52 The caller must populate the vertex colors itself. | 38 The caller must populate the vertex colors itself. |
53 | 39 |
54 The vertex attrib order is always pos, color, [local coords]. | 40 The vertex attrib order is always pos, color, [local coords]. |
55 */ | 41 */ |
56 static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords, | 42 static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords, |
57 GrColor color, | 43 GrColor color, |
58 const SkMatrix* localMatrix) { | 44 const SkMatrix* localMatrix) { |
59 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | 45 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | |
60 GrDefaultGeoProcFactory::kColor_GPType; | 46 GrDefaultGeoProcFactory::kColor_GPType; |
61 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPTyp
e : 0; | 47 flags |= hasExplicitLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPTyp
e : 0; |
62 if (localMatrix) { | 48 if (localMatrix) { |
63 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *loc
alMatrix, | 49 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), *loc
alMatrix, |
64 GrColorIsOpaque(color)); | 50 GrColorIsOpaque(color)); |
65 } else { | 51 } else { |
66 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMa
trix::I(), | 52 return GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMa
trix::I(), |
67 GrColorIsOpaque(color)); | 53 GrColorIsOpaque(color)); |
68 } | 54 } |
69 } | 55 } |
70 | 56 |
71 static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
gs) { | |
72 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Fa
ce; | |
73 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); | |
74 if (isWinding) { | |
75 // Double check that it is in fact winding. | |
76 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); | |
77 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); | |
78 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); | |
79 SkASSERT(!pathStencilSettings.isTwoSided()); | |
80 } | |
81 return isWinding; | |
82 } | |
83 | |
84 class RectBatch : public GrBatch { | 57 class RectBatch : public GrBatch { |
85 public: | 58 public: |
86 struct Geometry { | 59 struct Geometry { |
87 GrColor fColor; | 60 GrColor fColor; |
88 SkMatrix fViewMatrix; | 61 SkMatrix fViewMatrix; |
89 SkRect fRect; | 62 SkRect fRect; |
90 bool fHasLocalRect; | 63 bool fHasLocalRect; |
91 bool fHasLocalMatrix; | 64 bool fHasLocalMatrix; |
92 SkRect fLocalRect; | 65 SkRect fLocalRect; |
93 SkMatrix fLocalMatrix; | 66 SkMatrix fLocalMatrix; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 geometry.fHasLocalMatrix = false; | 285 geometry.fHasLocalMatrix = false; |
313 } | 286 } |
314 | 287 |
315 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry)); | 288 SkAutoTUnref<GrBatch> batch(RectBatch::Create(geometry)); |
316 | 289 |
317 SkRect bounds = rect; | 290 SkRect bounds = rect; |
318 viewMatrix.mapRect(&bounds); | 291 viewMatrix.mapRect(&bounds); |
319 this->drawBatch(pipelineBuilder, batch, &bounds); | 292 this->drawBatch(pipelineBuilder, batch, &bounds); |
320 } | 293 } |
321 | 294 |
322 int GrTargetCommands::concatInstancedDraw(GrInOrderDrawBuffer* iodb, | |
323 const GrDrawTarget::DrawInfo& info) { | |
324 SkASSERT(!fCmdBuffer.empty()); | |
325 SkASSERT(info.isInstanced()); | |
326 | |
327 const GrIndexBuffer* ib; | |
328 if (!iodb->canConcatToIndexBuffer(&ib)) { | |
329 return 0; | |
330 } | |
331 | |
332 // Check if there is a draw info that is compatible that uses the same VB fr
om the pool and | |
333 // the same IB | |
334 if (Cmd::kDraw_Cmd != fCmdBuffer.back().type()) { | |
335 return 0; | |
336 } | |
337 | |
338 Draw* draw = static_cast<Draw*>(&fCmdBuffer.back()); | |
339 | |
340 if (!draw->fInfo.isInstanced() || | |
341 draw->fInfo.primitiveType() != info.primitiveType() || | |
342 draw->fInfo.verticesPerInstance() != info.verticesPerInstance() || | |
343 draw->fInfo.indicesPerInstance() != info.indicesPerInstance() || | |
344 draw->fInfo.vertexBuffer() != info.vertexBuffer() || | |
345 draw->fInfo.indexBuffer() != ib) { | |
346 return 0; | |
347 } | |
348 if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != info.startVerte
x()) { | |
349 return 0; | |
350 } | |
351 | |
352 // how many instances can be concat'ed onto draw given the size of the index
buffer | |
353 int instancesToConcat = iodb->indexCountInCurrentSource() / info.indicesPerI
nstance(); | |
354 instancesToConcat -= draw->fInfo.instanceCount(); | |
355 instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); | |
356 | |
357 draw->fInfo.adjustInstanceCount(instancesToConcat); | |
358 | |
359 // update last fGpuCmdMarkers to include any additional trace markers that h
ave been added | |
360 iodb->recordTraceMarkersIfNecessary(draw); | |
361 return instancesToConcat; | |
362 } | |
363 | |
364 void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp, | 295 void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp, |
365 const DrawInfo& info, | 296 const DrawInfo& info, |
366 const PipelineInfo& pipelineInfo) { | 297 const PipelineInfo& pipelineInfo) { |
367 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineIn
fo); | 298 GrTargetCommands::Cmd* cmd = fCommands.recordDraw(this, gp, info, pipelineIn
fo); |
368 this->recordTraceMarkersIfNecessary(cmd); | 299 this->recordTraceMarkersIfNecessary(cmd); |
369 } | 300 } |
370 | 301 |
371 GrTargetCommands::Cmd* GrTargetCommands::recordDraw( | |
372 GrInOrderDrawBuffer* iodb, | |
373 const GrGeometryProcessor* gp, | |
374 const GrDrawTarget::DrawInfo&
info, | |
375 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
376 SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer())); | |
377 this->closeBatch(); | |
378 | |
379 if (!this->setupPipelineAndShouldDraw(iodb, gp, pipelineInfo)) { | |
380 return NULL; | |
381 } | |
382 | |
383 Draw* draw; | |
384 if (info.isInstanced()) { | |
385 int instancesConcated = this->concatInstancedDraw(iodb, info); | |
386 if (info.instanceCount() > instancesConcated) { | |
387 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | |
388 draw->fInfo.adjustInstanceCount(-instancesConcated); | |
389 } else { | |
390 return NULL; | |
391 } | |
392 } else { | |
393 draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info)); | |
394 } | |
395 | |
396 return draw; | |
397 } | |
398 | |
399 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, | 302 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, |
400 const PipelineInfo& pipelineInfo) { | 303 const PipelineInfo& pipelineInfo) { |
401 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipeline
Info); | 304 GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipeline
Info); |
402 this->recordTraceMarkersIfNecessary(cmd); | 305 this->recordTraceMarkersIfNecessary(cmd); |
403 } | 306 } |
404 | 307 |
405 GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch( | |
406 GrInOrderDrawBuffer* iodb, | |
407 GrBatch* batch, | |
408 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
409 if (!this->setupPipelineAndShouldDraw(iodb, batch, pipelineInfo)) { | |
410 return NULL; | |
411 } | |
412 | |
413 // Check if there is a Batch Draw we can batch with | |
414 if (Cmd::kDrawBatch_Cmd != fCmdBuffer.back().type() || !fDrawBatch) { | |
415 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | |
416 return fDrawBatch; | |
417 } | |
418 | |
419 SkASSERT(&fCmdBuffer.back() == fDrawBatch); | |
420 if (!fDrawBatch->fBatch->combineIfPossible(batch)) { | |
421 this->closeBatch(); | |
422 fDrawBatch = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fB
atchTarget)); | |
423 } | |
424 | |
425 return fDrawBatch; | |
426 } | |
427 | |
428 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
, | 308 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
, |
429 const GrPathProcessor* pathProc, | 309 const GrPathProcessor* pathProc, |
430 const GrPath* path, | 310 const GrPath* path, |
431 const GrScissorState& scissorState, | 311 const GrScissorState& scissorState, |
432 const GrStencilSettings& stencilSettings
) { | 312 const GrStencilSettings& stencilSettings
) { |
433 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuild
er, | 313 GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuild
er, |
434 pathProc, path, sci
ssorState, | 314 pathProc, path, sci
ssorState, |
435 stencilSettings); | 315 stencilSettings); |
436 this->recordTraceMarkersIfNecessary(cmd); | 316 this->recordTraceMarkersIfNecessary(cmd); |
437 } | 317 } |
438 | 318 |
439 GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath( | |
440 GrInOrderDrawBuffer* iod
b, | |
441 const GrPipelineBuilder&
pipelineBuilder, | |
442 const GrPathProcessor* p
athProc, | |
443 const GrPath* path, | |
444 const GrScissorState& sc
issorState, | |
445 const GrStencilSettings&
stencilSettings) { | |
446 this->closeBatch(); | |
447 | |
448 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, | |
449 (path, pipelineBuilder.getRenderT
arget())); | |
450 | |
451 sp->fScissor = scissorState; | |
452 sp->fUseHWAA = pipelineBuilder.isHWAntialias(); | |
453 sp->fViewMatrix = pathProc->viewMatrix(); | |
454 sp->fStencil = stencilSettings; | |
455 return sp; | |
456 } | |
457 | |
458 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, | 319 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, |
459 const GrPath* path, | 320 const GrPath* path, |
460 const GrStencilSettings& stencilSettings, | 321 const GrStencilSettings& stencilSettings, |
461 const PipelineInfo& pipelineInfo) { | 322 const PipelineInfo& pipelineInfo) { |
462 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, | 323 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, |
463 path, stencilSettings, | 324 path, stencilSettings, |
464 pipelineInfo); | 325 pipelineInfo); |
465 this->recordTraceMarkersIfNecessary(cmd); | 326 this->recordTraceMarkersIfNecessary(cmd); |
466 } | 327 } |
467 | 328 |
468 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath( | |
469 GrInOrderDrawBuffer* iodb, | |
470 const GrPathProcessor* pathPro
c, | |
471 const GrPath* path, | |
472 const GrStencilSettings& stenc
ilSettings, | |
473 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
474 this->closeBatch(); | |
475 | |
476 // TODO: Only compare the subset of GrPipelineBuilder relevant to path cover
ing? | |
477 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { | |
478 return NULL; | |
479 } | |
480 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path)); | |
481 dp->fStencilSettings = stencilSettings; | |
482 return dp; | |
483 } | |
484 | |
485 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, | 329 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, |
486 const GrPathRange* pathRange, | 330 const GrPathRange* pathRange, |
487 const void* indices, | 331 const void* indices, |
488 PathIndexType indexType, | 332 PathIndexType indexType, |
489 const float transformValues[], | 333 const float transformValues[], |
490 PathTransformType transformType, | 334 PathTransformType transformType, |
491 int count, | 335 int count, |
492 const GrStencilSettings& stencilSettings, | 336 const GrStencilSettings& stencilSettings, |
493 const PipelineInfo& pipelineInfo) { | 337 const PipelineInfo& pipelineInfo) { |
494 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathR
ange, | 338 GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathR
ange, |
495 indices, indexType, t
ransformValues, | 339 indices, indexType, t
ransformValues, |
496 transformType, count, | 340 transformType, count, |
497 stencilSettings, pipe
lineInfo); | 341 stencilSettings, pipe
lineInfo); |
498 this->recordTraceMarkersIfNecessary(cmd); | 342 this->recordTraceMarkersIfNecessary(cmd); |
499 } | 343 } |
500 | 344 |
501 GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths( | |
502 GrInOrderDrawBuffer* iodb, | |
503 const GrPathProcessor* pathPro
c, | |
504 const GrPathRange* pathRange, | |
505 const void* indexValues, | |
506 GrDrawTarget::PathIndexType in
dexType, | |
507 const float transformValues[], | |
508 GrDrawTarget::PathTransformTyp
e transformType, | |
509 int count, | |
510 const GrStencilSettings& stenc
ilSettings, | |
511 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
512 SkASSERT(pathRange); | |
513 SkASSERT(indexValues); | |
514 SkASSERT(transformValues); | |
515 this->closeBatch(); | |
516 | |
517 if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) { | |
518 return NULL; | |
519 } | |
520 | |
521 char* savedIndices; | |
522 float* savedTransforms; | |
523 | |
524 iodb->appendIndicesAndTransforms(indexValues, indexType, | |
525 transformValues, transformType, | |
526 count, &savedIndices, &savedTransforms); | |
527 | |
528 if (Cmd::kDrawPaths_Cmd == fCmdBuffer.back().type()) { | |
529 // The previous command was also DrawPaths. Try to collapse this call in
to the one | |
530 // before. Note that stenciling all the paths at once, then covering, ma
y not be | |
531 // equivalent to two separate draw calls if there is overlap. Blending w
on't work, | |
532 // and the combined calls may also cancel each other's winding numbers i
n some | |
533 // places. For now the winding numbers are only an issue if the fill is
even/odd, | |
534 // because DrawPaths is currently only used for glyphs, and glyphs in th
e same | |
535 // font tend to all wind in the same direction. | |
536 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | |
537 if (pathRange == previous->pathRange() && | |
538 indexType == previous->fIndexType && | |
539 transformType == previous->fTransformType && | |
540 stencilSettings == previous->fStencilSettings && | |
541 path_fill_type_is_winding(stencilSettings) && | |
542 !pipelineInfo.willBlendWithDst(pathProc)) { | |
543 const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexTy
pe); | |
544 const int xformSize = GrPathRendering::PathTransformSize(transfo
rmType); | |
545 if (&previous->fIndices[previous->fCount*indexBytes] == savedInd
ices && | |
546 (0 == xformSize || | |
547 &previous->fTransforms[previous->fCount*xformSize] == saved
Transforms)) { | |
548 // Fold this DrawPaths call into the one previous. | |
549 previous->fCount += count; | |
550 return NULL; | |
551 } | |
552 } | |
553 } | |
554 | |
555 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | |
556 dp->fIndices = savedIndices; | |
557 dp->fIndexType = indexType; | |
558 dp->fTransforms = savedTransforms; | |
559 dp->fTransformType = transformType; | |
560 dp->fCount = count; | |
561 dp->fStencilSettings = stencilSettings; | |
562 return dp; | |
563 } | |
564 | |
565 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, | 345 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, |
566 bool canIgnoreRect, GrRenderTarget* renderTarg
et) { | 346 bool canIgnoreRect, GrRenderTarget* renderTarg
et) { |
567 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, | 347 GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, |
568 canIgnoreRect, renderTarg
et); | 348 canIgnoreRect, renderTarg
et); |
569 this->recordTraceMarkersIfNecessary(cmd); | 349 this->recordTraceMarkersIfNecessary(cmd); |
570 } | 350 } |
571 | 351 |
572 GrTargetCommands::Cmd* GrTargetCommands::recordClear(GrInOrderDrawBuffer* iodb, | |
573 const SkIRect* rect, | |
574 GrColor color, | |
575 bool canIgnoreRect, | |
576 GrRenderTarget* renderTarge
t) { | |
577 SkASSERT(renderTarget); | |
578 this->closeBatch(); | |
579 | |
580 SkIRect r; | |
581 if (NULL == rect) { | |
582 // We could do something smart and remove previous draws and clears to | |
583 // the current render target. If we get that smart we have to make sure | |
584 // those draws aren't read before this clear (render-to-texture). | |
585 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height()); | |
586 rect = &r; | |
587 } | |
588 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | |
589 GrColorIsPMAssert(color); | |
590 clr->fColor = color; | |
591 clr->fRect = *rect; | |
592 clr->fCanIgnoreRect = canIgnoreRect; | |
593 return clr; | |
594 } | |
595 | |
596 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, | 352 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, |
597 bool insideClip, | 353 bool insideClip, |
598 GrRenderTarget* renderTarget) { | 354 GrRenderTarget* renderTarget) { |
599 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, | 355 GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, |
600 insideClip, re
nderTarget); | 356 insideClip, re
nderTarget); |
601 this->recordTraceMarkersIfNecessary(cmd); | 357 this->recordTraceMarkersIfNecessary(cmd); |
602 } | 358 } |
603 | 359 |
604 GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(GrInOrderDrawBuf
fer* iodb, | |
605 const SkIRect& r
ect, | |
606 bool insideClip, | |
607 GrRenderTarget*
renderTarget) { | |
608 SkASSERT(renderTarget); | |
609 this->closeBatch(); | |
610 | |
611 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilCli
p, (renderTarget)); | |
612 clr->fRect = rect; | |
613 clr->fInsideClip = insideClip; | |
614 return clr; | |
615 } | |
616 | |
617 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { | 360 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { |
618 if (!this->caps()->discardRenderTargetSupport()) { | 361 if (!this->caps()->discardRenderTargetSupport()) { |
619 return; | 362 return; |
620 } | 363 } |
621 | 364 |
622 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); | 365 GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); |
623 this->recordTraceMarkersIfNecessary(cmd); | 366 this->recordTraceMarkersIfNecessary(cmd); |
624 } | 367 } |
625 | 368 |
626 GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrInOrderDrawBuffer* iodb
, | |
627 GrRenderTarget* renderTar
get) { | |
628 SkASSERT(renderTarget); | |
629 this->closeBatch(); | |
630 | |
631 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | |
632 clr->fColor = GrColor_ILLEGAL; | |
633 return clr; | |
634 } | |
635 | |
636 void GrInOrderDrawBuffer::onReset() { | 369 void GrInOrderDrawBuffer::onReset() { |
637 fCommands.reset(); | 370 fCommands.reset(); |
638 fPathIndexBuffer.rewind(); | 371 fPathIndexBuffer.rewind(); |
639 fPathTransformBuffer.rewind(); | 372 fPathTransformBuffer.rewind(); |
640 fGpuCmdMarkers.reset(); | 373 fGpuCmdMarkers.reset(); |
641 } | 374 } |
642 | 375 |
643 void GrTargetCommands::reset() { | |
644 fCmdBuffer.reset(); | |
645 fPrevState = NULL; | |
646 fDrawBatch = NULL; | |
647 } | |
648 | |
649 void GrInOrderDrawBuffer::onFlush() { | 376 void GrInOrderDrawBuffer::onFlush() { |
650 fCommands.flush(this); | 377 fCommands.flush(this); |
651 ++fDrawID; | 378 ++fDrawID; |
652 } | 379 } |
653 | 380 |
654 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { | |
655 if (fCmdBuffer.empty()) { | |
656 return; | |
657 } | |
658 | |
659 // Updated every time we find a set state cmd to reflect the current state i
n the playback | |
660 // stream. | |
661 SetState* currentState = NULL; | |
662 | |
663 // TODO this is temporary while batch is being rolled out | |
664 this->closeBatch(); | |
665 iodb->getVertexAllocPool()->unmap(); | |
666 iodb->getIndexAllocPool()->unmap(); | |
667 fBatchTarget.preFlush(); | |
668 | |
669 currentState = NULL; | |
670 CmdBuffer::Iter iter(fCmdBuffer); | |
671 | |
672 int currCmdMarker = 0; | |
673 | |
674 GrGpu* gpu = iodb->getGpu(); | |
675 | |
676 int i = 0; | |
677 while (iter.next()) { | |
678 i++; | |
679 GrGpuTraceMarker newMarker("", -1); | |
680 SkString traceString; | |
681 if (iter->isTraced()) { | |
682 traceString = iodb->getCmdString(currCmdMarker); | |
683 newMarker.fMarker = traceString.c_str(); | |
684 gpu->addGpuTraceMarker(&newMarker); | |
685 ++currCmdMarker; | |
686 } | |
687 | |
688 // TODO temporary hack | |
689 if (Cmd::kDrawBatch_Cmd == iter->type()) { | |
690 DrawBatch* db = reinterpret_cast<DrawBatch*>(iter.get()); | |
691 fBatchTarget.flushNext(db->fBatch->numberOfDraws()); | |
692 continue; | |
693 } | |
694 | |
695 if (Cmd::kSetState_Cmd == iter->type()) { | |
696 SetState* ss = reinterpret_cast<SetState*>(iter.get()); | |
697 | |
698 // TODO sometimes we have a prim proc, othertimes we have a GrBatch.
Eventually we | |
699 // will only have GrBatch and we can delete this | |
700 if (ss->fPrimitiveProcessor) { | |
701 gpu->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor, | |
702 *ss->getPipeline(), | |
703 ss->fBatchTracker); | |
704 } | |
705 currentState = ss; | |
706 } else { | |
707 iter->execute(gpu, currentState); | |
708 } | |
709 | |
710 if (iter->isTraced()) { | |
711 gpu->removeGpuTraceMarker(&newMarker); | |
712 } | |
713 } | |
714 | |
715 // TODO see copious notes about hack | |
716 fBatchTarget.postFlush(); | |
717 } | |
718 | |
719 void GrTargetCommands::Draw::execute(GrGpu* gpu, const SetState* state) { | |
720 SkASSERT(state); | |
721 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
722 &state->fBatchTracker); | |
723 gpu->draw(args, fInfo); | |
724 } | |
725 | |
726 void GrTargetCommands::StencilPath::execute(GrGpu* gpu, const SetState*) { | |
727 GrGpu::StencilPathState state; | |
728 state.fRenderTarget = fRenderTarget.get(); | |
729 state.fScissor = &fScissor; | |
730 state.fStencil = &fStencil; | |
731 state.fUseHWAA = fUseHWAA; | |
732 state.fViewMatrix = &fViewMatrix; | |
733 | |
734 gpu->stencilPath(this->path(), state); | |
735 } | |
736 | |
737 void GrTargetCommands::DrawPath::execute(GrGpu* gpu, const SetState* state) { | |
738 SkASSERT(state); | |
739 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
740 &state->fBatchTracker); | |
741 gpu->drawPath(args, this->path(), fStencilSettings); | |
742 } | |
743 | |
744 void GrTargetCommands::DrawPaths::execute(GrGpu* gpu, const SetState* state) { | |
745 SkASSERT(state); | |
746 DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state
->fDesc, | |
747 &state->fBatchTracker); | |
748 gpu->drawPaths(args, this->pathRange(), | |
749 fIndices, fIndexType, | |
750 fTransforms, fTransformType, | |
751 fCount, fStencilSettings); | |
752 } | |
753 | |
754 void GrTargetCommands::DrawBatch::execute(GrGpu*, const SetState* state) { | |
755 SkASSERT(state); | |
756 fBatch->generateGeometry(fBatchTarget, state->getPipeline()); | |
757 } | |
758 | |
759 void GrTargetCommands::SetState::execute(GrGpu*, const SetState*) {} | |
760 | |
761 void GrTargetCommands::Clear::execute(GrGpu* gpu, const SetState*) { | |
762 if (GrColor_ILLEGAL == fColor) { | |
763 gpu->discard(this->renderTarget()); | |
764 } else { | |
765 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget()); | |
766 } | |
767 } | |
768 | |
769 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { | |
770 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | |
771 } | |
772 | |
773 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { | |
774 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); | |
775 } | |
776 | |
777 bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, | 381 bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, |
778 GrSurface* src, | 382 GrSurface* src, |
779 const SkIRect& srcRect, | 383 const SkIRect& srcRect, |
780 const SkIPoint& dstPoint) { | 384 const SkIPoint& dstPoint) { |
781 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src, | 385 GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(this, dst, src, |
782 srcRect, dstPoint); | 386 srcRect, dstPoint); |
783 this->recordTraceMarkersIfNecessary(cmd); | 387 this->recordTraceMarkersIfNecessary(cmd); |
784 return SkToBool(cmd); | 388 return SkToBool(cmd); |
785 } | 389 } |
786 | 390 |
787 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, | |
788 GrSurface* dst, | |
789 GrSurface* src, | |
790 const SkIRect& srcRec
t, | |
791 const SkIPoint& dstPo
int) { | |
792 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { | |
793 this->closeBatch(); | |
794 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst
, src)); | |
795 cs->fSrcRect = srcRect; | |
796 cs->fDstPoint = dstPoint; | |
797 return cs; | |
798 } | |
799 return NULL; | |
800 } | |
801 | |
802 bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb, | |
803 const GrPrimitiveProcessor* pr
imProc, | |
804 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
805 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (primProc)); | |
806 iodb->setupPipeline(pipelineInfo, ss->pipelineLocation()); | |
807 | |
808 if (ss->getPipeline()->mustSkip()) { | |
809 fCmdBuffer.pop_back(); | |
810 return false; | |
811 } | |
812 | |
813 ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker, | |
814 ss->getPipeline()->getInitBatchTra
cker()); | |
815 | |
816 if (fPrevState && fPrevState->fPrimitiveProcessor.get() && | |
817 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker, | |
818 *ss->fPrimitiveProcessor, | |
819 ss->fBatchTracker) && | |
820 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { | |
821 fCmdBuffer.pop_back(); | |
822 } else { | |
823 fPrevState = ss; | |
824 iodb->recordTraceMarkersIfNecessary(ss); | |
825 } | |
826 return true; | |
827 } | |
828 | |
829 bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb, | |
830 GrBatch* batch, | |
831 const GrDrawTarget::PipelineIn
fo& pipelineInfo) { | |
832 SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, ()); | |
833 iodb->setupPipeline(pipelineInfo, ss->pipelineLocation()); | |
834 | |
835 if (ss->getPipeline()->mustSkip()) { | |
836 fCmdBuffer.pop_back(); | |
837 return false; | |
838 } | |
839 | |
840 batch->initBatchTracker(ss->getPipeline()->getInitBatchTracker()); | |
841 | |
842 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() && | |
843 fPrevState->getPipeline()->isEqual(*ss->getPipeline())) { | |
844 fCmdBuffer.pop_back(); | |
845 } else { | |
846 this->closeBatch(); | |
847 fPrevState = ss; | |
848 iodb->recordTraceMarkersIfNecessary(ss); | |
849 } | |
850 return true; | |
851 } | |
852 | |
853 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c
md) { | 391 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c
md) { |
854 if (!cmd) { | 392 if (!cmd) { |
855 return; | 393 return; |
856 } | 394 } |
857 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); | 395 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); |
858 if (activeTraceMarkers.count() > 0) { | 396 if (activeTraceMarkers.count() > 0) { |
859 if (cmd->isTraced()) { | 397 if (cmd->isTraced()) { |
860 fGpuCmdMarkers.back().addSet(activeTraceMarkers); | 398 fGpuCmdMarkers.back().addSet(activeTraceMarkers); |
861 } else { | 399 } else { |
862 cmd->makeTraced(); | 400 cmd->makeTraced(); |
863 fGpuCmdMarkers.push_back(activeTraceMarkers); | 401 fGpuCmdMarkers.push_back(activeTraceMarkers); |
864 } | 402 } |
865 } | 403 } |
866 } | 404 } |
867 | 405 |
868 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, | 406 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount, |
869 size_t vertexStride, | 407 size_t vertexStride, |
870 int indexCount) { | 408 int indexCount) { |
871 fCommands.closeBatch(); | 409 fCommands.closeBatch(); |
872 | 410 |
873 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i
ndexCount); | 411 this->INHERITED::willReserveVertexAndIndexSpace(vertexCount, vertexStride, i
ndexCount); |
874 } | 412 } |
OLD | NEW |