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 |