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