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