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