1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "GrDrawTarget.h" 10 11 #include "GrAuditTrail.h" 12 #include "GrCaps.h" 13 #include "GrGpu.h" 14 #include "GrPath.h" 15 #include "GrPipeline.h" 16 #include "GrMemoryPool.h" 17 #include "GrRenderTarget.h" 18 #include "GrResourceProvider.h" 19 #include "GrRenderTargetPriv.h" 20 #include "GrSurfacePriv.h" 21 #include "GrTexture.h" 22 #include "GrVertexBuffer.h" 23 #include "gl/GrGLRenderTarget.h" 24 25 #include "SkStrokeRec.h" 26 27 #include "batches/GrClearBatch.h" 28 #include "batches/GrCopySurfaceBatch.h" 29 #include "batches/GrDiscardBatch.h" 30 #include "batches/GrDrawBatch.h" 31 #include "batches/GrDrawPathBatch.h" 32 #include "batches/GrRectBatchFactory.h" 33 #include "batches/GrStencilPathBatch.h" 34 35 //////////////////////////////////////////////////////////////////////////////// 36 37 // Experimentally we have found that most batching occurs within the first 10 comparisons. 38 static const int kDefaultMaxBatchLookback = 10; 39 40 GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider, 41 GrAuditTrail* auditTrail, const Options& options) 42 : fGpu(SkRef(gpu)) 43 , fResourceProvider(resourceProvider) 44 , fAuditTrail(auditTrail) 45 , fFlags(0) 46 , fRenderTarget(rt) { 47 // TODO: Stop extracting the context (currently needed by GrClipMaskManager) 48 fContext = fGpu->getContext(); 49 fClipMaskManager.reset(new GrClipMaskManager(this, options.fClipBatchToBounds)); 50 51 fDrawBatchBounds = options.fDrawBatchBounds; 52 fMaxBatchLookback = (options.fMaxBatchLookback < 0) ? kDefaultMaxBatchLookback : 53 options.fMaxBatchLookback; 54 55 rt->setLastDrawTarget(this); 56 57 #ifdef SK_DEBUG 58 static int debugID = 0; 59 fDebugID = debugID++; 60 #endif 61 } 62 63 GrDrawTarget::~GrDrawTarget() { 64 if (fRenderTarget && this == fRenderTarget->getLastDrawTarget()) { 65 fRenderTarget->setLastDrawTarget(nullptr); 66 } 67 68 fGpu->unref(); 69 } 70 71 //////////////////////////////////////////////////////////////////////////////// 72 73 // Add a GrDrawTarget-based dependency 74 void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) { 75 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad 76 77 if (this->dependsOn(dependedOn)) { 78 return; // don't add duplicate dependencies 79 } 80 81 *fDependencies.push() = dependedOn; 82 } 83 84 // Convert from a GrSurface-based dependency to a GrDrawTarget one 85 void GrDrawTarget::addDependency(GrSurface* dependedOn) { 86 if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) { 87 // If it is still receiving dependencies, this DT shouldn't be closed 88 SkASSERT(!this->isClosed()); 89 90 GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget(); 91 if (dt == this) { 92 // self-read - presumably for dst reads 93 } else { 94 this->addDependency(dt); 95 96 // Can't make it closed in the self-read case 97 dt->makeClosed(); 98 } 99 } 100 } 101 102 #ifdef SK_DEBUG 103 void GrDrawTarget::dump() const { 104 SkDebugf("--------------------------------------------------------------\n"); 105 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->getUniqueID() : -1); 106 SkDebugf("relies On (%d): ", fDependencies.count()); 107 for (int i = 0; i < fDependencies.count(); ++i) { 108 SkDebugf("%d, ", fDependencies[i]->fDebugID); 109 } 110 SkDebugf("\n"); 111 SkDebugf("batches (%d):\n", fBatches.count()); 112 for (int i = 0; i < fBatches.count(); ++i) { 113 #if 0 114 SkDebugf("*******************************\n"); 115 #endif 116 SkDebugf("%d: %s\n", i, fBatches[i]->name()); 117 #if 0 118 SkString str = fBatches[i]->dumpInfo(); 119 SkDebugf("%s\n", str.c_str()); 120 #endif 121 } 122 } 123 #endif 124 125 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder, 126 const GrPipelineOptimizations& optimizations, 127 GrXferProcessor::DstTexture* dstTexture, 128 const SkRect& batchBounds) { 129 SkRect bounds = batchBounds; 130 bounds.outset(0.5f, 0.5f); 131 132 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) { 133 return true; 134 } 135 136 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); 137 138 if (this->caps()->textureBarrierSupport()) { 139 if (GrTexture* rtTex = rt->asTexture()) { 140 // The render target is a texture, so we can read from it directly in the shader. The XP 141 // will be responsible to detect this situation and request a texture barrier. 142 dstTexture->setTexture(rtTex); 143 dstTexture->setOffset(0, 0); 144 return true; 145 } 146 } 147 148 SkIRect copyRect; 149 pipelineBuilder.clip().getConservativeBounds(rt->width(), rt->height(), ©Rect); 150 151 SkIRect drawIBounds; 152 bounds.roundOut(&drawIBounds); 153 if (!copyRect.intersect(drawIBounds)) { 154 #ifdef SK_DEBUG 155 GrCapsDebugf(this->caps(), "Missed an early reject. " 156 "Bailing on draw from setupDstReadIfNecessary.\n"); 157 #endif 158 return false; 159 } 160 161 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 162 // have per-sample dst values by making the copy multisampled. 163 GrSurfaceDesc desc; 164 if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) { 165 desc.fOrigin = kDefault_GrSurfaceOrigin; 166 desc.fFlags = kRenderTarget_GrSurfaceFlag; 167 desc.fConfig = rt->config(); 168 } 169 170 desc.fWidth = copyRect.width(); 171 desc.fHeight = copyRect.height(); 172 173 static const uint32_t kFlags = 0; 174 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags)); 175 176 if (!copy) { 177 SkDebugf("Failed to create temporary copy of destination texture.\n"); 178 return false; 179 } 180 SkIPoint dstPoint = {0, 0}; 181 this->copySurface(copy, rt, copyRect, dstPoint); 182 dstTexture->setTexture(copy); 183 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop); 184 return true; 185 } 186 187 void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) { 188 // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh 189 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed 190 // but need to be flushed anyway. Closing such drawTargets here will mean new 191 // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again. 192 this->makeClosed(); 193 194 // Loop over the batches that haven't yet generated their geometry 195 for (int i = 0; i < fBatches.count(); ++i) { 196 fBatches[i]->prepare(flushState); 197 } 198 } 199 200 void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) { 201 // Draw all the generated geometry. 202 SkRandom random; 203 for (int i = 0; i < fBatches.count(); ++i) { 204 if (fDrawBatchBounds) { 205 const SkRect& bounds = fBatches[i]->bounds(); 206 SkIRect ibounds; 207 bounds.roundOut(&ibounds); 208 // In multi-draw buffer all the batches use the same render target and we won't need to 209 // get the batchs bounds. 210 if (GrRenderTarget* rt = fBatches[i]->renderTarget()) { 211 fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU()); 212 } 213 } 214 fBatches[i]->draw(flushState); 215 } 216 217 fGpu->finishDrawTarget(); 218 } 219 220 void GrDrawTarget::reset() { 221 fBatches.reset(); 222 } 223 224 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) { 225 // Setup clip 226 GrPipelineBuilder::AutoRestoreStencil ars; 227 GrAppliedClip clip; 228 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) { 229 return; 230 } 231 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; 232 if (clip.clipCoverageFragmentProcessor()) { 233 arfps.set(&pipelineBuilder); 234 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor()); 235 } 236 237 GrPipeline::CreateArgs args; 238 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) { 239 return; 240 } 241 242 #ifdef ENABLE_MDB 243 SkASSERT(fRenderTarget); 244 batch->pipeline()->addDependenciesTo(fRenderTarget); 245 #endif 246 247 this->recordBatch(batch); 248 } 249 250 static const GrStencilSettings& winding_path_stencil_settings() { 251 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 252 kIncClamp_StencilOp, 253 kIncClamp_StencilOp, 254 kAlwaysIfInClip_StencilFunc, 255 0xFFFF, 0xFFFF, 0xFFFF); 256 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 257 } 258 259 static const GrStencilSettings& even_odd_path_stencil_settings() { 260 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 261 kInvert_StencilOp, 262 kInvert_StencilOp, 263 kAlwaysIfInClip_StencilFunc, 264 0xFFFF, 0xFFFF, 0xFFFF); 265 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 266 } 267 268 void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill, 269 const GrStencilAttachment* sb, 270 GrStencilSettings* outStencilSettings) { 271 272 switch (fill) { 273 default: 274 SkFAIL("Unexpected path fill."); 275 case GrPathRendering::kWinding_FillType: 276 *outStencilSettings = winding_path_stencil_settings(); 277 break; 278 case GrPathRendering::kEvenOdd_FillType: 279 *outStencilSettings = even_odd_path_stencil_settings(); 280 break; 281 } 282 fClipMaskManager->adjustPathStencilParams(sb, outStencilSettings); 283 } 284 285 void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder, 286 const SkMatrix& viewMatrix, 287 const GrPath* path, 288 GrPathRendering::FillType fill) { 289 // TODO: extract portions of checkDraw that are relevant to path stenciling. 290 SkASSERT(path); 291 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); 292 293 // Setup clip 294 GrPipelineBuilder::AutoRestoreStencil ars; 295 GrAppliedClip clip; 296 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, nullptr, &clip)) { 297 return; 298 } 299 300 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; 301 if (clip.clipCoverageFragmentProcessor()) { 302 arfps.set(&pipelineBuilder); 303 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor()); 304 } 305 306 // set stencil settings for path 307 GrStencilSettings stencilSettings; 308 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); 309 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt); 310 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 311 312 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, 313 pipelineBuilder.isHWAntialias(), 314 stencilSettings, clip.scissorState(), 315 pipelineBuilder.getRenderTarget(), 316 path); 317 this->recordBatch(batch); 318 batch->unref(); 319 } 320 321 void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder, 322 GrDrawPathBatchBase* batch) { 323 // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted 324 // after setting up clipping but before onDrawBatch(). TODO: Figure out a better model for 325 // handling stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and 326 // batches. 327 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); 328 329 GrPipelineBuilder::AutoRestoreStencil ars; 330 GrAppliedClip clip; 331 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) { 332 return; 333 } 334 335 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; 336 if (clip.clipCoverageFragmentProcessor()) { 337 arfps.set(&pipelineBuilder); 338 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor()); 339 } 340 341 // Ensure the render target has a stencil buffer and get the stencil settings. 342 GrStencilSettings stencilSettings; 343 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); 344 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt); 345 this->getPathStencilSettingsForFilltype(batch->fillType(), sb, &stencilSettings); 346 batch->setStencilSettings(stencilSettings); 347 348 GrPipeline::CreateArgs args; 349 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) { 350 return; 351 } 352 353 this->recordBatch(batch); 354 } 355 356 void GrDrawTarget::clear(const SkIRect* rect, 357 GrColor color, 358 bool canIgnoreRect, 359 GrRenderTarget* renderTarget) { 360 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height()); 361 SkIRect clippedRect; 362 if (!rect || 363 (canIgnoreRect && this->caps()->fullClearIsFree()) || 364 rect->contains(rtRect)) { 365 rect = &rtRect; 366 } else { 367 clippedRect = *rect; 368 if (!clippedRect.intersect(rtRect)) { 369 return; 370 } 371 rect = &clippedRect; 372 } 373 374 if (this->caps()->useDrawInsteadOfClear()) { 375 // This works around a driver bug with clear by drawing a rect instead. 376 // The driver will ignore a clear if it is the only thing rendered to a 377 // target before the target is read. 378 if (rect == &rtRect) { 379 this->discard(renderTarget); 380 } 381 382 GrPipelineBuilder pipelineBuilder; 383 pipelineBuilder.setXPFactory( 384 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref(); 385 pipelineBuilder.setRenderTarget(renderTarget); 386 387 SkRect scalarRect = SkRect::Make(*rect); 388 SkAutoTUnref<GrDrawBatch> batch( 389 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalarRect, 390 nullptr, nullptr)); 391 this->drawBatch(pipelineBuilder, batch); 392 } else { 393 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget); 394 this->recordBatch(batch); 395 batch->unref(); 396 } 397 } 398 399 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { 400 if (this->caps()->discardRenderTargetSupport()) { 401 GrBatch* batch = new GrDiscardBatch(renderTarget); 402 this->recordBatch(batch); 403 batch->unref(); 404 } 405 } 406 407 //////////////////////////////////////////////////////////////////////////////// 408 409 bool GrDrawTarget::copySurface(GrSurface* dst, 410 GrSurface* src, 411 const SkIRect& srcRect, 412 const SkIPoint& dstPoint) { 413 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); 414 if (!batch) { 415 return false; 416 } 417 #ifdef ENABLE_MDB 418 this->addDependency(src); 419 #endif 420 421 this->recordBatch(batch); 422 batch->unref(); 423 return true; 424 } 425 426 template <class Left, class Right> static bool intersect(const Left& a, const Right& b) { 427 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom && 428 b.fLeft <= b.fRight && b.fTop <= b.fBottom); 429 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom; 430 } 431 432 void GrDrawTarget::recordBatch(GrBatch* batch) { 433 // A closed drawTarget should never receive new/more batches 434 SkASSERT(!this->isClosed()); 435 436 // Check if there is a Batch Draw we can batch with by linearly searching back until we either 437 // 1) check every draw 438 // 2) intersect with something 439 // 3) find a 'blocker' 440 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch->name(), batch->bounds()); 441 GrBATCH_INFO("Re-Recording (%s, B%u)\n" 442 "\tBounds LRTB (%f, %f, %f, %f)\n", 443 batch->name(), 444 batch->uniqueID(), 445 batch->bounds().fLeft, batch->bounds().fRight, 446 batch->bounds().fTop, batch->bounds().fBottom); 447 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); 448 GrBATCH_INFO("\tOutcome:\n"); 449 int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count()); 450 if (maxCandidates) { 451 int i = 0; 452 while (true) { 453 GrBatch* candidate = fBatches.fromBack(i); 454 // We cannot continue to search backwards if the render target changes 455 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) { 456 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", 457 candidate->name(), candidate->uniqueID()); 458 break; 459 } 460 if (candidate->combineIfPossible(batch, *this->caps())) { 461 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(), 462 candidate->uniqueID()); 463 return; 464 } 465 // Stop going backwards if we would cause a painter's order violation. 466 // TODO: The bounds used here do not fully consider the clip. It may be advantageous 467 // to clip each batch's bounds to the clip. 468 if (intersect(candidate->bounds(), batch->bounds())) { 469 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(), 470 candidate->uniqueID()); 471 break; 472 } 473 ++i; 474 if (i == maxCandidates) { 475 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i); 476 break; 477 } 478 } 479 } else { 480 GrBATCH_INFO("\t\tFirstBatch\n"); 481 } 482 fBatches.push_back().reset(SkRef(batch)); 483 } 484 485 /////////////////////////////////////////////////////////////////////////////// 486 487 bool GrDrawTarget::installPipelineInDrawBatch(const GrPipelineBuilder* pipelineBuilder, 488 const GrScissorState* scissor, 489 GrDrawBatch* batch) { 490 GrPipeline::CreateArgs args; 491 args.fPipelineBuilder = pipelineBuilder; 492 args.fCaps = this->caps(); 493 args.fScissor = scissor; 494 batch->getPipelineOptimizations(&args.fOpts); 495 GrScissorState finalScissor; 496 if (args.fOpts.fOverrides.fUsePLSDstRead) { 497 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 498 GrGLIRect viewport; 499 viewport.fLeft = 0; 500 viewport.fBottom = 0; 501 viewport.fWidth = rt->width(); 502 viewport.fHeight = rt->height(); 503 SkIRect ibounds; 504 ibounds.fLeft = SkTPin(SkScalarFloorToInt(batch->bounds().fLeft), viewport.fLeft, 505 viewport.fWidth); 506 ibounds.fTop = SkTPin(SkScalarFloorToInt(batch->bounds().fTop), viewport.fBottom, 507 viewport.fHeight); 508 ibounds.fRight = SkTPin(SkScalarCeilToInt(batch->bounds().fRight), viewport.fLeft, 509 viewport.fWidth); 510 ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom, 511 viewport.fHeight); 512 if (scissor != nullptr && scissor->enabled()) { 513 if (!ibounds.intersect(scissor->rect())) { 514 ibounds = scissor->rect(); 515 } 516 } 517 finalScissor.set(ibounds); 518 args.fScissor = &finalScissor; 519 } 520 args.fOpts.fColorPOI.completeCalculations(pipelineBuilder->fColorFragmentProcessors.begin(), 521 pipelineBuilder->numColorFragmentProcessors()); 522 args.fOpts.fCoveragePOI.completeCalculations( 523 pipelineBuilder->fCoverageFragmentProcessors.begin(), 524 pipelineBuilder->numCoverageFragmentProcessors()); 525 if (!this->setupDstReadIfNecessary(*pipelineBuilder, args.fOpts, &args.fDstTexture, 526 batch->bounds())) { 527 return false; 528 } 529 530 if (!batch->installPipeline(args)) { 531 return false; 532 } 533 534 return true; 535 } 536 537 void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) { 538 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); 539 this->recordBatch(batch); 540 batch->unref(); 541 } 542