| Index: src/gpu/GrDrawTarget.cpp
|
| diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
|
| index 356c480da8cda1c2d345dbcf17ede21a2623dcae..8beaade32c16b2d8ceb7f163963c2f38dea7b96f 100644
|
| --- a/src/gpu/GrDrawTarget.cpp
|
| +++ b/src/gpu/GrDrawTarget.cpp
|
| @@ -115,15 +115,19 @@ void GrDrawTarget::dump() const {
|
| SkDebugf("%d, ", fDependencies[i]->fDebugID);
|
| }
|
| SkDebugf("\n");
|
| - SkDebugf("batches (%d):\n", fBatches.count());
|
| - for (int i = 0; i < fBatches.count(); ++i) {
|
| + SkDebugf("batches (%d):\n", fRecordedBatches.count());
|
| + for (int i = 0; i < fRecordedBatches.count(); ++i) {
|
| SkDebugf("*******************************\n");
|
| - if (!fBatches[i]) {
|
| + if (!fRecordedBatches[i].fBatch) {
|
| SkDebugf("%d: <combined forward>\n", i);
|
| } else {
|
| - SkDebugf("%d: %s\n", i, fBatches[i]->name());
|
| - SkString str = fBatches[i]->dumpInfo();
|
| + SkDebugf("%d: %s\n", i, fRecordedBatches[i].fBatch->name());
|
| + SkString str = fRecordedBatches[i].fBatch->dumpInfo();
|
| SkDebugf("%s\n", str.c_str());
|
| + const SkRect& clippedBounds = fRecordedBatches[i].fClippedBounds;
|
| + SkDebugf("ClippedBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
|
| + clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight,
|
| + clippedBounds.fBottom);
|
| }
|
| }
|
| }
|
| @@ -199,9 +203,9 @@ void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
|
| this->makeClosed();
|
|
|
| // Loop over the batches that haven't yet generated their geometry
|
| - for (int i = 0; i < fBatches.count(); ++i) {
|
| - if (fBatches[i]) {
|
| - fBatches[i]->prepare(flushState);
|
| + for (int i = 0; i < fRecordedBatches.count(); ++i) {
|
| + if (fRecordedBatches[i].fBatch) {
|
| + fRecordedBatches[i].fBatch->prepare(flushState);
|
| }
|
| }
|
|
|
| @@ -216,11 +220,11 @@ void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
|
| GrRenderTarget* currentRT = nullptr;
|
| SkAutoTDelete<GrGpuCommandBuffer> commandBuffer;
|
| SkRect bounds = SkRect::MakeEmpty();
|
| - for (int i = 0; i < fBatches.count(); ++i) {
|
| - if (!fBatches[i]) {
|
| + for (int i = 0; i < fRecordedBatches.count(); ++i) {
|
| + if (!fRecordedBatches[i].fBatch) {
|
| continue;
|
| }
|
| - if (fBatches[i]->renderTarget() != currentRT) {
|
| + if (fRecordedBatches[i].fBatch->renderTarget() != currentRT) {
|
| if (commandBuffer) {
|
| commandBuffer->end();
|
| if (bounds.intersect(0, 0,
|
| @@ -233,7 +237,7 @@ void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
|
| commandBuffer.reset();
|
| }
|
| bounds.setEmpty();
|
| - currentRT = fBatches[i]->renderTarget();
|
| + currentRT = fRecordedBatches[i].fBatch->renderTarget();
|
| if (currentRT) {
|
| static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo
|
| { GrGpuCommandBuffer::LoadOp::kLoad,GrGpuCommandBuffer::StoreOp::kStore,
|
| @@ -245,19 +249,19 @@ void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
|
| flushState->setCommandBuffer(commandBuffer);
|
| }
|
| if (commandBuffer) {
|
| - bounds.join(fBatches[i]->bounds());
|
| + bounds.join(fRecordedBatches[i].fClippedBounds);
|
| }
|
| if (fDrawBatchBounds) {
|
| - const SkRect& batchBounds = fBatches[i]->bounds();
|
| - SkIRect iBatchBounds;
|
| - batchBounds.roundOut(&iBatchBounds);
|
| + const SkRect& bounds = fRecordedBatches[i].fClippedBounds;
|
| + SkIRect ibounds;
|
| + bounds.roundOut(&ibounds);
|
| // In multi-draw buffer all the batches use the same render target and we won't need to
|
| // get the batchs bounds.
|
| - if (GrRenderTarget* rt = fBatches[i]->renderTarget()) {
|
| - fGpu->drawDebugWireRect(rt, iBatchBounds, 0xFF000000 | random.nextU());
|
| + if (GrRenderTarget* rt = fRecordedBatches[i].fBatch->renderTarget()) {
|
| + fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU());
|
| }
|
| }
|
| - fBatches[i]->draw(flushState);
|
| + fRecordedBatches[i].fBatch->draw(flushState);
|
| }
|
| if (commandBuffer) {
|
| commandBuffer->end();
|
| @@ -275,7 +279,7 @@ void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
|
| }
|
|
|
| void GrDrawTarget::reset() {
|
| - fBatches.reset();
|
| + fRecordedBatches.reset();
|
| if (fInstancedRendering) {
|
| fInstancedRendering->endFlush();
|
| }
|
| @@ -307,6 +311,16 @@ static void batch_bounds(SkRect* bounds, const GrBatch* batch) {
|
| }
|
| }
|
|
|
| +static inline bool intersect(SkRect* out, const SkRect& a, const SkRect& b) {
|
| + SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom);
|
| + SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom);
|
| + out->fLeft = SkTMax(a.fLeft, b.fLeft);
|
| + out->fTop = SkTMax(a.fTop, b.fTop);
|
| + out->fRight = SkTMin(a.fRight, b.fRight);
|
| + out->fBottom = SkTMin(a.fBottom, b.fBottom);
|
| + return (out->fLeft <= out->fRight && out->fTop <= out->fBottom);
|
| +}
|
| +
|
| void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
|
| GrDrawContext* drawContext,
|
| const GrClip& clip,
|
| @@ -384,8 +398,9 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
|
| SkASSERT(fRenderTarget);
|
| batch->pipeline()->addDependenciesTo(fRenderTarget);
|
| #endif
|
| -
|
| - this->recordBatch(batch);
|
| + SkRect clippedBounds;
|
| + SkAssertResult(intersect(&clippedBounds, bounds, appliedClip.deviceBounds()));
|
| + this->recordBatch(batch, clippedBounds);
|
| }
|
|
|
| void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
|
| @@ -424,7 +439,7 @@ void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
|
| appliedClip.scissorState(),
|
| drawContext->accessRenderTarget(),
|
| path);
|
| - this->recordBatch(batch);
|
| + this->recordBatch(batch, appliedClip.deviceBounds());
|
| batch->unref();
|
| }
|
|
|
| @@ -465,7 +480,7 @@ void GrDrawTarget::clear(const SkIRect* rect,
|
| this->drawBatch(pipelineBuilder, drawContext, GrNoClip(), batch);
|
| } else {
|
| GrBatch* batch = new GrClearBatch(*rect, color, drawContext->accessRenderTarget());
|
| - this->recordBatch(batch);
|
| + this->recordBatch(batch, batch->bounds());
|
| batch->unref();
|
| }
|
| }
|
| @@ -473,7 +488,7 @@ void GrDrawTarget::clear(const SkIRect* rect,
|
| void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
|
| if (this->caps()->discardRenderTargetSupport()) {
|
| GrBatch* batch = new GrDiscardBatch(renderTarget);
|
| - this->recordBatch(batch);
|
| + this->recordBatch(batch, batch->bounds());
|
| batch->unref();
|
| }
|
| }
|
| @@ -492,25 +507,26 @@ bool GrDrawTarget::copySurface(GrSurface* dst,
|
| this->addDependency(src);
|
| #endif
|
|
|
| - this->recordBatch(batch);
|
| + this->recordBatch(batch, batch->bounds());
|
| batch->unref();
|
| return true;
|
| }
|
|
|
| -static inline bool exclusive_no_intersection(const SkRect& a, const SkRect& b) {
|
| +static inline bool can_reorder(const SkRect& a, const SkRect& b) {
|
| return a.fRight <= b.fLeft || a.fBottom <= b.fTop ||
|
| b.fRight <= a.fLeft || b.fBottom <= a.fTop;
|
| }
|
|
|
| -static inline bool can_reorder(const GrBatch* a, const GrBatch* b) {
|
| - SkRect ra;
|
| - SkRect rb;
|
| - batch_bounds(&ra, a);
|
| - batch_bounds(&rb, a);
|
| - return exclusive_no_intersection(ra, rb);
|
| +static void join(SkRect* out, const SkRect& a, const SkRect& b) {
|
| + SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom);
|
| + SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom);
|
| + out->fLeft = SkTMin(a.fLeft, b.fLeft);
|
| + out->fTop = SkTMin(a.fTop, b.fTop);
|
| + out->fRight = SkTMax(a.fRight, b.fRight);
|
| + out->fBottom = SkTMax(a.fBottom, b.fBottom);
|
| }
|
|
|
| -void GrDrawTarget::recordBatch(GrBatch* batch) {
|
| +void GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds) {
|
| // A closed drawTarget should never receive new/more batches
|
| SkASSERT(!this->isClosed());
|
|
|
| @@ -526,12 +542,15 @@ void GrDrawTarget::recordBatch(GrBatch* batch) {
|
| batch->bounds().fLeft, batch->bounds().fRight,
|
| batch->bounds().fTop, batch->bounds().fBottom);
|
| GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
|
| + GrBATCH_INFO("\tClipped Bounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
|
| + clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight,
|
| + clippedBounds.fBottom);
|
| GrBATCH_INFO("\tOutcome:\n");
|
| - int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count());
|
| + int maxCandidates = SkTMin(fMaxBatchLookback, fRecordedBatches.count());
|
| if (maxCandidates) {
|
| int i = 0;
|
| while (true) {
|
| - GrBatch* candidate = fBatches.fromBack(i);
|
| + GrBatch* candidate = fRecordedBatches.fromBack(i).fBatch.get();
|
| // We cannot continue to search backwards if the render target changes
|
| if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
|
| GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
|
| @@ -542,12 +561,13 @@ void GrDrawTarget::recordBatch(GrBatch* batch) {
|
| GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
|
| candidate->uniqueID());
|
| GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate, batch);
|
| + join(&fRecordedBatches.fromBack(i).fClippedBounds,
|
| + fRecordedBatches.fromBack(i).fClippedBounds, clippedBounds);
|
| return;
|
| }
|
| // Stop going backwards if we would cause a painter's order violation.
|
| - // TODO: The bounds used here do not fully consider the clip. It may be advantageous
|
| - // to clip each batch's bounds to the clip.
|
| - if (!can_reorder(candidate, batch)) {
|
| + const SkRect& candidateBounds = fRecordedBatches.fromBack(i).fClippedBounds;
|
| + if (!can_reorder(candidateBounds, clippedBounds)) {
|
| GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
|
| candidate->uniqueID());
|
| break;
|
| @@ -562,16 +582,17 @@ void GrDrawTarget::recordBatch(GrBatch* batch) {
|
| GrBATCH_INFO("\t\tFirstBatch\n");
|
| }
|
| GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch);
|
| - fBatches.push_back().reset(SkRef(batch));
|
| + fRecordedBatches.emplace_back(RecordedBatch{sk_ref_sp(batch), clippedBounds});
|
| }
|
|
|
| void GrDrawTarget::forwardCombine() {
|
| - for (int i = 0; i < fBatches.count() - 2; ++i) {
|
| - GrBatch* batch = fBatches[i];
|
| - int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fBatches.count() - 1);
|
| + for (int i = 0; i < fRecordedBatches.count() - 2; ++i) {
|
| + GrBatch* batch = fRecordedBatches[i].fBatch.get();
|
| + const SkRect& batchBounds = fRecordedBatches[i].fClippedBounds;
|
| + int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fRecordedBatches.count() - 1);
|
| int j = i + 1;
|
| while (true) {
|
| - GrBatch* candidate = fBatches[j];
|
| + GrBatch* candidate = fRecordedBatches[j].fBatch.get();
|
| // We cannot continue to search if the render target changes
|
| if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
|
| GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
|
| @@ -586,14 +607,14 @@ void GrDrawTarget::forwardCombine() {
|
| GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
|
| candidate->uniqueID());
|
| GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, candidate);
|
| - fBatches[j].reset(SkRef(batch));
|
| - fBatches[i].reset(nullptr);
|
| + fRecordedBatches[j].fBatch = std::move(fRecordedBatches[i].fBatch);
|
| + join(&fRecordedBatches[j].fClippedBounds, fRecordedBatches[j].fClippedBounds,
|
| + batchBounds);
|
| break;
|
| }
|
| // Stop going traversing if we would cause a painter's order violation.
|
| - // TODO: The bounds used here do not fully consider the clip. It may be advantageous
|
| - // to clip each batch's bounds to the clip.
|
| - if (!can_reorder(candidate, batch)) {
|
| + const SkRect& candidateBounds = fRecordedBatches[j].fClippedBounds;
|
| + if (!can_reorder(candidateBounds, batchBounds)) {
|
| GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
|
| candidate->uniqueID());
|
| break;
|
| @@ -611,6 +632,6 @@ void GrDrawTarget::forwardCombine() {
|
|
|
| void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
|
| GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
|
| - this->recordBatch(batch);
|
| + this->recordBatch(batch, batch->bounds());
|
| batch->unref();
|
| }
|
|
|