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