| 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 11 matching lines...) Expand all Loading... |
| 300 if (bounds->fRight == before.fRight) { | 304 if (bounds->fRight == before.fRight) { |
| 301 bounds->fRight += 1; | 305 bounds->fRight += 1; |
| 302 } | 306 } |
| 303 if (bounds->fBottom == before.fBottom) { | 307 if (bounds->fBottom == before.fBottom) { |
| 304 bounds->fBottom += 1; | 308 bounds->fBottom += 1; |
| 305 } | 309 } |
| 306 } | 310 } |
| 307 } | 311 } |
| 308 } | 312 } |
| 309 | 313 |
| 314 static inline bool intersect(SkRect* out, const SkRect& a, const SkRect& b) { |
| 315 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom); |
| 316 SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom); |
| 317 out->fLeft = SkTMax(a.fLeft, b.fLeft); |
| 318 out->fTop = SkTMax(a.fTop, b.fTop); |
| 319 out->fRight = SkTMin(a.fRight, b.fRight); |
| 320 out->fBottom = SkTMin(a.fBottom, b.fBottom); |
| 321 return (out->fLeft <= out->fRight && out->fTop <= out->fBottom); |
| 322 } |
| 323 |
| 310 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, | 324 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, |
| 311 GrDrawContext* drawContext, | 325 GrDrawContext* drawContext, |
| 312 const GrClip& clip, | 326 const GrClip& clip, |
| 313 GrDrawBatch* batch) { | 327 GrDrawBatch* batch) { |
| 314 // Setup clip | 328 // Setup clip |
| 315 GrAppliedClip appliedClip; | 329 GrAppliedClip appliedClip; |
| 316 SkRect bounds; | 330 SkRect bounds; |
| 317 batch_bounds(&bounds, batch); | 331 batch_bounds(&bounds, batch); |
| 318 if (!clip.apply(fContext, pipelineBuilder, drawContext, &bounds, &appliedCli
p)) { | 332 if (!clip.apply(fContext, pipelineBuilder, drawContext, &bounds, &appliedCli
p)) { |
| 319 return; | 333 return; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 391 } |
| 378 | 392 |
| 379 if (!batch->installPipeline(args)) { | 393 if (!batch->installPipeline(args)) { |
| 380 return; | 394 return; |
| 381 } | 395 } |
| 382 | 396 |
| 383 #ifdef ENABLE_MDB | 397 #ifdef ENABLE_MDB |
| 384 SkASSERT(fRenderTarget); | 398 SkASSERT(fRenderTarget); |
| 385 batch->pipeline()->addDependenciesTo(fRenderTarget); | 399 batch->pipeline()->addDependenciesTo(fRenderTarget); |
| 386 #endif | 400 #endif |
| 387 | 401 SkRect clippedBounds; |
| 388 this->recordBatch(batch); | 402 SkAssertResult(intersect(&clippedBounds, bounds, appliedClip.deviceBounds())
); |
| 403 this->recordBatch(batch, clippedBounds); |
| 389 } | 404 } |
| 390 | 405 |
| 391 void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder, | 406 void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder, |
| 392 GrDrawContext* drawContext, | 407 GrDrawContext* drawContext, |
| 393 const GrClip& clip, | 408 const GrClip& clip, |
| 394 const SkMatrix& viewMatrix, | 409 const SkMatrix& viewMatrix, |
| 395 const GrPath* path, | 410 const GrPath* path, |
| 396 GrPathRendering::FillType fill) { | 411 GrPathRendering::FillType fill) { |
| 397 // TODO: extract portions of checkDraw that are relevant to path stenciling. | 412 // TODO: extract portions of checkDraw that are relevant to path stenciling. |
| 398 SkASSERT(path); | 413 SkASSERT(path); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 417 } | 432 } |
| 418 | 433 |
| 419 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, | 434 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, |
| 420 pipelineBuilder.isHWAntialias(), | 435 pipelineBuilder.isHWAntialias(), |
| 421 fill, | 436 fill, |
| 422 appliedClip.hasStencilClip(), | 437 appliedClip.hasStencilClip(), |
| 423 stencilAttachment->bits(), | 438 stencilAttachment->bits(), |
| 424 appliedClip.scissorState(), | 439 appliedClip.scissorState(), |
| 425 drawContext->accessRenderTarget(
), | 440 drawContext->accessRenderTarget(
), |
| 426 path); | 441 path); |
| 427 this->recordBatch(batch); | 442 this->recordBatch(batch, appliedClip.deviceBounds()); |
| 428 batch->unref(); | 443 batch->unref(); |
| 429 } | 444 } |
| 430 | 445 |
| 431 void GrDrawTarget::clear(const SkIRect* rect, | 446 void GrDrawTarget::clear(const SkIRect* rect, |
| 432 GrColor color, | 447 GrColor color, |
| 433 bool canIgnoreRect, | 448 bool canIgnoreRect, |
| 434 GrDrawContext* drawContext) { | 449 GrDrawContext* drawContext) { |
| 435 SkIRect rtRect = SkIRect::MakeWH(drawContext->width(), drawContext->height()
); | 450 SkIRect rtRect = SkIRect::MakeWH(drawContext->width(), drawContext->height()
); |
| 436 SkIRect clippedRect; | 451 SkIRect clippedRect; |
| 437 if (!rect || | 452 if (!rect || |
| (...skipping 20 matching lines...) Expand all Loading... |
| 458 GrPipelineBuilder pipelineBuilder; | 473 GrPipelineBuilder pipelineBuilder; |
| 459 pipelineBuilder.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSr
c_Mode)); | 474 pipelineBuilder.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSr
c_Mode)); |
| 460 | 475 |
| 461 SkRect scalarRect = SkRect::Make(*rect); | 476 SkRect scalarRect = SkRect::Make(*rect); |
| 462 SkAutoTUnref<GrDrawBatch> batch( | 477 SkAutoTUnref<GrDrawBatch> batch( |
| 463 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalar
Rect, | 478 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalar
Rect, |
| 464 nullptr, nullptr)); | 479 nullptr, nullptr)); |
| 465 this->drawBatch(pipelineBuilder, drawContext, GrNoClip(), batch); | 480 this->drawBatch(pipelineBuilder, drawContext, GrNoClip(), batch); |
| 466 } else { | 481 } else { |
| 467 GrBatch* batch = new GrClearBatch(*rect, color, drawContext->accessRende
rTarget()); | 482 GrBatch* batch = new GrClearBatch(*rect, color, drawContext->accessRende
rTarget()); |
| 468 this->recordBatch(batch); | 483 this->recordBatch(batch, batch->bounds()); |
| 469 batch->unref(); | 484 batch->unref(); |
| 470 } | 485 } |
| 471 } | 486 } |
| 472 | 487 |
| 473 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { | 488 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { |
| 474 if (this->caps()->discardRenderTargetSupport()) { | 489 if (this->caps()->discardRenderTargetSupport()) { |
| 475 GrBatch* batch = new GrDiscardBatch(renderTarget); | 490 GrBatch* batch = new GrDiscardBatch(renderTarget); |
| 476 this->recordBatch(batch); | 491 this->recordBatch(batch, batch->bounds()); |
| 477 batch->unref(); | 492 batch->unref(); |
| 478 } | 493 } |
| 479 } | 494 } |
| 480 | 495 |
| 481 //////////////////////////////////////////////////////////////////////////////// | 496 //////////////////////////////////////////////////////////////////////////////// |
| 482 | 497 |
| 483 bool GrDrawTarget::copySurface(GrSurface* dst, | 498 bool GrDrawTarget::copySurface(GrSurface* dst, |
| 484 GrSurface* src, | 499 GrSurface* src, |
| 485 const SkIRect& srcRect, | 500 const SkIRect& srcRect, |
| 486 const SkIPoint& dstPoint) { | 501 const SkIPoint& dstPoint) { |
| 487 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); | 502 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); |
| 488 if (!batch) { | 503 if (!batch) { |
| 489 return false; | 504 return false; |
| 490 } | 505 } |
| 491 #ifdef ENABLE_MDB | 506 #ifdef ENABLE_MDB |
| 492 this->addDependency(src); | 507 this->addDependency(src); |
| 493 #endif | 508 #endif |
| 494 | 509 |
| 495 this->recordBatch(batch); | 510 this->recordBatch(batch, batch->bounds()); |
| 496 batch->unref(); | 511 batch->unref(); |
| 497 return true; | 512 return true; |
| 498 } | 513 } |
| 499 | 514 |
| 500 static inline bool exclusive_no_intersection(const SkRect& a, const SkRect& b) { | 515 static inline bool can_reorder(const SkRect& a, const SkRect& b) { |
| 501 return a.fRight <= b.fLeft || a.fBottom <= b.fTop || | 516 return a.fRight <= b.fLeft || a.fBottom <= b.fTop || |
| 502 b.fRight <= a.fLeft || b.fBottom <= a.fTop; | 517 b.fRight <= a.fLeft || b.fBottom <= a.fTop; |
| 503 } | 518 } |
| 504 | 519 |
| 505 static inline bool can_reorder(const GrBatch* a, const GrBatch* b) { | 520 static void join(SkRect* out, const SkRect& a, const SkRect& b) { |
| 506 SkRect ra; | 521 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom); |
| 507 SkRect rb; | 522 SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom); |
| 508 batch_bounds(&ra, a); | 523 out->fLeft = SkTMin(a.fLeft, b.fLeft); |
| 509 batch_bounds(&rb, a); | 524 out->fTop = SkTMin(a.fTop, b.fTop); |
| 510 return exclusive_no_intersection(ra, rb); | 525 out->fRight = SkTMax(a.fRight, b.fRight); |
| 526 out->fBottom = SkTMax(a.fBottom, b.fBottom); |
| 511 } | 527 } |
| 512 | 528 |
| 513 void GrDrawTarget::recordBatch(GrBatch* batch) { | 529 void GrDrawTarget::recordBatch(GrBatch* batch, const SkRect& clippedBounds) { |
| 514 // A closed drawTarget should never receive new/more batches | 530 // A closed drawTarget should never receive new/more batches |
| 515 SkASSERT(!this->isClosed()); | 531 SkASSERT(!this->isClosed()); |
| 516 | 532 |
| 517 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either | 533 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either |
| 518 // 1) check every draw | 534 // 1) check every draw |
| 519 // 2) intersect with something | 535 // 2) intersect with something |
| 520 // 3) find a 'blocker' | 536 // 3) find a 'blocker' |
| 521 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); | 537 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch); |
| 522 GrBATCH_INFO("Re-Recording (%s, B%u)\n" | 538 GrBATCH_INFO("Re-Recording (%s, B%u)\n" |
| 523 "\tBounds LRTB (%f, %f, %f, %f)\n", | 539 "\tBounds LRTB (%f, %f, %f, %f)\n", |
| 524 batch->name(), | 540 batch->name(), |
| 525 batch->uniqueID(), | 541 batch->uniqueID(), |
| 526 batch->bounds().fLeft, batch->bounds().fRight, | 542 batch->bounds().fLeft, batch->bounds().fRight, |
| 527 batch->bounds().fTop, batch->bounds().fBottom); | 543 batch->bounds().fTop, batch->bounds().fBottom); |
| 528 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); | 544 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); |
| 545 GrBATCH_INFO("\tClipped Bounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", |
| 546 clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight, |
| 547 clippedBounds.fBottom); |
| 529 GrBATCH_INFO("\tOutcome:\n"); | 548 GrBATCH_INFO("\tOutcome:\n"); |
| 530 int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count()); | 549 int maxCandidates = SkTMin(fMaxBatchLookback, fRecordedBatches.count()); |
| 531 if (maxCandidates) { | 550 if (maxCandidates) { |
| 532 int i = 0; | 551 int i = 0; |
| 533 while (true) { | 552 while (true) { |
| 534 GrBatch* candidate = fBatches.fromBack(i); | 553 GrBatch* candidate = fRecordedBatches.fromBack(i).fBatch.get(); |
| 535 // We cannot continue to search backwards if the render target chang
es | 554 // We cannot continue to search backwards if the render target chang
es |
| 536 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { | 555 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { |
| 537 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", | 556 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
| 538 candidate->name(), candidate->uniqueID()); | 557 candidate->name(), candidate->uniqueID()); |
| 539 break; | 558 break; |
| 540 } | 559 } |
| 541 if (candidate->combineIfPossible(batch, *this->caps())) { | 560 if (candidate->combineIfPossible(batch, *this->caps())) { |
| 542 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, | 561 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
| 543 candidate->uniqueID()); | 562 candidate->uniqueID()); |
| 544 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); | 563 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate,
batch); |
| 564 join(&fRecordedBatches.fromBack(i).fClippedBounds, |
| 565 fRecordedBatches.fromBack(i).fClippedBounds, clippedBounds)
; |
| 545 return; | 566 return; |
| 546 } | 567 } |
| 547 // Stop going backwards if we would cause a painter's order violatio
n. | 568 // 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 | 569 const SkRect& candidateBounds = fRecordedBatches.fromBack(i).fClippe
dBounds; |
| 549 // to clip each batch's bounds to the clip. | 570 if (!can_reorder(candidateBounds, clippedBounds)) { |
| 550 if (!can_reorder(candidate, batch)) { | |
| 551 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), | 571 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
| 552 candidate->uniqueID()); | 572 candidate->uniqueID()); |
| 553 break; | 573 break; |
| 554 } | 574 } |
| 555 ++i; | 575 ++i; |
| 556 if (i == maxCandidates) { | 576 if (i == maxCandidates) { |
| 557 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); | 577 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); |
| 558 break; | 578 break; |
| 559 } | 579 } |
| 560 } | 580 } |
| 561 } else { | 581 } else { |
| 562 GrBATCH_INFO("\t\tFirstBatch\n"); | 582 GrBATCH_INFO("\t\tFirstBatch\n"); |
| 563 } | 583 } |
| 564 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); | 584 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch); |
| 565 fBatches.push_back().reset(SkRef(batch)); | 585 fRecordedBatches.emplace_back(RecordedBatch{sk_ref_sp(batch), clippedBounds}
); |
| 566 } | 586 } |
| 567 | 587 |
| 568 void GrDrawTarget::forwardCombine() { | 588 void GrDrawTarget::forwardCombine() { |
| 569 for (int i = 0; i < fBatches.count() - 2; ++i) { | 589 for (int i = 0; i < fRecordedBatches.count() - 2; ++i) { |
| 570 GrBatch* batch = fBatches[i]; | 590 GrBatch* batch = fRecordedBatches[i].fBatch.get(); |
| 571 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fBatches.count() -
1); | 591 const SkRect& batchBounds = fRecordedBatches[i].fClippedBounds; |
| 592 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fRecordedBatches.co
unt() - 1); |
| 572 int j = i + 1; | 593 int j = i + 1; |
| 573 while (true) { | 594 while (true) { |
| 574 GrBatch* candidate = fBatches[j]; | 595 GrBatch* candidate = fRecordedBatches[j].fBatch.get(); |
| 575 // We cannot continue to search if the render target changes | 596 // We cannot continue to search if the render target changes |
| 576 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { | 597 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { |
| 577 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", | 598 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
| 578 candidate->name(), candidate->uniqueID()); | 599 candidate->name(), candidate->uniqueID()); |
| 579 break; | 600 break; |
| 580 } | 601 } |
| 581 if (j == i +1) { | 602 if (j == i +1) { |
| 582 // We assume batch would have combined with candidate when the c
andidate was added | 603 // We assume batch would have combined with candidate when the c
andidate was added |
| 583 // via backwards combining in recordBatch. | 604 // via backwards combining in recordBatch. |
| 584 SkASSERT(!batch->combineIfPossible(candidate, *this->caps())); | 605 SkASSERT(!batch->combineIfPossible(candidate, *this->caps())); |
| 585 } else if (batch->combineIfPossible(candidate, *this->caps())) { | 606 } else if (batch->combineIfPossible(candidate, *this->caps())) { |
| 586 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, | 607 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
| 587 candidate->uniqueID()); | 608 candidate->uniqueID()); |
| 588 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, cand
idate); | 609 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, cand
idate); |
| 589 fBatches[j].reset(SkRef(batch)); | 610 fRecordedBatches[j].fBatch = std::move(fRecordedBatches[i].fBatc
h); |
| 590 fBatches[i].reset(nullptr); | 611 join(&fRecordedBatches[j].fClippedBounds, fRecordedBatches[j].fC
lippedBounds, |
| 612 batchBounds); |
| 591 break; | 613 break; |
| 592 } | 614 } |
| 593 // Stop going traversing if we would cause a painter's order violati
on. | 615 // 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 | 616 const SkRect& candidateBounds = fRecordedBatches[j].fClippedBounds; |
| 595 // to clip each batch's bounds to the clip. | 617 if (!can_reorder(candidateBounds, batchBounds)) { |
| 596 if (!can_reorder(candidate, batch)) { | |
| 597 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), | 618 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
| 598 candidate->uniqueID()); | 619 candidate->uniqueID()); |
| 599 break; | 620 break; |
| 600 } | 621 } |
| 601 ++j; | 622 ++j; |
| 602 if (j > maxCandidateIdx) { | 623 if (j > maxCandidateIdx) { |
| 603 GrBATCH_INFO("\t\tReached max lookahead or end of batch array %d
\n", i); | 624 GrBATCH_INFO("\t\tReached max lookahead or end of batch array %d
\n", i); |
| 604 break; | 625 break; |
| 605 } | 626 } |
| 606 } | 627 } |
| 607 } | 628 } |
| 608 } | 629 } |
| 609 | 630 |
| 610 /////////////////////////////////////////////////////////////////////////////// | 631 /////////////////////////////////////////////////////////////////////////////// |
| 611 | 632 |
| 612 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { | 633 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { |
| 613 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); | 634 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); |
| 614 this->recordBatch(batch); | 635 this->recordBatch(batch, batch->bounds()); |
| 615 batch->unref(); | 636 batch->unref(); |
| 616 } | 637 } |
| OLD | NEW |