| 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 27 matching lines...) Expand all Loading... |
| 38 #include "instanced/InstancedRendering.h" | 38 #include "instanced/InstancedRendering.h" |
| 39 | 39 |
| 40 //////////////////////////////////////////////////////////////////////////////// | 40 //////////////////////////////////////////////////////////////////////////////// |
| 41 | 41 |
| 42 // Experimentally we have found that most batching occurs within the first 10 co
mparisons. | 42 // Experimentally we have found that most batching occurs within the first 10 co
mparisons. |
| 43 static const int kDefaultMaxBatchLookback = 10; | 43 static const int kDefaultMaxBatchLookback = 10; |
| 44 static const int kDefaultMaxBatchLookahead = 10; | 44 static const int kDefaultMaxBatchLookahead = 10; |
| 45 | 45 |
| 46 GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* r
esourceProvider, | 46 GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* r
esourceProvider, |
| 47 GrAuditTrail* auditTrail, const Options& options) | 47 GrAuditTrail* auditTrail, const Options& options) |
| 48 : fGpu(SkRef(gpu)) | 48 : fLastFullClearBatch(nullptr) |
| 49 , fGpu(SkRef(gpu)) |
| 49 , fResourceProvider(resourceProvider) | 50 , fResourceProvider(resourceProvider) |
| 50 , fAuditTrail(auditTrail) | 51 , fAuditTrail(auditTrail) |
| 51 , fFlags(0) | 52 , fFlags(0) |
| 52 , fRenderTarget(rt) { | 53 , fRenderTarget(rt) { |
| 53 // TODO: Stop extracting the context (currently needed by GrClip) | 54 // TODO: Stop extracting the context (currently needed by GrClip) |
| 54 fContext = fGpu->getContext(); | 55 fContext = fGpu->getContext(); |
| 55 | 56 |
| 56 fClipBatchToBounds = options.fClipBatchToBounds; | 57 fClipBatchToBounds = options.fClipBatchToBounds; |
| 57 fDrawBatchBounds = options.fDrawBatchBounds; | 58 fDrawBatchBounds = options.fDrawBatchBounds; |
| 58 fMaxBatchLookback = (options.fMaxBatchLookback < 0) ? kDefaultMaxBatchLookba
ck : | 59 fMaxBatchLookback = (options.fMaxBatchLookback < 0) ? kDefaultMaxBatchLookba
ck : |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 bounds.roundOut(&iBounds); | 281 bounds.roundOut(&iBounds); |
| 281 commandBuffer->submit(iBounds); | 282 commandBuffer->submit(iBounds); |
| 282 } | 283 } |
| 283 flushState->setCommandBuffer(nullptr); | 284 flushState->setCommandBuffer(nullptr); |
| 284 } | 285 } |
| 285 | 286 |
| 286 fGpu->finishDrawTarget(); | 287 fGpu->finishDrawTarget(); |
| 287 } | 288 } |
| 288 | 289 |
| 289 void GrDrawTarget::reset() { | 290 void GrDrawTarget::reset() { |
| 291 fLastFullClearBatch = nullptr; |
| 290 fRecordedBatches.reset(); | 292 fRecordedBatches.reset(); |
| 291 if (fInstancedRendering) { | 293 if (fInstancedRendering) { |
| 292 fInstancedRendering->endFlush(); | 294 fInstancedRendering->endFlush(); |
| 293 } | 295 } |
| 294 } | 296 } |
| 295 | 297 |
| 296 static void batch_bounds(SkRect* bounds, const GrBatch* batch) { | 298 static void batch_bounds(SkRect* bounds, const GrBatch* batch) { |
| 297 *bounds = batch->bounds(); | 299 *bounds = batch->bounds(); |
| 298 if (batch->hasZeroArea()) { | 300 if (batch->hasZeroArea()) { |
| 299 if (batch->hasAABloat()) { | 301 if (batch->hasAABloat()) { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 path); | 453 path); |
| 452 this->recordBatch(batch, appliedClip.deviceBounds()); | 454 this->recordBatch(batch, appliedClip.deviceBounds()); |
| 453 batch->unref(); | 455 batch->unref(); |
| 454 } | 456 } |
| 455 | 457 |
| 456 void GrDrawTarget::addBatch(sk_sp<GrBatch> batch) { | 458 void GrDrawTarget::addBatch(sk_sp<GrBatch> batch) { |
| 457 this->recordBatch(batch.get(), batch->bounds()); | 459 this->recordBatch(batch.get(), batch->bounds()); |
| 458 } | 460 } |
| 459 | 461 |
| 460 void GrDrawTarget::fullClear(GrRenderTarget* renderTarget, GrColor color) { | 462 void GrDrawTarget::fullClear(GrRenderTarget* renderTarget, GrColor color) { |
| 461 // Currently this just inserts a clear batch. However, once in MDB this can
remove all the | 463 // Currently this just inserts or updates the last clear batch. However, onc
e in MDB this can |
| 462 // previously recorded batches and change the load op to clear with supplied
color. | 464 // remove all the previously recorded batches and change the load op to clea
r with supplied |
| 463 sk_sp<GrBatch> batch = GrClearBatch::Make(SkIRect::MakeWH(renderTarget->widt
h(), | 465 // color. |
| 464 renderTarget->heig
ht()), | 466 if (fLastFullClearBatch && |
| 465 color, renderTarget); | 467 fLastFullClearBatch->renderTargetUniqueID() == renderTarget->getUniqueID
()) { |
| 466 this->recordBatch(batch.get(), batch->bounds()); | 468 // As currently implemented, fLastFullClearBatch should be the last batc
h because we would |
| 469 // have cleared it when another batch was recorded. |
| 470 SkASSERT(fRecordedBatches.back().fBatch.get() == fLastFullClearBatch); |
| 471 fLastFullClearBatch->setColor(color); |
| 472 return; |
| 473 } |
| 474 sk_sp<GrClearBatch> batch(GrClearBatch::Make(SkIRect::MakeWH(renderTarget->w
idth(), |
| 475 renderTarget->h
eight()), |
| 476 color, renderTarget)); |
| 477 if (batch.get() == this->recordBatch(batch.get(), batch->bounds())) { |
| 478 fLastFullClearBatch = batch.get(); |
| 479 } |
| 467 } | 480 } |
| 468 | 481 |
| 469 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { | 482 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { |
| 470 // Currently this just inserts a discard batch. However, once in MDB this ca
n remove all the | 483 // Currently this just inserts a discard batch. However, once in MDB this ca
n remove all the |
| 471 // previously recorded batches and change the load op to discard. | 484 // previously recorded batches and change the load op to discard. |
| 472 if (this->caps()->discardRenderTargetSupport()) { | 485 if (this->caps()->discardRenderTargetSupport()) { |
| 473 GrBatch* batch = new GrDiscardBatch(renderTarget); | 486 GrBatch* batch = new GrDiscardBatch(renderTarget); |
| 474 this->recordBatch(batch, batch->bounds()); | 487 this->recordBatch(batch, batch->bounds()); |
| 475 batch->unref(); | 488 batch->unref(); |
| 476 } | 489 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 502 | 515 |
| 503 static void join(SkRect* out, const SkRect& a, const SkRect& b) { | 516 static void join(SkRect* out, const SkRect& a, const SkRect& b) { |
| 504 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom); | 517 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom); |
| 505 SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom); | 518 SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom); |
| 506 out->fLeft = SkTMin(a.fLeft, b.fLeft); | 519 out->fLeft = SkTMin(a.fLeft, b.fLeft); |
| 507 out->fTop = SkTMin(a.fTop, b.fTop); | 520 out->fTop = SkTMin(a.fTop, b.fTop); |
| 508 out->fRight = SkTMax(a.fRight, b.fRight); | 521 out->fRight = SkTMax(a.fRight, b.fRight); |
| 509 out->fBottom = SkTMax(a.fBottom, b.fBottom); | 522 out->fBottom = SkTMax(a.fBottom, b.fBottom); |
| 510 } | 523 } |
| 511 | 524 |
| 512 void GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds) { | 525 GrBatch* GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds)
{ |
| 513 // A closed drawTarget should never receive new/more batches | 526 // A closed drawTarget should never receive new/more batches |
| 514 SkASSERT(!this->isClosed()); | 527 SkASSERT(!this->isClosed()); |
| 515 | 528 |
| 516 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either | 529 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either |
| 517 // 1) check every draw | 530 // 1) check every draw |
| 518 // 2) intersect with something | 531 // 2) intersect with something |
| 519 // 3) find a 'blocker' | 532 // 3) find a 'blocker' |
| 520 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); | 533 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); |
| 521 GrBATCH_INFO("Re-Recording (%s, B%u)\n" | 534 GrBATCH_INFO("Re-Recording (%s, B%u)\n" |
| 522 "\tBounds LRTB (%f, %f, %f, %f)\n", | 535 "\tBounds LRTB (%f, %f, %f, %f)\n", |
| (...skipping 16 matching lines...) Expand all Loading... |
| 539 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", | 552 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
| 540 candidate->name(), candidate->uniqueID()); | 553 candidate->name(), candidate->uniqueID()); |
| 541 break; | 554 break; |
| 542 } | 555 } |
| 543 if (candidate->combineIfPossible(batch, *this->caps())) { | 556 if (candidate->combineIfPossible(batch, *this->caps())) { |
| 544 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, | 557 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
| 545 candidate->uniqueID()); | 558 candidate->uniqueID()); |
| 546 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); | 559 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); |
| 547 join(&fRecordedBatches.fromBack(i).fClippedBounds, | 560 join(&fRecordedBatches.fromBack(i).fClippedBounds, |
| 548 fRecordedBatches.fromBack(i).fClippedBounds, clippedBounds)
; | 561 fRecordedBatches.fromBack(i).fClippedBounds, clippedBounds)
; |
| 549 return; | 562 return candidate; |
| 550 } | 563 } |
| 551 // Stop going backwards if we would cause a painter's order violatio
n. | 564 // Stop going backwards if we would cause a painter's order violatio
n. |
| 552 const SkRect& candidateBounds = fRecordedBatches.fromBack(i).fClippe
dBounds; | 565 const SkRect& candidateBounds = fRecordedBatches.fromBack(i).fClippe
dBounds; |
| 553 if (!can_reorder(candidateBounds, clippedBounds)) { | 566 if (!can_reorder(candidateBounds, clippedBounds)) { |
| 554 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), | 567 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
| 555 candidate->uniqueID()); | 568 candidate->uniqueID()); |
| 556 break; | 569 break; |
| 557 } | 570 } |
| 558 ++i; | 571 ++i; |
| 559 if (i == maxCandidates) { | 572 if (i == maxCandidates) { |
| 560 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); | 573 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); |
| 561 break; | 574 break; |
| 562 } | 575 } |
| 563 } | 576 } |
| 564 } else { | 577 } else { |
| 565 GrBATCH_INFO("\t\tFirstBatch\n"); | 578 GrBATCH_INFO("\t\tFirstBatch\n"); |
| 566 } | 579 } |
| 567 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); | 580 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); |
| 568 fRecordedBatches.emplace_back(RecordedBatch{sk_ref_sp(batch), clippedBounds}
); | 581 fRecordedBatches.emplace_back(RecordedBatch{sk_ref_sp(batch), clippedBounds}
); |
| 582 fLastFullClearBatch = nullptr; |
| 583 return batch; |
| 569 } | 584 } |
| 570 | 585 |
| 571 void GrDrawTarget::forwardCombine() { | 586 void GrDrawTarget::forwardCombine() { |
| 572 for (int i = 0; i < fRecordedBatches.count() - 2; ++i) { | 587 for (int i = 0; i < fRecordedBatches.count() - 2; ++i) { |
| 573 GrBatch* batch = fRecordedBatches[i].fBatch.get(); | 588 GrBatch* batch = fRecordedBatches[i].fBatch.get(); |
| 574 const SkRect& batchBounds = fRecordedBatches[i].fClippedBounds; | 589 const SkRect& batchBounds = fRecordedBatches[i].fClippedBounds; |
| 575 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fRecordedBatches.co
unt() - 1); | 590 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fRecordedBatches.co
unt() - 1); |
| 576 int j = i + 1; | 591 int j = i + 1; |
| 577 while (true) { | 592 while (true) { |
| 578 GrBatch* candidate = fRecordedBatches[j].fBatch.get(); | 593 GrBatch* candidate = fRecordedBatches[j].fBatch.get(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 } | 626 } |
| 612 } | 627 } |
| 613 | 628 |
| 614 /////////////////////////////////////////////////////////////////////////////// | 629 /////////////////////////////////////////////////////////////////////////////// |
| 615 | 630 |
| 616 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { | 631 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { |
| 617 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); | 632 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); |
| 618 this->recordBatch(batch, batch->bounds()); | 633 this->recordBatch(batch, batch->bounds()); |
| 619 batch->unref(); | 634 batch->unref(); |
| 620 } | 635 } |
| OLD | NEW |