| 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 |