OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 "GrDrawTarget.h" | 8 #include "GrDrawTarget.h" |
9 | 9 |
10 #include "GrAuditTrail.h" | 10 #include "GrAuditTrail.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 108 |
109 #ifdef SK_DEBUG | 109 #ifdef SK_DEBUG |
110 void GrDrawTarget::dump() const { | 110 void GrDrawTarget::dump() const { |
111 SkDebugf("--------------------------------------------------------------\n")
; | 111 SkDebugf("--------------------------------------------------------------\n")
; |
112 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->ge
tUniqueID() : -1); | 112 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->ge
tUniqueID() : -1); |
113 SkDebugf("relies On (%d): ", fDependencies.count()); | 113 SkDebugf("relies On (%d): ", fDependencies.count()); |
114 for (int i = 0; i < fDependencies.count(); ++i) { | 114 for (int i = 0; i < fDependencies.count(); ++i) { |
115 SkDebugf("%d, ", fDependencies[i]->fDebugID); | 115 SkDebugf("%d, ", fDependencies[i]->fDebugID); |
116 } | 116 } |
117 SkDebugf("\n"); | 117 SkDebugf("\n"); |
118 SkDebugf("batches (%d):\n", fBatches.count()); | 118 SkDebugf("batches (%d):\n", fRecordedBatches.count()); |
119 for (int i = 0; i < fBatches.count(); ++i) { | 119 for (int i = 0; i < fRecordedBatches.count(); ++i) { |
120 SkDebugf("*******************************\n"); | 120 SkDebugf("*******************************\n"); |
121 if (!fBatches[i]) { | 121 if (!fRecordedBatches[i].fBatch) { |
122 SkDebugf("%d: <combined forward>\n", i); | 122 SkDebugf("%d: <combined forward>\n", i); |
123 } else { | 123 } else { |
124 SkDebugf("%d: %s\n", i, fBatches[i]->name()); | 124 SkDebugf("%d: %s\n", i, fRecordedBatches[i].fBatch->name()); |
125 SkString str = fBatches[i]->dumpInfo(); | 125 SkString str = fRecordedBatches[i].fBatch->dumpInfo(); |
126 SkDebugf("%s\n", str.c_str()); | 126 SkDebugf("%s\n", str.c_str()); |
| 127 const SkRect& clippedBounds = fRecordedBatches[i].fClippedBounds; |
| 128 SkDebugf("ClippedBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", |
| 129 clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRig
ht, |
| 130 clippedBounds.fBottom); |
127 } | 131 } |
128 } | 132 } |
129 } | 133 } |
130 #endif | 134 #endif |
131 | 135 |
132 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
der, | 136 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
der, |
133 GrRenderTarget* rt, | 137 GrRenderTarget* rt, |
134 const GrClip& clip, | 138 const GrClip& clip, |
135 const GrPipelineOptimizations& optimi
zations, | 139 const GrPipelineOptimizations& optimi
zations, |
136 GrXferProcessor::DstTexture* dstTextu
re, | 140 GrXferProcessor::DstTexture* dstTextu
re, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 196 } |
193 | 197 |
194 void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) { | 198 void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) { |
195 // Semi-usually the drawTargets are already closed at this point, but someti
mes Ganesh | 199 // Semi-usually the drawTargets are already closed at this point, but someti
mes Ganesh |
196 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won'
t be closed | 200 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won'
t be closed |
197 // but need to be flushed anyway. Closing such drawTargets here will mean ne
w | 201 // but need to be flushed anyway. Closing such drawTargets here will mean ne
w |
198 // drawTargets will be created to replace them if the SkGpuDevice(s) write t
o them again. | 202 // drawTargets will be created to replace them if the SkGpuDevice(s) write t
o them again. |
199 this->makeClosed(); | 203 this->makeClosed(); |
200 | 204 |
201 // Loop over the batches that haven't yet generated their geometry | 205 // Loop over the batches that haven't yet generated their geometry |
202 for (int i = 0; i < fBatches.count(); ++i) { | 206 for (int i = 0; i < fRecordedBatches.count(); ++i) { |
203 if (fBatches[i]) { | 207 if (fRecordedBatches[i].fBatch) { |
204 fBatches[i]->prepare(flushState); | 208 fRecordedBatches[i].fBatch->prepare(flushState); |
205 } | 209 } |
206 } | 210 } |
207 | 211 |
208 if (fInstancedRendering) { | 212 if (fInstancedRendering) { |
209 fInstancedRendering->beginFlush(flushState->resourceProvider()); | 213 fInstancedRendering->beginFlush(flushState->resourceProvider()); |
210 } | 214 } |
211 } | 215 } |
212 | 216 |
213 void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) { | 217 void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) { |
214 // Draw all the generated geometry. | 218 // Draw all the generated geometry. |
215 SkRandom random; | 219 SkRandom random; |
216 GrRenderTarget* currentRT = nullptr; | 220 GrRenderTarget* currentRT = nullptr; |
217 SkAutoTDelete<GrGpuCommandBuffer> commandBuffer; | 221 SkAutoTDelete<GrGpuCommandBuffer> commandBuffer; |
218 SkRect bounds = SkRect::MakeEmpty(); | 222 SkRect bounds = SkRect::MakeEmpty(); |
219 for (int i = 0; i < fBatches.count(); ++i) { | 223 for (int i = 0; i < fRecordedBatches.count(); ++i) { |
220 if (!fBatches[i]) { | 224 if (!fRecordedBatches[i].fBatch) { |
221 continue; | 225 continue; |
222 } | 226 } |
223 if (fBatches[i]->renderTarget() != currentRT) { | 227 if (fRecordedBatches[i].fBatch->renderTarget() != currentRT) { |
224 if (commandBuffer) { | 228 if (commandBuffer) { |
225 commandBuffer->end(); | 229 commandBuffer->end(); |
226 if (bounds.intersect(0, 0, | 230 if (bounds.intersect(0, 0, |
227 SkIntToScalar(currentRT->width()), | 231 SkIntToScalar(currentRT->width()), |
228 SkIntToScalar(currentRT->height()))) { | 232 SkIntToScalar(currentRT->height()))) { |
229 SkIRect iBounds; | 233 SkIRect iBounds; |
230 bounds.roundOut(&iBounds); | 234 bounds.roundOut(&iBounds); |
231 commandBuffer->submit(iBounds); | 235 commandBuffer->submit(iBounds); |
232 } | 236 } |
233 commandBuffer.reset(); | 237 commandBuffer.reset(); |
234 } | 238 } |
235 bounds.setEmpty(); | 239 bounds.setEmpty(); |
236 currentRT = fBatches[i]->renderTarget(); | 240 currentRT = fRecordedBatches[i].fBatch->renderTarget(); |
237 if (currentRT) { | 241 if (currentRT) { |
238 static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStor
eInfo | 242 static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStor
eInfo |
239 { GrGpuCommandBuffer::LoadOp::kLoad,GrGpuCommandBuffer::Stor
eOp::kStore, | 243 { GrGpuCommandBuffer::LoadOp::kLoad,GrGpuCommandBuffer::Stor
eOp::kStore, |
240 GrColor_ILLEGAL }; | 244 GrColor_ILLEGAL }; |
241 commandBuffer.reset(fGpu->createCommandBuffer(currentRT, | 245 commandBuffer.reset(fGpu->createCommandBuffer(currentRT, |
242 kBasicLoadStoreInf
o, // Color | 246 kBasicLoadStoreInf
o, // Color |
243 kBasicLoadStoreInf
o)); // Stencil | 247 kBasicLoadStoreInf
o)); // Stencil |
244 } | 248 } |
245 flushState->setCommandBuffer(commandBuffer); | 249 flushState->setCommandBuffer(commandBuffer); |
246 } | 250 } |
247 if (commandBuffer) { | 251 if (commandBuffer) { |
248 bounds.join(fBatches[i]->bounds()); | 252 bounds.join(fRecordedBatches[i].fClippedBounds); |
249 } | 253 } |
250 if (fDrawBatchBounds) { | 254 if (fDrawBatchBounds) { |
251 const SkRect& batchBounds = fBatches[i]->bounds(); | 255 const SkRect& bounds = fRecordedBatches[i].fClippedBounds; |
252 SkIRect iBatchBounds; | 256 SkIRect ibounds; |
253 batchBounds.roundOut(&iBatchBounds); | 257 bounds.roundOut(&ibounds); |
254 // In multi-draw buffer all the batches use the same render target a
nd we won't need to | 258 // In multi-draw buffer all the batches use the same render target a
nd we won't need to |
255 // get the batchs bounds. | 259 // get the batchs bounds. |
256 if (GrRenderTarget* rt = fBatches[i]->renderTarget()) { | 260 if (GrRenderTarget* rt = fRecordedBatches[i].fBatch->renderTarget())
{ |
257 fGpu->drawDebugWireRect(rt, iBatchBounds, 0xFF000000 | random.ne
xtU()); | 261 fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU()
); |
258 } | 262 } |
259 } | 263 } |
260 fBatches[i]->draw(flushState); | 264 fRecordedBatches[i].fBatch->draw(flushState); |
261 } | 265 } |
262 if (commandBuffer) { | 266 if (commandBuffer) { |
263 commandBuffer->end(); | 267 commandBuffer->end(); |
264 if (bounds.intersect(0, 0, | 268 if (bounds.intersect(0, 0, |
265 SkIntToScalar(currentRT->width()), | 269 SkIntToScalar(currentRT->width()), |
266 SkIntToScalar(currentRT->height()))) { | 270 SkIntToScalar(currentRT->height()))) { |
267 SkIRect iBounds; | 271 SkIRect iBounds; |
268 bounds.roundOut(&iBounds); | 272 bounds.roundOut(&iBounds); |
269 commandBuffer->submit(iBounds); | 273 commandBuffer->submit(iBounds); |
270 } | 274 } |
271 flushState->setCommandBuffer(nullptr); | 275 flushState->setCommandBuffer(nullptr); |
272 } | 276 } |
273 | 277 |
274 fGpu->finishDrawTarget(); | 278 fGpu->finishDrawTarget(); |
275 } | 279 } |
276 | 280 |
277 void GrDrawTarget::reset() { | 281 void GrDrawTarget::reset() { |
278 fBatches.reset(); | 282 fRecordedBatches.reset(); |
279 if (fInstancedRendering) { | 283 if (fInstancedRendering) { |
280 fInstancedRendering->endFlush(); | 284 fInstancedRendering->endFlush(); |
281 } | 285 } |
282 } | 286 } |
283 | 287 |
284 static void batch_bounds(SkRect* bounds, const GrBatch* batch) { | 288 static void batch_bounds(SkRect* bounds, const GrBatch* batch) { |
285 *bounds = batch->bounds(); | 289 *bounds = batch->bounds(); |
286 if (batch->hasZeroArea()) { | 290 if (batch->hasZeroArea()) { |
287 if (batch->hasAABloat()) { | 291 if (batch->hasAABloat()) { |
288 bounds->outset(0.5f, 0.5f); | 292 bounds->outset(0.5f, 0.5f); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 } | 381 } |
378 | 382 |
379 if (!batch->installPipeline(args)) { | 383 if (!batch->installPipeline(args)) { |
380 return; | 384 return; |
381 } | 385 } |
382 | 386 |
383 #ifdef ENABLE_MDB | 387 #ifdef ENABLE_MDB |
384 SkASSERT(fRenderTarget); | 388 SkASSERT(fRenderTarget); |
385 batch->pipeline()->addDependenciesTo(fRenderTarget); | 389 batch->pipeline()->addDependenciesTo(fRenderTarget); |
386 #endif | 390 #endif |
387 | 391 SkRect clippedBounds; |
388 this->recordBatch(batch); | 392 SkAssertResult(clippedBounds.intersect(bounds, appliedClip.deviceBounds())); |
| 393 this->recordBatch(batch, clippedBounds); |
389 } | 394 } |
390 | 395 |
391 void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder, | 396 void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder, |
392 GrDrawContext* drawContext, | 397 GrDrawContext* drawContext, |
393 const GrClip& clip, | 398 const GrClip& clip, |
394 const SkMatrix& viewMatrix, | 399 const SkMatrix& viewMatrix, |
395 const GrPath* path, | 400 const GrPath* path, |
396 GrPathRendering::FillType fill) { | 401 GrPathRendering::FillType fill) { |
397 // TODO: extract portions of checkDraw that are relevant to path stenciling. | 402 // TODO: extract portions of checkDraw that are relevant to path stenciling. |
398 SkASSERT(path); | 403 SkASSERT(path); |
(...skipping 18 matching lines...) Expand all Loading... |
417 } | 422 } |
418 | 423 |
419 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, | 424 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, |
420 pipelineBuilder.isHWAntialias(), | 425 pipelineBuilder.isHWAntialias(), |
421 fill, | 426 fill, |
422 appliedClip.hasStencilClip(), | 427 appliedClip.hasStencilClip(), |
423 stencilAttachment->bits(), | 428 stencilAttachment->bits(), |
424 appliedClip.scissorState(), | 429 appliedClip.scissorState(), |
425 drawContext->accessRenderTarget(
), | 430 drawContext->accessRenderTarget(
), |
426 path); | 431 path); |
427 this->recordBatch(batch); | 432 this->recordBatch(batch, appliedClip.deviceBounds()); |
428 batch->unref(); | 433 batch->unref(); |
429 } | 434 } |
430 | 435 |
431 void GrDrawTarget::clear(const SkIRect* rect, | 436 void GrDrawTarget::clear(const SkIRect* rect, |
432 GrColor color, | 437 GrColor color, |
433 bool canIgnoreRect, | 438 bool canIgnoreRect, |
434 GrDrawContext* drawContext) { | 439 GrDrawContext* drawContext) { |
435 SkIRect rtRect = SkIRect::MakeWH(drawContext->width(), drawContext->height()
); | 440 SkIRect rtRect = SkIRect::MakeWH(drawContext->width(), drawContext->height()
); |
436 SkIRect clippedRect; | 441 SkIRect clippedRect; |
437 if (!rect || | 442 if (!rect || |
(...skipping 20 matching lines...) Expand all Loading... |
458 GrPipelineBuilder pipelineBuilder; | 463 GrPipelineBuilder pipelineBuilder; |
459 pipelineBuilder.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSr
c_Mode)); | 464 pipelineBuilder.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSr
c_Mode)); |
460 | 465 |
461 SkRect scalarRect = SkRect::Make(*rect); | 466 SkRect scalarRect = SkRect::Make(*rect); |
462 SkAutoTUnref<GrDrawBatch> batch( | 467 SkAutoTUnref<GrDrawBatch> batch( |
463 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalar
Rect, | 468 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalar
Rect, |
464 nullptr, nullptr)); | 469 nullptr, nullptr)); |
465 this->drawBatch(pipelineBuilder, drawContext, GrNoClip(), batch); | 470 this->drawBatch(pipelineBuilder, drawContext, GrNoClip(), batch); |
466 } else { | 471 } else { |
467 GrBatch* batch = new GrClearBatch(*rect, color, drawContext->accessRende
rTarget()); | 472 GrBatch* batch = new GrClearBatch(*rect, color, drawContext->accessRende
rTarget()); |
468 this->recordBatch(batch); | 473 this->recordBatch(batch, batch->bounds()); |
469 batch->unref(); | 474 batch->unref(); |
470 } | 475 } |
471 } | 476 } |
472 | 477 |
473 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { | 478 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { |
474 if (this->caps()->discardRenderTargetSupport()) { | 479 if (this->caps()->discardRenderTargetSupport()) { |
475 GrBatch* batch = new GrDiscardBatch(renderTarget); | 480 GrBatch* batch = new GrDiscardBatch(renderTarget); |
476 this->recordBatch(batch); | 481 this->recordBatch(batch, batch->bounds()); |
477 batch->unref(); | 482 batch->unref(); |
478 } | 483 } |
479 } | 484 } |
480 | 485 |
481 //////////////////////////////////////////////////////////////////////////////// | 486 //////////////////////////////////////////////////////////////////////////////// |
482 | 487 |
483 bool GrDrawTarget::copySurface(GrSurface* dst, | 488 bool GrDrawTarget::copySurface(GrSurface* dst, |
484 GrSurface* src, | 489 GrSurface* src, |
485 const SkIRect& srcRect, | 490 const SkIRect& srcRect, |
486 const SkIPoint& dstPoint) { | 491 const SkIPoint& dstPoint) { |
487 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); | 492 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); |
488 if (!batch) { | 493 if (!batch) { |
489 return false; | 494 return false; |
490 } | 495 } |
491 #ifdef ENABLE_MDB | 496 #ifdef ENABLE_MDB |
492 this->addDependency(src); | 497 this->addDependency(src); |
493 #endif | 498 #endif |
494 | 499 |
495 this->recordBatch(batch); | 500 this->recordBatch(batch, batch->bounds()); |
496 batch->unref(); | 501 batch->unref(); |
497 return true; | 502 return true; |
498 } | 503 } |
499 | 504 |
500 static inline bool exclusive_no_intersection(const SkRect& a, const SkRect& b) { | 505 static inline bool can_reorder(const SkRect& a, const SkRect& b) { |
501 return a.fRight <= b.fLeft || a.fBottom <= b.fTop || | 506 return a.fRight <= b.fLeft || a.fBottom <= b.fTop || |
502 b.fRight <= a.fLeft || b.fBottom <= a.fTop; | 507 b.fRight <= a.fLeft || b.fBottom <= a.fTop; |
503 } | 508 } |
504 | 509 |
505 static inline bool can_reorder(const GrBatch* a, const GrBatch* b) { | 510 void GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds) { |
506 SkRect ra; | |
507 SkRect rb; | |
508 batch_bounds(&ra, a); | |
509 batch_bounds(&rb, a); | |
510 return exclusive_no_intersection(ra, rb); | |
511 } | |
512 | |
513 void GrDrawTarget::recordBatch(GrBatch* batch) { | |
514 // A closed drawTarget should never receive new/more batches | 511 // A closed drawTarget should never receive new/more batches |
515 SkASSERT(!this->isClosed()); | 512 SkASSERT(!this->isClosed()); |
516 | 513 |
517 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either | 514 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either |
518 // 1) check every draw | 515 // 1) check every draw |
519 // 2) intersect with something | 516 // 2) intersect with something |
520 // 3) find a 'blocker' | 517 // 3) find a 'blocker' |
521 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); | 518 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); |
522 GrBATCH_INFO("Re-Recording (%s, B%u)\n" | 519 GrBATCH_INFO("Re-Recording (%s, B%u)\n" |
523 "\tBounds LRTB (%f, %f, %f, %f)\n", | 520 "\tBounds LRTB (%f, %f, %f, %f)\n", |
524 batch->name(), | 521 batch->name(), |
525 batch->uniqueID(), | 522 batch->uniqueID(), |
526 batch->bounds().fLeft, batch->bounds().fRight, | 523 batch->bounds().fLeft, batch->bounds().fRight, |
527 batch->bounds().fTop, batch->bounds().fBottom); | 524 batch->bounds().fTop, batch->bounds().fBottom); |
528 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); | 525 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); |
| 526 GrBATCH_INFO("\tClipped Bounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", |
| 527 clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight, |
| 528 clippedBounds.fBottom); |
529 GrBATCH_INFO("\tOutcome:\n"); | 529 GrBATCH_INFO("\tOutcome:\n"); |
530 int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count()); | 530 int maxCandidates = SkTMin(fMaxBatchLookback, fRecordedBatches.count()); |
531 if (maxCandidates) { | 531 if (maxCandidates) { |
532 int i = 0; | 532 int i = 0; |
533 while (true) { | 533 while (true) { |
534 GrBatch* candidate = fBatches.fromBack(i); | 534 GrBatch* candidate = fRecordedBatches.fromBack(i).fBatch.get(); |
535 // We cannot continue to search backwards if the render target chang
es | 535 // We cannot continue to search backwards if the render target chang
es |
536 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { | 536 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { |
537 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", | 537 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
538 candidate->name(), candidate->uniqueID()); | 538 candidate->name(), candidate->uniqueID()); |
539 break; | 539 break; |
540 } | 540 } |
541 if (candidate->combineIfPossible(batch, *this->caps())) { | 541 if (candidate->combineIfPossible(batch, *this->caps())) { |
542 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, | 542 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
543 candidate->uniqueID()); | 543 candidate->uniqueID()); |
544 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); | 544 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); |
| 545 fRecordedBatches.fromBack(i).fClippedBounds.joinNonEmptyArg(clip
pedBounds); |
545 return; | 546 return; |
546 } | 547 } |
547 // Stop going backwards if we would cause a painter's order violatio
n. | 548 // Stop going backwards if we would cause a painter's order violatio
n. |
548 // TODO: The bounds used here do not fully consider the clip. It may
be advantageous | 549 const SkRect& candidateBounds = fRecordedBatches.fromBack(i).fClippe
dBounds; |
549 // to clip each batch's bounds to the clip. | 550 if (!can_reorder(candidateBounds, clippedBounds)) { |
550 if (!can_reorder(candidate, batch)) { | |
551 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), | 551 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
552 candidate->uniqueID()); | 552 candidate->uniqueID()); |
553 break; | 553 break; |
554 } | 554 } |
555 ++i; | 555 ++i; |
556 if (i == maxCandidates) { | 556 if (i == maxCandidates) { |
557 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); | 557 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); |
558 break; | 558 break; |
559 } | 559 } |
560 } | 560 } |
561 } else { | 561 } else { |
562 GrBATCH_INFO("\t\tFirstBatch\n"); | 562 GrBATCH_INFO("\t\tFirstBatch\n"); |
563 } | 563 } |
564 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); | 564 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); |
565 fBatches.push_back().reset(SkRef(batch)); | 565 fRecordedBatches.emplace_back(RecordedBatch{sk_ref_sp(batch), clippedBounds}
); |
566 } | 566 } |
567 | 567 |
568 void GrDrawTarget::forwardCombine() { | 568 void GrDrawTarget::forwardCombine() { |
569 for (int i = 0; i < fBatches.count() - 2; ++i) { | 569 for (int i = 0; i < fRecordedBatches.count() - 2; ++i) { |
570 GrBatch* batch = fBatches[i]; | 570 GrBatch* batch = fRecordedBatches[i].fBatch.get(); |
571 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fBatches.count() -
1); | 571 const SkRect& batchBounds = fRecordedBatches[i].fClippedBounds; |
| 572 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fRecordedBatches.co
unt() - 1); |
572 int j = i + 1; | 573 int j = i + 1; |
573 while (true) { | 574 while (true) { |
574 GrBatch* candidate = fBatches[j]; | 575 GrBatch* candidate = fRecordedBatches[j].fBatch.get(); |
575 // We cannot continue to search if the render target changes | 576 // We cannot continue to search if the render target changes |
576 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { | 577 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { |
577 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", | 578 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
578 candidate->name(), candidate->uniqueID()); | 579 candidate->name(), candidate->uniqueID()); |
579 break; | 580 break; |
580 } | 581 } |
581 if (j == i +1) { | 582 if (j == i +1) { |
582 // We assume batch would have combined with candidate when the c
andidate was added | 583 // We assume batch would have combined with candidate when the c
andidate was added |
583 // via backwards combining in recordBatch. | 584 // via backwards combining in recordBatch. |
584 SkASSERT(!batch->combineIfPossible(candidate, *this->caps())); | 585 SkASSERT(!batch->combineIfPossible(candidate, *this->caps())); |
585 } else if (batch->combineIfPossible(candidate, *this->caps())) { | 586 } else if (batch->combineIfPossible(candidate, *this->caps())) { |
586 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, | 587 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
587 candidate->uniqueID()); | 588 candidate->uniqueID()); |
588 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, cand
idate); | 589 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, cand
idate); |
589 fBatches[j].reset(SkRef(batch)); | 590 fRecordedBatches[j].fBatch = std::move(fRecordedBatches[i].fBatc
h); |
590 fBatches[i].reset(nullptr); | 591 fRecordedBatches[j].fClippedBounds.join(batchBounds); |
591 break; | 592 break; |
592 } | 593 } |
593 // Stop going traversing if we would cause a painter's order violati
on. | 594 // Stop going traversing if we would cause a painter's order violati
on. |
594 // TODO: The bounds used here do not fully consider the clip. It may
be advantageous | 595 const SkRect& candidateBounds = fRecordedBatches[j].fClippedBounds; |
595 // to clip each batch's bounds to the clip. | 596 if (!can_reorder(candidateBounds, batchBounds)) { |
596 if (!can_reorder(candidate, batch)) { | |
597 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), | 597 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
598 candidate->uniqueID()); | 598 candidate->uniqueID()); |
599 break; | 599 break; |
600 } | 600 } |
601 ++j; | 601 ++j; |
602 if (j > maxCandidateIdx) { | 602 if (j > maxCandidateIdx) { |
603 GrBATCH_INFO("\t\tReached max lookahead or end of batch array %d
\n", i); | 603 GrBATCH_INFO("\t\tReached max lookahead or end of batch array %d
\n", i); |
604 break; | 604 break; |
605 } | 605 } |
606 } | 606 } |
607 } | 607 } |
608 } | 608 } |
609 | 609 |
610 /////////////////////////////////////////////////////////////////////////////// | 610 /////////////////////////////////////////////////////////////////////////////// |
611 | 611 |
612 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { | 612 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { |
613 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); | 613 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); |
614 this->recordBatch(batch); | 614 this->recordBatch(batch, batch->bounds()); |
615 batch->unref(); | 615 batch->unref(); |
616 } | 616 } |
OLD | NEW |