| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrDrawTarget.h" | 9 #include "GrDrawTarget.h" |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "batches/GrStencilPathBatch.h" | 29 #include "batches/GrStencilPathBatch.h" |
| 30 | 30 |
| 31 #include "SkStrokeRec.h" | 31 #include "SkStrokeRec.h" |
| 32 | 32 |
| 33 //////////////////////////////////////////////////////////////////////////////// | 33 //////////////////////////////////////////////////////////////////////////////// |
| 34 | 34 |
| 35 GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider) | 35 GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider) |
| 36 : fGpu(SkRef(gpu)) | 36 : fGpu(SkRef(gpu)) |
| 37 , fCaps(SkRef(gpu->caps())) | 37 , fCaps(SkRef(gpu->caps())) |
| 38 , fResourceProvider(resourceProvider) | 38 , fResourceProvider(resourceProvider) |
| 39 , fFlushing(false) { | 39 , fFlushing(false) |
| 40 , fLastFlushToken(0) { |
| 40 } | 41 } |
| 41 | 42 |
| 42 GrDrawTarget::~GrDrawTarget() { | 43 GrDrawTarget::~GrDrawTarget() { |
| 43 fGpu->unref(); | 44 fGpu->unref(); |
| 44 fCaps->unref(); | 45 fCaps->unref(); |
| 45 } | 46 } |
| 46 | 47 |
| 47 //////////////////////////////////////////////////////////////////////////////// | 48 //////////////////////////////////////////////////////////////////////////////// |
| 48 | 49 |
| 49 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
der, | 50 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
der, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop); | 113 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop); |
| 113 return true; | 114 return true; |
| 114 } | 115 } |
| 115 | 116 |
| 116 void GrDrawTarget::flush() { | 117 void GrDrawTarget::flush() { |
| 117 if (fFlushing) { | 118 if (fFlushing) { |
| 118 return; | 119 return; |
| 119 } | 120 } |
| 120 fFlushing = true; | 121 fFlushing = true; |
| 121 | 122 |
| 122 this->onFlush(); | 123 GrBatchFlushState flushState(fGpu, fResourceProvider, fLastFlushToken); |
| 124 |
| 125 // Loop over all batches and generate geometry |
| 126 for (int i = 0; i < fBatches.count(); ++i) { |
| 127 fBatches[i]->prepare(&flushState); |
| 128 } |
| 129 |
| 130 // Upload all data to the GPU |
| 131 flushState.preIssueDraws(); |
| 132 |
| 133 // Draw all the generated geometry. |
| 134 for (int i = 0; i < fBatches.count(); ++i) { |
| 135 fBatches[i]->draw(&flushState); |
| 136 } |
| 137 |
| 138 fLastFlushToken = flushState.lastFlushedToken(); |
| 123 | 139 |
| 124 fFlushing = false; | 140 fFlushing = false; |
| 125 this->reset(); | 141 this->reset(); |
| 126 } | 142 } |
| 127 | 143 |
| 144 void GrDrawTarget::reset() { |
| 145 fBatches.reset(); |
| 146 } |
| 147 |
| 128 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBat
ch* batch) { | 148 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBat
ch* batch) { |
| 129 // Setup clip | 149 // Setup clip |
| 130 GrScissorState scissorState; | 150 GrScissorState scissorState; |
| 131 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; | 151 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; |
| 132 GrPipelineBuilder::AutoRestoreStencil ars; | 152 GrPipelineBuilder::AutoRestoreStencil ars; |
| 133 if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &batch->b
ounds())) { | 153 if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &batch->b
ounds())) { |
| 134 return; | 154 return; |
| 135 } | 155 } |
| 136 | 156 |
| 137 // Batch bounds are tight, so for dev copies | 157 // Batch bounds are tight, so for dev copies |
| 138 // TODO move this into setupDstReadIfNecessary when paths are in batch | 158 // TODO move this into setupDstReadIfNecessary when paths are in batch |
| 139 SkRect bounds = batch->bounds(); | 159 SkRect bounds = batch->bounds(); |
| 140 bounds.outset(0.5f, 0.5f); | 160 bounds.outset(0.5f, 0.5f); |
| 141 | 161 |
| 142 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, bat
ch, &bounds, | 162 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, bat
ch, &bounds, |
| 143 this); | 163 this); |
| 144 | 164 |
| 145 if (!pipelineInfo.valid()) { | 165 if (!pipelineInfo.valid()) { |
| 146 return; | 166 return; |
| 147 } | 167 } |
| 148 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) { | 168 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) { |
| 149 return; | 169 return; |
| 150 } | 170 } |
| 151 this->onDrawBatch(batch); | 171 this->recordBatch(batch); |
| 152 } | 172 } |
| 153 | 173 |
| 154 static const GrStencilSettings& winding_path_stencil_settings() { | 174 static const GrStencilSettings& winding_path_stencil_settings() { |
| 155 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, | 175 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, |
| 156 kIncClamp_StencilOp, | 176 kIncClamp_StencilOp, |
| 157 kIncClamp_StencilOp, | 177 kIncClamp_StencilOp, |
| 158 kAlwaysIfInClip_StencilFunc, | 178 kAlwaysIfInClip_StencilFunc, |
| 159 0xFFFF, 0xFFFF, 0xFFFF); | 179 0xFFFF, 0xFFFF, 0xFFFF); |
| 160 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 180 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); |
| 161 } | 181 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 GrStencilSettings stencilSettings; | 226 GrStencilSettings stencilSettings; |
| 207 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 227 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 208 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment(); | 228 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment(); |
| 209 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); | 229 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); |
| 210 | 230 |
| 211 GrBatch* batch = GrStencilPathBatch::Create(pathProc->viewMatrix(), | 231 GrBatch* batch = GrStencilPathBatch::Create(pathProc->viewMatrix(), |
| 212 pipelineBuilder.isHWAntialias(), | 232 pipelineBuilder.isHWAntialias(), |
| 213 stencilSettings, scissorState, | 233 stencilSettings, scissorState, |
| 214 pipelineBuilder.getRenderTarget(
), | 234 pipelineBuilder.getRenderTarget(
), |
| 215 path); | 235 path); |
| 216 this->onDrawBatch(batch); | 236 this->recordBatch(batch); |
| 217 batch->unref(); | 237 batch->unref(); |
| 218 } | 238 } |
| 219 | 239 |
| 220 void GrDrawTarget::drawPath(const GrPipelineBuilder& pipelineBuilder, | 240 void GrDrawTarget::drawPath(const GrPipelineBuilder& pipelineBuilder, |
| 221 const GrPathProcessor* pathProc, | 241 const GrPathProcessor* pathProc, |
| 222 const GrPath* path, | 242 const GrPath* path, |
| 223 GrPathRendering::FillType fill) { | 243 GrPathRendering::FillType fill) { |
| 224 SkASSERT(path); | 244 SkASSERT(path); |
| 225 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); | 245 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); |
| 226 | 246 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, bat
ch, | 282 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, bat
ch, |
| 263 &batch->bounds(), this); | 283 &batch->bounds(), this); |
| 264 | 284 |
| 265 if (!pipelineInfo.valid()) { | 285 if (!pipelineInfo.valid()) { |
| 266 return; | 286 return; |
| 267 } | 287 } |
| 268 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) { | 288 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) { |
| 269 return; | 289 return; |
| 270 } | 290 } |
| 271 | 291 |
| 272 this->onDrawBatch(batch); | 292 this->recordBatch(batch); |
| 273 } | 293 } |
| 274 | 294 |
| 275 void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder, | 295 void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder, |
| 276 GrColor color, | 296 GrColor color, |
| 277 const SkMatrix& viewMatrix, | 297 const SkMatrix& viewMatrix, |
| 278 const SkRect& rect) { | 298 const SkRect& rect) { |
| 279 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, vi
ewMatrix, rect, | 299 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, vi
ewMatrix, rect, |
| 280 nullptr,
nullptr)); | 300 nullptr,
nullptr)); |
| 281 this->drawBatch(pipelineBuilder, batch); | 301 this->drawBatch(pipelineBuilder, batch); |
| 282 } | 302 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 if (rect == &rtRect) { | 357 if (rect == &rtRect) { |
| 338 this->discard(renderTarget); | 358 this->discard(renderTarget); |
| 339 } | 359 } |
| 340 | 360 |
| 341 GrPipelineBuilder pipelineBuilder; | 361 GrPipelineBuilder pipelineBuilder; |
| 342 pipelineBuilder.setRenderTarget(renderTarget); | 362 pipelineBuilder.setRenderTarget(renderTarget); |
| 343 | 363 |
| 344 this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect); | 364 this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect); |
| 345 } else { | 365 } else { |
| 346 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget); | 366 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget); |
| 347 this->onDrawBatch(batch); | 367 this->recordBatch(batch); |
| 348 batch->unref(); | 368 batch->unref(); |
| 349 } | 369 } |
| 350 } | 370 } |
| 351 | 371 |
| 352 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { | 372 void GrDrawTarget::discard(GrRenderTarget* renderTarget) { |
| 353 if (this->caps()->discardRenderTargetSupport()) { | 373 if (this->caps()->discardRenderTargetSupport()) { |
| 354 GrBatch* batch = new GrDiscardBatch(renderTarget); | 374 GrBatch* batch = new GrDiscardBatch(renderTarget); |
| 355 this->onDrawBatch(batch); | 375 this->recordBatch(batch); |
| 356 batch->unref(); | 376 batch->unref(); |
| 357 } | 377 } |
| 358 } | 378 } |
| 359 | 379 |
| 360 //////////////////////////////////////////////////////////////////////////////// | 380 //////////////////////////////////////////////////////////////////////////////// |
| 361 | 381 |
| 362 void GrDrawTarget::copySurface(GrSurface* dst, | 382 void GrDrawTarget::copySurface(GrSurface* dst, |
| 363 GrSurface* src, | 383 GrSurface* src, |
| 364 const SkIRect& srcRect, | 384 const SkIRect& srcRect, |
| 365 const SkIPoint& dstPoint) { | 385 const SkIPoint& dstPoint) { |
| 366 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); | 386 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint); |
| 367 if (batch) { | 387 if (batch) { |
| 368 this->onDrawBatch(batch); | 388 this->recordBatch(batch); |
| 369 batch->unref(); | 389 batch->unref(); |
| 370 } | 390 } |
| 371 } | 391 } |
| 372 | 392 |
| 393 template <class Left, class Right> static bool intersect(const Left& a, const Ri
ght& b) { |
| 394 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom && |
| 395 b.fLeft <= b.fRight && b.fTop <= b.fBottom); |
| 396 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.f
Top < a.fBottom; |
| 397 } |
| 398 |
| 399 void GrDrawTarget::recordBatch(GrBatch* batch) { |
| 400 // Check if there is a Batch Draw we can batch with by linearly searching ba
ck until we either |
| 401 // 1) check every draw |
| 402 // 2) intersect with something |
| 403 // 3) find a 'blocker' |
| 404 // Experimentally we have found that most batching occurs within the first 1
0 comparisons. |
| 405 static const int kMaxLookback = 10; |
| 406 |
| 407 GrBATCH_INFO("Re-Recording (%s, B%u)\n" |
| 408 "\tBounds (%f, %f, %f, %f)\n", |
| 409 batch->name(), |
| 410 batch->uniqueID(), |
| 411 batch->bounds().fLeft, batch->bounds().fRight, |
| 412 batch->bounds().fTop, batch->bounds().fBottom); |
| 413 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str()); |
| 414 GrBATCH_INFO("\tOutcome:\n"); |
| 415 int maxCandidates = SkTMin(kMaxLookback, fBatches.count()); |
| 416 if (maxCandidates) { |
| 417 int i = 0; |
| 418 while (true) { |
| 419 GrBatch* candidate = fBatches.fromBack(i); |
| 420 // We cannot continue to search backwards if the render target chang
es |
| 421 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID
()) { |
| 422 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", |
| 423 candidate->name(), candidate->uniqueID()); |
| 424 break; |
| 425 } |
| 426 if (candidate->combineIfPossible(batch, *this->caps())) { |
| 427 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name()
, |
| 428 candidate->uniqueID()); |
| 429 return; |
| 430 } |
| 431 // Stop going backwards if we would cause a painter's order violatio
n. |
| 432 if (intersect(candidate->bounds(), batch->bounds())) { |
| 433 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(
), |
| 434 candidate->uniqueID()); |
| 435 break; |
| 436 } |
| 437 ++i; |
| 438 if (i == maxCandidates) { |
| 439 GrBATCH_INFO("\t\tReached max lookback or beginning of batch arr
ay %d\n", i); |
| 440 break; |
| 441 } |
| 442 } |
| 443 } else { |
| 444 GrBATCH_INFO("\t\tFirstBatch\n"); |
| 445 } |
| 446 fBatches.push_back().reset(SkRef(batch)); |
| 447 } |
| 448 |
| 373 /////////////////////////////////////////////////////////////////////////////// | 449 /////////////////////////////////////////////////////////////////////////////// |
| 374 | 450 |
| 375 GrDrawTarget::PipelineInfo::PipelineInfo(const GrPipelineBuilder* pipelineBuilde
r, | 451 GrDrawTarget::PipelineInfo::PipelineInfo(const GrPipelineBuilder* pipelineBuilde
r, |
| 376 const GrScissorState* scissor, | 452 const GrScissorState* scissor, |
| 377 const GrDrawBatch* batch, | 453 const GrDrawBatch* batch, |
| 378 const SkRect* devBounds, | 454 const SkRect* devBounds, |
| 379 GrDrawTarget* target) { | 455 GrDrawTarget* target) { |
| 380 fArgs.fPipelineBuilder = pipelineBuilder; | 456 fArgs.fPipelineBuilder = pipelineBuilder; |
| 381 fArgs.fCaps = target->caps(); | 457 fArgs.fCaps = target->caps(); |
| 382 fArgs.fScissor = scissor; | 458 fArgs.fScissor = scissor; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 409 } | 485 } |
| 410 | 486 |
| 411 void GrClipTarget::purgeResources() { | 487 void GrClipTarget::purgeResources() { |
| 412 // The clip mask manager can rebuild all its clip masks so just | 488 // The clip mask manager can rebuild all its clip masks so just |
| 413 // get rid of them all. | 489 // get rid of them all. |
| 414 fClipMaskManager->purgeResources(); | 490 fClipMaskManager->purgeResources(); |
| 415 }; | 491 }; |
| 416 | 492 |
| 417 void GrClipTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { | 493 void GrClipTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRend
erTarget* rt) { |
| 418 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); | 494 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); |
| 419 this->onDrawBatch(batch); | 495 this->recordBatch(batch); |
| 420 batch->unref(); | 496 batch->unref(); |
| 421 } | 497 } |
| OLD | NEW |