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 |