GrDrawTarget.cpp revision 8415abe44cf205ac214b7793c076fd8c13272240
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 "GrBatch.h" 12#include "GrBufferAllocPool.h" 13#include "GrContext.h" 14#include "GrDrawTargetCaps.h" 15#include "GrPath.h" 16#include "GrPipeline.h" 17#include "GrMemoryPool.h" 18#include "GrRenderTarget.h" 19#include "GrRenderTargetPriv.h" 20#include "GrSurfacePriv.h" 21#include "GrTemplates.h" 22#include "GrTexture.h" 23#include "GrVertexBuffer.h" 24 25#include "SkStrokeRec.h" 26 27//////////////////////////////////////////////////////////////////////////////// 28 29GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) { 30 fPrimitiveType = di.fPrimitiveType; 31 fStartVertex = di.fStartVertex; 32 fStartIndex = di.fStartIndex; 33 fVertexCount = di.fVertexCount; 34 fIndexCount = di.fIndexCount; 35 36 fInstanceCount = di.fInstanceCount; 37 fVerticesPerInstance = di.fVerticesPerInstance; 38 fIndicesPerInstance = di.fIndicesPerInstance; 39 40 if (di.fDevBounds) { 41 SkASSERT(di.fDevBounds == &di.fDevBoundsStorage); 42 fDevBoundsStorage = di.fDevBoundsStorage; 43 fDevBounds = &fDevBoundsStorage; 44 } else { 45 fDevBounds = NULL; 46 } 47 48 this->setVertexBuffer(di.vertexBuffer()); 49 this->setIndexBuffer(di.indexBuffer()); 50 51 return *this; 52} 53 54//////////////////////////////////////////////////////////////////////////////// 55 56#define DEBUG_INVAL_BUFFER 0xdeadcafe 57#define DEBUG_INVAL_START_IDX -1 58 59GrDrawTarget::GrDrawTarget(GrContext* context, 60 GrVertexBufferAllocPool* vpool, 61 GrIndexBufferAllocPool* ipool) 62 : fContext(context) 63 , fCaps(SkRef(context->getGpu()->caps())) 64 , fGpuTraceMarkerCount(0) 65 , fVertexPool(vpool) 66 , fIndexPool(ipool) 67 , fFlushing(false) { 68 SkASSERT(context); 69} 70 71//////////////////////////////////////////////////////////////////////////////// 72 73bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder, 74 const GrProcOptInfo& colorPOI, 75 const GrProcOptInfo& coveragePOI, 76 GrDeviceCoordTexture* dstCopy, 77 const SkRect* drawBounds) { 78 if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) { 79 return true; 80 } 81 82 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); 83 84 if (this->caps()->textureBarrierSupport()) { 85 if (GrTexture* rtTex = rt->asTexture()) { 86 // The render target is a texture, se we can read from it directly in the shader. The XP 87 // will be responsible to detect this situation and request a texture barrier. 88 dstCopy->setTexture(rtTex); 89 dstCopy->setOffset(0, 0); 90 return true; 91 } 92 } 93 94 SkIRect copyRect; 95 pipelineBuilder.clip().getConservativeBounds(rt, ©Rect); 96 97 if (drawBounds) { 98 SkIRect drawIBounds; 99 drawBounds->roundOut(&drawIBounds); 100 if (!copyRect.intersect(drawIBounds)) { 101#ifdef SK_DEBUG 102 SkDebugf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 103#endif 104 return false; 105 } 106 } else { 107#ifdef SK_DEBUG 108 //SkDebugf("No dev bounds when dst copy is made.\n"); 109#endif 110 } 111 112 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 113 // have per-sample dst values by making the copy multisampled. 114 GrSurfaceDesc desc; 115 if (!this->getGpu()->initCopySurfaceDstDesc(rt, &desc)) { 116 desc.fOrigin = kDefault_GrSurfaceOrigin; 117 desc.fFlags = kRenderTarget_GrSurfaceFlag; 118 desc.fConfig = rt->config(); 119 } 120 121 122 desc.fWidth = copyRect.width(); 123 desc.fHeight = copyRect.height(); 124 125 SkAutoTUnref<GrTexture> copy(fContext->textureProvider()->refScratchTexture(desc, 126 GrTextureProvider::kApprox_ScratchTexMatch)); 127 128 if (!copy) { 129 SkDebugf("Failed to create temporary copy of destination texture.\n"); 130 return false; 131 } 132 SkIPoint dstPoint = {0, 0}; 133 if (this->copySurface(copy, rt, copyRect, dstPoint)) { 134 dstCopy->setTexture(copy); 135 dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); 136 return true; 137 } else { 138 return false; 139 } 140} 141 142void GrDrawTarget::reset() { 143 fVertexPool->reset(); 144 fIndexPool->reset(); 145 146 this->onReset(); 147} 148 149void GrDrawTarget::flush() { 150 if (fFlushing) { 151 return; 152 } 153 fFlushing = true; 154 155 this->getGpu()->saveActiveTraceMarkers(); 156 157 this->onFlush(); 158 159 this->getGpu()->restoreActiveTraceMarkers(); 160 161 fFlushing = false; 162 this->reset(); 163} 164 165void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder, 166 GrBatch* batch) { 167 SkASSERT(pipelineBuilder); 168 // TODO some kind of checkdraw, but not at this level 169 170 // Setup clip 171 GrScissorState scissorState; 172 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; 173 GrPipelineBuilder::AutoRestoreStencil ars; 174 if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &batch->bounds())) { 175 return; 176 } 177 178 // Batch bounds are tight, so for dev copies 179 // TODO move this into setupDstReadIfNecessary when paths are in batch 180 SkRect bounds = batch->bounds(); 181 bounds.outset(0.5f, 0.5f); 182 183 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, batch, &bounds, 184 this); 185 if (pipelineInfo.mustSkipDraw()) { 186 return; 187 } 188 189 this->onDrawBatch(batch, pipelineInfo); 190} 191 192static const GrStencilSettings& winding_path_stencil_settings() { 193 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 194 kIncClamp_StencilOp, 195 kIncClamp_StencilOp, 196 kAlwaysIfInClip_StencilFunc, 197 0xFFFF, 0xFFFF, 0xFFFF); 198 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 199} 200 201static const GrStencilSettings& even_odd_path_stencil_settings() { 202 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 203 kInvert_StencilOp, 204 kInvert_StencilOp, 205 kAlwaysIfInClip_StencilFunc, 206 0xFFFF, 0xFFFF, 0xFFFF); 207 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 208} 209 210void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill, 211 const GrStencilAttachment* sb, 212 GrStencilSettings* outStencilSettings) { 213 214 switch (fill) { 215 default: 216 SkFAIL("Unexpected path fill."); 217 case GrPathRendering::kWinding_FillType: 218 *outStencilSettings = winding_path_stencil_settings(); 219 break; 220 case GrPathRendering::kEvenOdd_FillType: 221 *outStencilSettings = even_odd_path_stencil_settings(); 222 break; 223 } 224 this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings); 225} 226 227void GrDrawTarget::stencilPath(GrPipelineBuilder* pipelineBuilder, 228 const GrPathProcessor* pathProc, 229 const GrPath* path, 230 GrPathRendering::FillType fill) { 231 // TODO: extract portions of checkDraw that are relevant to path stenciling. 232 SkASSERT(path); 233 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); 234 SkASSERT(pipelineBuilder); 235 236 // Setup clip 237 GrScissorState scissorState; 238 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; 239 GrPipelineBuilder::AutoRestoreStencil ars; 240 if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) { 241 return; 242 } 243 244 // set stencil settings for path 245 GrStencilSettings stencilSettings; 246 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 247 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment(); 248 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 249 250 this->onStencilPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings); 251} 252 253void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder, 254 const GrPathProcessor* pathProc, 255 const GrPath* path, 256 GrPathRendering::FillType fill) { 257 // TODO: extract portions of checkDraw that are relevant to path rendering. 258 SkASSERT(path); 259 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); 260 SkASSERT(pipelineBuilder); 261 262 SkRect devBounds = path->getBounds(); 263 pathProc->viewMatrix().mapRect(&devBounds); 264 265 // Setup clip 266 GrScissorState scissorState; 267 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; 268 GrPipelineBuilder::AutoRestoreStencil ars; 269 if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &devBounds)) { 270 return; 271 } 272 273 // set stencil settings for path 274 GrStencilSettings stencilSettings; 275 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 276 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment(); 277 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 278 279 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, &devBounds, 280 this); 281 if (pipelineInfo.mustSkipDraw()) { 282 return; 283 } 284 285 this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo); 286} 287 288void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder, 289 const GrPathProcessor* pathProc, 290 const GrPathRange* pathRange, 291 const void* indices, 292 PathIndexType indexType, 293 const float transformValues[], 294 PathTransformType transformType, 295 int count, 296 GrPathRendering::FillType fill) { 297 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); 298 SkASSERT(pathRange); 299 SkASSERT(indices); 300 SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType)); 301 SkASSERT(transformValues); 302 SkASSERT(pipelineBuilder); 303 304 // Setup clip 305 GrScissorState scissorState; 306 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; 307 GrPipelineBuilder::AutoRestoreStencil ars; 308 309 if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) { 310 return; 311 } 312 313 // set stencil settings for path 314 GrStencilSettings stencilSettings; 315 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 316 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment(); 317 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 318 319 // Don't compute a bounding box for dst copy texture, we'll opt 320 // instead for it to just copy the entire dst. Realistically this is a moot 321 // point, because any context that supports NV_path_rendering will also 322 // support NV_blend_equation_advanced. 323 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, NULL, this); 324 if (pipelineInfo.mustSkipDraw()) { 325 return; 326 } 327 328 this->onDrawPaths(pathProc, pathRange, indices, indexType, transformValues, 329 transformType, count, stencilSettings, pipelineInfo); 330} 331 332void GrDrawTarget::clear(const SkIRect* rect, 333 GrColor color, 334 bool canIgnoreRect, 335 GrRenderTarget* renderTarget) { 336 if (fCaps->useDrawInsteadOfClear()) { 337 // This works around a driver bug with clear by drawing a rect instead. 338 // The driver will ignore a clear if it is the only thing rendered to a 339 // target before the target is read. 340 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height()); 341 if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) { 342 rect = &rtRect; 343 // We first issue a discard() since that may help tilers. 344 this->discard(renderTarget); 345 } 346 347 GrPipelineBuilder pipelineBuilder; 348 pipelineBuilder.setRenderTarget(renderTarget); 349 350 this->drawSimpleRect(&pipelineBuilder, color, SkMatrix::I(), *rect); 351 } else { 352 this->onClear(rect, color, canIgnoreRect, renderTarget); 353 } 354} 355 356typedef GrTraceMarkerSet::Iter TMIter; 357void GrDrawTarget::saveActiveTraceMarkers() { 358 if (this->caps()->gpuTracingSupport()) { 359 SkASSERT(0 == fStoredTraceMarkers.count()); 360 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 361 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 362 this->removeGpuTraceMarker(&(*iter)); 363 } 364 } 365} 366 367void GrDrawTarget::restoreActiveTraceMarkers() { 368 if (this->caps()->gpuTracingSupport()) { 369 SkASSERT(0 == fActiveTraceMarkers.count()); 370 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 371 this->addGpuTraceMarker(&(*iter)); 372 } 373 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 374 this->fStoredTraceMarkers.remove(*iter); 375 } 376 } 377} 378 379void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 380 if (this->caps()->gpuTracingSupport()) { 381 SkASSERT(fGpuTraceMarkerCount >= 0); 382 this->fActiveTraceMarkers.add(*marker); 383 ++fGpuTraceMarkerCount; 384 } 385} 386 387void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 388 if (this->caps()->gpuTracingSupport()) { 389 SkASSERT(fGpuTraceMarkerCount >= 1); 390 this->fActiveTraceMarkers.remove(*marker); 391 --fGpuTraceMarkerCount; 392 } 393} 394 395//////////////////////////////////////////////////////////////////////////////// 396 397namespace { 398// returns true if the read/written rect intersects the src/dst and false if not. 399bool clip_srcrect_and_dstpoint(const GrSurface* dst, 400 const GrSurface* src, 401 const SkIRect& srcRect, 402 const SkIPoint& dstPoint, 403 SkIRect* clippedSrcRect, 404 SkIPoint* clippedDstPoint) { 405 *clippedSrcRect = srcRect; 406 *clippedDstPoint = dstPoint; 407 408 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 409 if (clippedSrcRect->fLeft < 0) { 410 clippedDstPoint->fX -= clippedSrcRect->fLeft; 411 clippedSrcRect->fLeft = 0; 412 } 413 if (clippedDstPoint->fX < 0) { 414 clippedSrcRect->fLeft -= clippedDstPoint->fX; 415 clippedDstPoint->fX = 0; 416 } 417 418 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 419 if (clippedSrcRect->fTop < 0) { 420 clippedDstPoint->fY -= clippedSrcRect->fTop; 421 clippedSrcRect->fTop = 0; 422 } 423 if (clippedDstPoint->fY < 0) { 424 clippedSrcRect->fTop -= clippedDstPoint->fY; 425 clippedDstPoint->fY = 0; 426 } 427 428 // clip the right edge to the src and dst bounds. 429 if (clippedSrcRect->fRight > src->width()) { 430 clippedSrcRect->fRight = src->width(); 431 } 432 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 433 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 434 } 435 436 // clip the bottom edge to the src and dst bounds. 437 if (clippedSrcRect->fBottom > src->height()) { 438 clippedSrcRect->fBottom = src->height(); 439 } 440 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 441 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 442 } 443 444 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 445 // dst bounds. 446 return !clippedSrcRect->isEmpty(); 447} 448} 449 450bool GrDrawTarget::copySurface(GrSurface* dst, 451 GrSurface* src, 452 const SkIRect& srcRect, 453 const SkIPoint& dstPoint) { 454 SkASSERT(dst); 455 SkASSERT(src); 456 457 SkIRect clippedSrcRect; 458 SkIPoint clippedDstPoint; 459 // If the rect is outside the src or dst then we've already succeeded. 460 if (!clip_srcrect_and_dstpoint(dst, 461 src, 462 srcRect, 463 dstPoint, 464 &clippedSrcRect, 465 &clippedDstPoint)) { 466 return true; 467 } 468 469 if (this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)) { 470 this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 471 return true; 472 } 473 474 GrRenderTarget* rt = dst->asRenderTarget(); 475 GrTexture* tex = src->asTexture(); 476 477 if ((dst == src) || !rt || !tex) { 478 return false; 479 } 480 481 GrPipelineBuilder pipelineBuilder; 482 pipelineBuilder.setRenderTarget(rt); 483 SkMatrix matrix; 484 matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX), 485 SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY)); 486 matrix.postIDiv(tex->width(), tex->height()); 487 pipelineBuilder.addColorTextureProcessor(tex, matrix); 488 SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX, 489 clippedDstPoint.fY, 490 clippedSrcRect.width(), 491 clippedSrcRect.height()); 492 this->drawSimpleRect(&pipelineBuilder, GrColor_WHITE, SkMatrix::I(), dstRect); 493 return true; 494} 495 496bool GrDrawTarget::canCopySurface(const GrSurface* dst, 497 const GrSurface* src, 498 const SkIRect& srcRect, 499 const SkIPoint& dstPoint) { 500 SkASSERT(dst); 501 SkASSERT(src); 502 503 SkIRect clippedSrcRect; 504 SkIPoint clippedDstPoint; 505 // If the rect is outside the src or dst then we're guaranteed success 506 if (!clip_srcrect_and_dstpoint(dst, 507 src, 508 srcRect, 509 dstPoint, 510 &clippedSrcRect, 511 &clippedDstPoint)) { 512 return true; 513 } 514 return ((dst != src) && dst->asRenderTarget() && src->asTexture()) || 515 this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 516} 517 518void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo, 519 GrPipeline* pipeline) { 520 SkNEW_PLACEMENT_ARGS(pipeline, GrPipeline, (*pipelineInfo.fPipelineBuilder, 521 pipelineInfo.fColorPOI, 522 pipelineInfo.fCoveragePOI, 523 *this->caps(), 524 *pipelineInfo.fScissor, 525 &pipelineInfo.fDstCopy)); 526} 527/////////////////////////////////////////////////////////////////////////////// 528 529GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder, 530 GrScissorState* scissor, 531 const GrPrimitiveProcessor* primProc, 532 const SkRect* devBounds, 533 GrDrawTarget* target) 534 : fPipelineBuilder(pipelineBuilder) 535 , fScissor(scissor) { 536 fColorPOI = fPipelineBuilder->colorProcInfo(primProc); 537 fCoveragePOI = fPipelineBuilder->coverageProcInfo(primProc); 538 if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI, 539 &fDstCopy, devBounds)) { 540 fPipelineBuilder = NULL; 541 } 542} 543 544GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder, 545 GrScissorState* scissor, 546 const GrBatch* batch, 547 const SkRect* devBounds, 548 GrDrawTarget* target) 549 : fPipelineBuilder(pipelineBuilder) 550 , fScissor(scissor) { 551 fColorPOI = fPipelineBuilder->colorProcInfo(batch); 552 fCoveragePOI = fPipelineBuilder->coverageProcInfo(batch); 553 if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI, 554 &fDstCopy, devBounds)) { 555 fPipelineBuilder = NULL; 556 } 557} 558 559/////////////////////////////////////////////////////////////////////////////// 560 561void GrShaderCaps::reset() { 562 fShaderDerivativeSupport = false; 563 fGeometryShaderSupport = false; 564 fPathRenderingSupport = false; 565 fDstReadInShaderSupport = false; 566 fDualSourceBlendingSupport = false; 567 568 fShaderPrecisionVaries = false; 569} 570 571GrShaderCaps& GrShaderCaps::operator=(const GrShaderCaps& other) { 572 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 573 fGeometryShaderSupport = other.fGeometryShaderSupport; 574 fPathRenderingSupport = other.fPathRenderingSupport; 575 fDstReadInShaderSupport = other.fDstReadInShaderSupport; 576 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 577 578 fShaderPrecisionVaries = other.fShaderPrecisionVaries; 579 for (int s = 0; s < kGrShaderTypeCount; ++s) { 580 for (int p = 0; p < kGrSLPrecisionCount; ++p) { 581 fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p]; 582 } 583 } 584 return *this; 585} 586 587static const char* shader_type_to_string(GrShaderType type) { 588 switch (type) { 589 case kVertex_GrShaderType: 590 return "vertex"; 591 case kGeometry_GrShaderType: 592 return "geometry"; 593 case kFragment_GrShaderType: 594 return "fragment"; 595 } 596 return ""; 597} 598 599static const char* precision_to_string(GrSLPrecision p) { 600 switch (p) { 601 case kLow_GrSLPrecision: 602 return "low"; 603 case kMedium_GrSLPrecision: 604 return "medium"; 605 case kHigh_GrSLPrecision: 606 return "high"; 607 } 608 return ""; 609} 610 611SkString GrShaderCaps::dump() const { 612 SkString r; 613 static const char* gNY[] = { "NO", "YES" }; 614 r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 615 r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 616 r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); 617 r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 618 r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); 619 620 r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]); 621 622 for (int s = 0; s < kGrShaderTypeCount; ++s) { 623 GrShaderType shaderType = static_cast<GrShaderType>(s); 624 r.appendf("\t%s:\n", shader_type_to_string(shaderType)); 625 for (int p = 0; p < kGrSLPrecisionCount; ++p) { 626 if (fFloatPrecisions[s][p].supported()) { 627 GrSLPrecision precision = static_cast<GrSLPrecision>(p); 628 r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n", 629 precision_to_string(precision), 630 fFloatPrecisions[s][p].fLogRangeLow, 631 fFloatPrecisions[s][p].fLogRangeHigh, 632 fFloatPrecisions[s][p].fBits); 633 } 634 } 635 } 636 637 return r; 638} 639 640/////////////////////////////////////////////////////////////////////////////// 641 642void GrDrawTargetCaps::reset() { 643 fMipMapSupport = false; 644 fNPOTTextureTileSupport = false; 645 fTwoSidedStencilSupport = false; 646 fStencilWrapOpsSupport = false; 647 fDiscardRenderTargetSupport = false; 648 fReuseScratchTextures = true; 649 fGpuTracingSupport = false; 650 fCompressedTexSubImageSupport = false; 651 fOversizedStencilSupport = false; 652 fTextureBarrierSupport = false; 653 654 fUseDrawInsteadOfClear = false; 655 656 fMapBufferFlags = kNone_MapFlags; 657 658 fMaxRenderTargetSize = 0; 659 fMaxTextureSize = 0; 660 fMaxSampleCount = 0; 661 662 memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport)); 663 memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport)); 664} 665 666GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 667 fMipMapSupport = other.fMipMapSupport; 668 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 669 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 670 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 671 fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport; 672 fReuseScratchTextures = other.fReuseScratchTextures; 673 fGpuTracingSupport = other.fGpuTracingSupport; 674 fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport; 675 fOversizedStencilSupport = other.fOversizedStencilSupport; 676 fTextureBarrierSupport = other.fTextureBarrierSupport; 677 678 fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear; 679 680 fMapBufferFlags = other.fMapBufferFlags; 681 682 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 683 fMaxTextureSize = other.fMaxTextureSize; 684 fMaxSampleCount = other.fMaxSampleCount; 685 686 memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport)); 687 memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport)); 688 689 return *this; 690} 691 692static SkString map_flags_to_string(uint32_t flags) { 693 SkString str; 694 if (GrDrawTargetCaps::kNone_MapFlags == flags) { 695 str = "none"; 696 } else { 697 SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags); 698 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag); 699 str = "can_map"; 700 701 if (GrDrawTargetCaps::kSubset_MapFlag & flags) { 702 str.append(" partial"); 703 } else { 704 str.append(" full"); 705 } 706 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag); 707 } 708 SkASSERT(0 == flags); // Make sure we handled all the flags. 709 return str; 710} 711 712SkString GrDrawTargetCaps::dump() const { 713 SkString r; 714 static const char* gNY[] = {"NO", "YES"}; 715 r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); 716 r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 717 r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 718 r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 719 r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); 720 r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 721 r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); 722 r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); 723 r.appendf("Oversized Stencil Support : %s\n", gNY[fOversizedStencilSupport]); 724 r.appendf("Texture Barrier Support : %s\n", gNY[fTextureBarrierSupport]); 725 r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); 726 727 r.appendf("Max Texture Size : %d\n", fMaxTextureSize); 728 r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 729 r.appendf("Max Sample Count : %d\n", fMaxSampleCount); 730 731 r.appendf("Map Buffer Support : %s\n", 732 map_flags_to_string(fMapBufferFlags).c_str()); 733 734 static const char* kConfigNames[] = { 735 "Unknown", // kUnknown_GrPixelConfig 736 "Alpha8", // kAlpha_8_GrPixelConfig, 737 "Index8", // kIndex_8_GrPixelConfig, 738 "RGB565", // kRGB_565_GrPixelConfig, 739 "RGBA444", // kRGBA_4444_GrPixelConfig, 740 "RGBA8888", // kRGBA_8888_GrPixelConfig, 741 "BGRA8888", // kBGRA_8888_GrPixelConfig, 742 "SRGBA8888",// kSRGBA_8888_GrPixelConfig, 743 "ETC1", // kETC1_GrPixelConfig, 744 "LATC", // kLATC_GrPixelConfig, 745 "R11EAC", // kR11_EAC_GrPixelConfig, 746 "ASTC12x12",// kASTC_12x12_GrPixelConfig, 747 "RGBAFloat",// kRGBA_float_GrPixelConfig 748 "AlphaHalf",// kAlpha_half_GrPixelConfig 749 }; 750 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); 751 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); 752 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); 753 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); 754 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); 755 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); 756 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); 757 GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); 758 GR_STATIC_ASSERT(8 == kETC1_GrPixelConfig); 759 GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig); 760 GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig); 761 GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig); 762 GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig); 763 GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig); 764 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); 765 766 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); 767 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); 768 769 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 770 r.appendf("%s is renderable: %s, with MSAA: %s\n", 771 kConfigNames[i], 772 gNY[fConfigRenderSupport[i][0]], 773 gNY[fConfigRenderSupport[i][1]]); 774 } 775 776 SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]); 777 778 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 779 r.appendf("%s is uploadable to a texture: %s\n", 780 kConfigNames[i], 781 gNY[fConfigTextureSupport[i]]); 782 } 783 784 return r; 785} 786 787/////////////////////////////////////////////////////////////////////////////////////////////////// 788 789bool GrClipTarget::setupClip(GrPipelineBuilder* pipelineBuilder, 790 GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp, 791 GrPipelineBuilder::AutoRestoreStencil* ars, 792 GrScissorState* scissorState, 793 const SkRect* devBounds) { 794 return fClipMaskManager.setupClipping(pipelineBuilder, 795 arfp, 796 ars, 797 scissorState, 798 devBounds); 799} 800