OLD | NEW |
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 "GrTargetCommands.h" | 8 #include "GrTargetCommands.h" |
9 | 9 |
10 #include "GrColor.h" | 10 #include "GrColor.h" |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 return NULL; | 184 return NULL; |
185 } | 185 } |
186 | 186 |
187 char* savedIndices; | 187 char* savedIndices; |
188 float* savedTransforms; | 188 float* savedTransforms; |
189 | 189 |
190 iodb->appendIndicesAndTransforms(indexValues, indexType, | 190 iodb->appendIndicesAndTransforms(indexValues, indexType, |
191 transformValues, transformType, | 191 transformValues, transformType, |
192 count, &savedIndices, &savedTransforms); | 192 count, &savedIndices, &savedTransforms); |
193 | 193 |
194 if (Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) { | 194 CmdBuffer::ReverseIter reverseIter(fCmdBuffer); |
195 // The previous command was also DrawPaths. Try to collapse this call in
to the one | 195 if (Cmd::kXferBarrier_CmdType == reverseIter->type()) { |
196 // before. Note that stenciling all the paths at once, then covering, ma
y not be | 196 // We can combine instanced path commands through Xfer barriers because
they are implemented |
197 // equivalent to two separate draw calls if there is overlap. Blending w
on't work, | 197 // by a single (non-overlapping) cover operation and they use fullscreen
barriers. |
198 // and the combined calls may also cancel each other's winding numbers i
n some | 198 reverseIter.previous(); |
199 // places. For now the winding numbers are only an issue if the fill is
even/odd, | 199 } |
200 // because DrawPaths is currently only used for glyphs, and glyphs in th
e same | 200 |
201 // font tend to all wind in the same direction. | 201 if (Cmd::kDrawPaths_CmdType == reverseIter->type()) { |
202 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back()); | 202 // The previous command was also DrawPaths. Try to combine this call wit
h the one before. |
| 203 // Note that when there is overlap, this is not equivalent to two separa
te draw calls. We |
| 204 // don't worry about that case because instanced path commands are only
used for text. |
| 205 DrawPaths* previous = static_cast<DrawPaths*>(reverseIter.get()); |
203 if (pathRange == previous->pathRange() && | 206 if (pathRange == previous->pathRange() && |
204 indexType == previous->fIndexType && | 207 indexType == previous->fIndexType && |
205 transformType == previous->fTransformType && | 208 transformType == previous->fTransformType && |
206 stencilSettings == previous->fStencilSettings && | 209 stencilSettings == previous->fStencilSettings && |
207 path_fill_type_is_winding(stencilSettings) && | 210 path_fill_type_is_winding(stencilSettings)) { |
208 !pipelineInfo.willBlendWithDst(pathProc)) { | 211 const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); |
209 const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexTy
pe); | 212 const int xformSize = GrPathRendering::PathTransformSize(transformTy
pe); |
210 const int xformSize = GrPathRendering::PathTransformSize(transfo
rmType); | 213 if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices
&& |
211 if (&previous->fIndices[previous->fCount*indexBytes] == savedInd
ices && | 214 (0 == xformSize || |
212 (0 == xformSize || | 215 &previous->fTransforms[previous->fCount*xformSize] == savedTran
sforms)) { |
213 &previous->fTransforms[previous->fCount*xformSize] == saved
Transforms)) { | 216 // Fold this DrawPaths call into the one previous. |
214 // Fold this DrawPaths call into the one previous. | 217 previous->fCount += count; |
215 previous->fCount += count; | 218 if (Cmd::kXferBarrier_CmdType == fCmdBuffer.back().type()) { |
216 return NULL; | 219 // Drop the barrier we fell through. |
| 220 fCmdBuffer.pop_back(); |
| 221 SkASSERT(!fXferBarrier); // The Xfer barrier should have bee
n fullscreen. |
217 } | 222 } |
| 223 SkASSERT(previous == &fCmdBuffer.back()); |
| 224 return NULL; |
| 225 } |
218 } | 226 } |
219 } | 227 } |
220 | 228 |
221 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; | 229 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange))
; |
222 dp->fIndices = savedIndices; | 230 dp->fIndices = savedIndices; |
223 dp->fIndexType = indexType; | 231 dp->fIndexType = indexType; |
224 dp->fTransforms = savedTransforms; | 232 dp->fTransforms = savedTransforms; |
225 dp->fTransformType = transformType; | 233 dp->fTransformType = transformType; |
226 dp->fCount = count; | 234 dp->fCount = count; |
227 dp->fStencilSettings = stencilSettings; | 235 dp->fStencilSettings = stencilSettings; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 280 |
273 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); | 281 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget)); |
274 clr->fColor = GrColor_ILLEGAL; | 282 clr->fColor = GrColor_ILLEGAL; |
275 return clr; | 283 return clr; |
276 } | 284 } |
277 | 285 |
278 void GrTargetCommands::reset() { | 286 void GrTargetCommands::reset() { |
279 fCmdBuffer.reset(); | 287 fCmdBuffer.reset(); |
280 fPrevState = NULL; | 288 fPrevState = NULL; |
281 fDrawBatch = NULL; | 289 fDrawBatch = NULL; |
| 290 fXferBarrier = NULL; |
282 } | 291 } |
283 | 292 |
284 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { | 293 void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) { |
285 if (fCmdBuffer.empty()) { | 294 if (fCmdBuffer.empty()) { |
286 return; | 295 return; |
287 } | 296 } |
288 | 297 |
289 // TODO this is temporary while batch is being rolled out | 298 // TODO this is temporary while batch is being rolled out |
290 this->closeBatch(); | 299 this->closeBatch(); |
291 iodb->getVertexAllocPool()->unmap(); | 300 iodb->getVertexAllocPool()->unmap(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { | 406 void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) { |
398 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); | 407 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget()); |
399 } | 408 } |
400 | 409 |
401 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { | 410 void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) { |
402 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); | 411 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint); |
403 } | 412 } |
404 | 413 |
405 void GrTargetCommands::XferBarrier::execute(GrGpu* gpu, const SetState* state) { | 414 void GrTargetCommands::XferBarrier::execute(GrGpu* gpu, const SetState* state) { |
406 SkASSERT(state); | 415 SkASSERT(state); |
| 416 SkASSERT(fRenderTarget == state->getRenderTarget()); |
407 if (kDstCopy_GrXferBarrierType == fType) { | 417 if (kDstCopy_GrXferBarrierType == fType) { |
408 GrDeviceCoordTexture dstCopy; | 418 GrDeviceCoordTexture dstCopy; |
409 gpu->setXferBarrier(fType, state->getRenderTarget(), fBounds, &dstCopy); | 419 gpu->setXferBarrier(fType, fRenderTarget, fReadBounds, &dstCopy); |
410 state->getXferProcessor()->updateDstCopy(dstCopy); | 420 for (int i = 0; i < fXferProcessors.count(); i++) { |
| 421 fXferProcessors[i]->updateDstCopy(dstCopy); |
| 422 } |
411 } else { | 423 } else { |
412 SkAssertResult(gpu->setXferBarrier(fType, state->getRenderTarget(), fBou
nds)); | 424 SkAssertResult(gpu->setXferBarrier(fType, fRenderTarget, fReadBounds)); |
413 } | 425 } |
414 } | 426 } |
415 | 427 |
416 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, | 428 GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrInOrderDrawBuffer*
iodb, |
417 GrSurface* dst, | 429 GrSurface* dst, |
418 GrSurface* src, | 430 GrSurface* src, |
419 const SkIRect& srcRec
t, | 431 const SkIRect& srcRec
t, |
420 const SkIPoint& dstPo
int) { | 432 const SkIPoint& dstPo
int) { |
421 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { | 433 if (iodb->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)) { |
422 this->closeBatch(); | 434 this->closeBatch(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 iodb->recordTraceMarkersIfNecessary(ss); | 492 iodb->recordTraceMarkersIfNecessary(ss); |
481 } | 493 } |
482 | 494 |
483 return this->recordXferBarrierIfNecessary(iodb, pipelineInfo); | 495 return this->recordXferBarrierIfNecessary(iodb, pipelineInfo); |
484 } | 496 } |
485 | 497 |
486 bool GrTargetCommands::recordXferBarrierIfNecessary(GrInOrderDrawBuffer* iodb, | 498 bool GrTargetCommands::recordXferBarrierIfNecessary(GrInOrderDrawBuffer* iodb, |
487 const GrDrawTarget::Pipeline
Info& info) { | 499 const GrDrawTarget::Pipeline
Info& info) { |
488 SkASSERT(fPrevState); | 500 SkASSERT(fPrevState); |
489 const GrXferProcessor& xp = *fPrevState->getXferProcessor(); | 501 const GrXferProcessor& xp = *fPrevState->getXferProcessor(); |
| 502 GrRenderTarget* rt = fPrevState->getRenderTarget(); |
490 | 503 |
491 GrXferBarrierType xbType = xp.setupDstReadIfNecessary(*iodb->caps(), info.ge
tCustomDstCopy()); | 504 GrXferBarrierType xbType = xp.setupDstReadIfNecessary(*iodb->caps(), info.ge
tCustomDstCopy()); |
492 | 505 |
493 if (kNone_GrXferBarrierType == xbType) { | 506 if (kNone_GrXferBarrierType == xbType) { |
494 return true; | 507 // The XP doesn't need a barrier, but the draw may still affect one. |
| 508 if (!fXferBarrier || rt != fXferBarrier->fRenderTarget) { |
| 509 return true; |
| 510 } |
| 511 SkIRect drawBounds; |
| 512 info.getQuickDrawBounds(&drawBounds); |
| 513 fXferBarrier->fInvalidBounds.join(drawBounds); |
| 514 } else { |
| 515 SkIRect xferBounds; |
| 516 if (!info.getConservativeDrawBounds(&xferBounds)) { |
| 517 // Early reject was detected. |
| 518 return false; |
| 519 } |
| 520 |
| 521 if (fXferBarrier && xbType == fXferBarrier->fType && rt == fXferBarrier-
>fRenderTarget && |
| 522 !SkIRect::IntersectsNoEmptyCheck(xferBounds, fXferBarrier->fInvalidB
ounds)) { |
| 523 // We can join with the previous barrier since they match and there
is no overlap. |
| 524 fXferBarrier->fReadBounds.join(xferBounds); |
| 525 fXferBarrier->fInvalidBounds.join(xferBounds); |
| 526 if (fXferBarrier->fXferProcessors.back() != &xp) { |
| 527 fXferBarrier->fXferProcessors.push_back(&xp); |
| 528 } |
| 529 } else { |
| 530 // We need to set a new barrier for this draw. |
| 531 this->closeBatch(); |
| 532 |
| 533 fXferBarrier = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, (xb
Type, rt)); |
| 534 fXferBarrier->fReadBounds = xferBounds; |
| 535 fXferBarrier->fInvalidBounds = xferBounds; |
| 536 fXferBarrier->fXferProcessors.push_back(&xp); |
| 537 |
| 538 iodb->recordTraceMarkersIfNecessary(fXferBarrier); |
| 539 } |
495 } | 540 } |
496 | 541 |
497 SkIRect xferBounds; | 542 if (fXferBarrier->fInvalidBounds.contains(0, 0, rt->width(), rt->height()))
{ |
498 if (!info.getConservativeDrawBounds(&xferBounds)) { | 543 // Close out the barrier since there is no valid area left. |
499 // Early reject was detected. | 544 fXferBarrier = NULL; |
500 return false; | |
501 } | 545 } |
502 | 546 |
503 this->closeBatch(); | |
504 | |
505 XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, (xbType)
); | |
506 xb->fBounds = xferBounds; | |
507 | |
508 iodb->recordTraceMarkersIfNecessary(xb); | |
509 | |
510 return true; | 547 return true; |
511 } | 548 } |
512 | 549 |
OLD | NEW |