GrDrawTarget.cpp revision 6bc1b5fab8554a9cb643277b4867965dd4535cd6
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 "GrRenderTarget.h" 17#include "GrRenderTargetPriv.h" 18#include "GrSurfacePriv.h" 19#include "GrTemplates.h" 20#include "GrTexture.h" 21#include "GrVertexBuffer.h" 22 23#include "SkStrokeRec.h" 24 25//////////////////////////////////////////////////////////////////////////////// 26 27GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) { 28 fPrimitiveType = di.fPrimitiveType; 29 fStartVertex = di.fStartVertex; 30 fStartIndex = di.fStartIndex; 31 fVertexCount = di.fVertexCount; 32 fIndexCount = di.fIndexCount; 33 34 fInstanceCount = di.fInstanceCount; 35 fVerticesPerInstance = di.fVerticesPerInstance; 36 fIndicesPerInstance = di.fIndicesPerInstance; 37 38 if (di.fDevBounds) { 39 SkASSERT(di.fDevBounds == &di.fDevBoundsStorage); 40 fDevBoundsStorage = di.fDevBoundsStorage; 41 fDevBounds = &fDevBoundsStorage; 42 } else { 43 fDevBounds = NULL; 44 } 45 46 this->setVertexBuffer(di.vertexBuffer()); 47 this->setIndexBuffer(di.indexBuffer()); 48 49 return *this; 50} 51 52#ifdef SK_DEBUG 53bool GrDrawTarget::DrawInfo::isInstanced() const { 54 if (fInstanceCount > 0) { 55 SkASSERT(0 == fIndexCount % fIndicesPerInstance); 56 SkASSERT(0 == fVertexCount % fVerticesPerInstance); 57 SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount); 58 SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount); 59 // there is no way to specify a non-zero start index to drawIndexedInstances(). 60 SkASSERT(0 == fStartIndex); 61 return true; 62 } else { 63 SkASSERT(!fVerticesPerInstance); 64 SkASSERT(!fIndicesPerInstance); 65 return false; 66 } 67} 68#endif 69 70void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) { 71 SkASSERT(this->isInstanced()); 72 SkASSERT(instanceOffset + fInstanceCount >= 0); 73 fInstanceCount += instanceOffset; 74 fVertexCount = fVerticesPerInstance * fInstanceCount; 75 fIndexCount = fIndicesPerInstance * fInstanceCount; 76} 77 78void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) { 79 fStartVertex += vertexOffset; 80 SkASSERT(fStartVertex >= 0); 81} 82 83void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) { 84 SkASSERT(this->isIndexed()); 85 fStartIndex += indexOffset; 86 SkASSERT(fStartIndex >= 0); 87} 88 89//////////////////////////////////////////////////////////////////////////////// 90 91#define DEBUG_INVAL_BUFFER 0xdeadcafe 92#define DEBUG_INVAL_START_IDX -1 93 94GrDrawTarget::GrDrawTarget(GrContext* context) 95 : fClip(NULL) 96 , fContext(context) 97 , fGpuTraceMarkerCount(0) { 98 SkASSERT(context); 99 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); 100#ifdef SK_DEBUG 101 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; 102 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 103 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; 104 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 105#endif 106 geoSrc.fVertexSrc = kNone_GeometrySrcType; 107 geoSrc.fIndexSrc = kNone_GeometrySrcType; 108} 109 110GrDrawTarget::~GrDrawTarget() { 111 SkASSERT(1 == fGeoSrcStateStack.count()); 112 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back()); 113 SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc); 114 SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc); 115} 116 117void GrDrawTarget::releaseGeometry() { 118 int popCnt = fGeoSrcStateStack.count() - 1; 119 while (popCnt) { 120 this->popGeometrySource(); 121 --popCnt; 122 } 123 this->resetVertexSource(); 124 this->resetIndexSource(); 125} 126 127void GrDrawTarget::setClip(const GrClipData* clip) { 128 fClip = clip; 129} 130 131const GrClipData* GrDrawTarget::getClip() const { 132 return fClip; 133} 134 135bool GrDrawTarget::reserveVertexSpace(size_t vertexSize, 136 int vertexCount, 137 void** vertices) { 138 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 139 bool acquired = false; 140 if (vertexCount > 0) { 141 SkASSERT(vertices); 142 this->releasePreviousVertexSource(); 143 geoSrc.fVertexSrc = kNone_GeometrySrcType; 144 145 acquired = this->onReserveVertexSpace(vertexSize, 146 vertexCount, 147 vertices); 148 } 149 if (acquired) { 150 geoSrc.fVertexSrc = kReserved_GeometrySrcType; 151 geoSrc.fVertexCount = vertexCount; 152 geoSrc.fVertexSize = vertexSize; 153 } else if (vertices) { 154 *vertices = NULL; 155 } 156 return acquired; 157} 158 159bool GrDrawTarget::reserveIndexSpace(int indexCount, 160 void** indices) { 161 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 162 bool acquired = false; 163 if (indexCount > 0) { 164 SkASSERT(indices); 165 this->releasePreviousIndexSource(); 166 geoSrc.fIndexSrc = kNone_GeometrySrcType; 167 168 acquired = this->onReserveIndexSpace(indexCount, indices); 169 } 170 if (acquired) { 171 geoSrc.fIndexSrc = kReserved_GeometrySrcType; 172 geoSrc.fIndexCount = indexCount; 173 } else if (indices) { 174 *indices = NULL; 175 } 176 return acquired; 177 178} 179 180bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount, 181 size_t vertexStride, 182 int indexCount, 183 void** vertices, 184 void** indices) { 185 this->willReserveVertexAndIndexSpace(vertexCount, vertexStride, indexCount); 186 if (vertexCount) { 187 if (!this->reserveVertexSpace(vertexStride, vertexCount, vertices)) { 188 if (indexCount) { 189 this->resetIndexSource(); 190 } 191 return false; 192 } 193 } 194 if (indexCount) { 195 if (!this->reserveIndexSpace(indexCount, indices)) { 196 if (vertexCount) { 197 this->resetVertexSource(); 198 } 199 return false; 200 } 201 } 202 return true; 203} 204 205bool GrDrawTarget::geometryHints(size_t vertexStride, 206 int32_t* vertexCount, 207 int32_t* indexCount) const { 208 if (vertexCount) { 209 *vertexCount = -1; 210 } 211 if (indexCount) { 212 *indexCount = -1; 213 } 214 return false; 215} 216 217void GrDrawTarget::releasePreviousVertexSource() { 218 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 219 switch (geoSrc.fVertexSrc) { 220 case kNone_GeometrySrcType: 221 break; 222 case kReserved_GeometrySrcType: 223 this->releaseReservedVertexSpace(); 224 break; 225 case kBuffer_GeometrySrcType: 226 geoSrc.fVertexBuffer->unref(); 227#ifdef SK_DEBUG 228 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 229#endif 230 break; 231 default: 232 SkFAIL("Unknown Vertex Source Type."); 233 break; 234 } 235} 236 237void GrDrawTarget::releasePreviousIndexSource() { 238 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 239 switch (geoSrc.fIndexSrc) { 240 case kNone_GeometrySrcType: // these two don't require 241 break; 242 case kReserved_GeometrySrcType: 243 this->releaseReservedIndexSpace(); 244 break; 245 case kBuffer_GeometrySrcType: 246 geoSrc.fIndexBuffer->unref(); 247#ifdef SK_DEBUG 248 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 249#endif 250 break; 251 default: 252 SkFAIL("Unknown Index Source Type."); 253 break; 254 } 255} 256 257void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer, size_t vertexStride) { 258 this->releasePreviousVertexSource(); 259 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 260 geoSrc.fVertexSrc = kBuffer_GeometrySrcType; 261 geoSrc.fVertexBuffer = buffer; 262 buffer->ref(); 263 geoSrc.fVertexSize = vertexStride; 264} 265 266void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { 267 this->releasePreviousIndexSource(); 268 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 269 geoSrc.fIndexSrc = kBuffer_GeometrySrcType; 270 geoSrc.fIndexBuffer = buffer; 271 buffer->ref(); 272} 273 274void GrDrawTarget::resetVertexSource() { 275 this->releasePreviousVertexSource(); 276 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 277 geoSrc.fVertexSrc = kNone_GeometrySrcType; 278} 279 280void GrDrawTarget::resetIndexSource() { 281 this->releasePreviousIndexSource(); 282 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 283 geoSrc.fIndexSrc = kNone_GeometrySrcType; 284} 285 286void GrDrawTarget::pushGeometrySource() { 287 this->geometrySourceWillPush(); 288 GeometrySrcState& newState = fGeoSrcStateStack.push_back(); 289 newState.fIndexSrc = kNone_GeometrySrcType; 290 newState.fVertexSrc = kNone_GeometrySrcType; 291#ifdef SK_DEBUG 292 newState.fVertexCount = ~0; 293 newState.fVertexBuffer = (GrVertexBuffer*)~0; 294 newState.fIndexCount = ~0; 295 newState.fIndexBuffer = (GrIndexBuffer*)~0; 296#endif 297} 298 299void GrDrawTarget::popGeometrySource() { 300 // if popping last element then pops are unbalanced with pushes 301 SkASSERT(fGeoSrcStateStack.count() > 1); 302 303 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); 304 this->releasePreviousVertexSource(); 305 this->releasePreviousIndexSource(); 306 fGeoSrcStateStack.pop_back(); 307} 308 309//////////////////////////////////////////////////////////////////////////////// 310 311bool GrDrawTarget::checkDraw(const GrPipelineBuilder& pipelineBuilder, 312 const GrGeometryProcessor* gp, 313 GrPrimitiveType type, 314 int startVertex, 315 int startIndex, 316 int vertexCount, 317 int indexCount) const { 318#ifdef SK_DEBUG 319 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 320 int maxVertex = startVertex + vertexCount; 321 int maxValidVertex; 322 switch (geoSrc.fVertexSrc) { 323 case kNone_GeometrySrcType: 324 SkFAIL("Attempting to draw without vertex src."); 325 case kReserved_GeometrySrcType: // fallthrough 326 maxValidVertex = geoSrc.fVertexCount; 327 break; 328 case kBuffer_GeometrySrcType: 329 maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->gpuMemorySize() / 330 geoSrc.fVertexSize); 331 break; 332 } 333 if (maxVertex > maxValidVertex) { 334 SkFAIL("Drawing outside valid vertex range."); 335 } 336 if (indexCount > 0) { 337 int maxIndex = startIndex + indexCount; 338 int maxValidIndex; 339 switch (geoSrc.fIndexSrc) { 340 case kNone_GeometrySrcType: 341 SkFAIL("Attempting to draw indexed geom without index src."); 342 case kReserved_GeometrySrcType: // fallthrough 343 maxValidIndex = geoSrc.fIndexCount; 344 break; 345 case kBuffer_GeometrySrcType: 346 maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->gpuMemorySize() / 347 sizeof(uint16_t)); 348 break; 349 } 350 if (maxIndex > maxValidIndex) { 351 SkFAIL("Index reads outside valid index range."); 352 } 353 } 354 355 SkASSERT(pipelineBuilder.getRenderTarget()); 356 357 if (gp) { 358 int numTextures = gp->numTextures(); 359 for (int t = 0; t < numTextures; ++t) { 360 GrTexture* texture = gp->texture(t); 361 SkASSERT(texture->asRenderTarget() != pipelineBuilder.getRenderTarget()); 362 } 363 } 364 365 for (int s = 0; s < pipelineBuilder.numColorStages(); ++s) { 366 const GrProcessor* effect = pipelineBuilder.getColorStage(s).processor(); 367 int numTextures = effect->numTextures(); 368 for (int t = 0; t < numTextures; ++t) { 369 GrTexture* texture = effect->texture(t); 370 SkASSERT(texture->asRenderTarget() != pipelineBuilder.getRenderTarget()); 371 } 372 } 373 for (int s = 0; s < pipelineBuilder.numCoverageStages(); ++s) { 374 const GrProcessor* effect = pipelineBuilder.getCoverageStage(s).processor(); 375 int numTextures = effect->numTextures(); 376 for (int t = 0; t < numTextures; ++t) { 377 GrTexture* texture = effect->texture(t); 378 SkASSERT(texture->asRenderTarget() != pipelineBuilder.getRenderTarget()); 379 } 380 } 381 382#endif 383 if (NULL == pipelineBuilder.getRenderTarget()) { 384 return false; 385 } 386 return true; 387} 388 389bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder, 390 const GrProcOptInfo& colorPOI, 391 const GrProcOptInfo& coveragePOI, 392 GrDeviceCoordTexture* dstCopy, 393 const SkRect* drawBounds) { 394 if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) { 395 return true; 396 } 397 SkIRect copyRect; 398 const GrClipData* clip = this->getClip(); 399 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); 400 clip->getConservativeBounds(rt, ©Rect); 401 402 if (drawBounds) { 403 SkIRect drawIBounds; 404 drawBounds->roundOut(&drawIBounds); 405 if (!copyRect.intersect(drawIBounds)) { 406#ifdef SK_DEBUG 407 SkDebugf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 408#endif 409 return false; 410 } 411 } else { 412#ifdef SK_DEBUG 413 //SkDebugf("No dev bounds when dst copy is made.\n"); 414#endif 415 } 416 417 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 418 // have per-sample dst values by making the copy multisampled. 419 GrSurfaceDesc desc; 420 this->initCopySurfaceDstDesc(rt, &desc); 421 desc.fWidth = copyRect.width(); 422 desc.fHeight = copyRect.height(); 423 424 SkAutoTUnref<GrTexture> copy( 425 fContext->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch)); 426 427 if (!copy) { 428 SkDebugf("Failed to create temporary copy of destination texture.\n"); 429 return false; 430 } 431 SkIPoint dstPoint = {0, 0}; 432 if (this->copySurface(copy, rt, copyRect, dstPoint)) { 433 dstCopy->setTexture(copy); 434 dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); 435 return true; 436 } else { 437 return false; 438 } 439} 440 441void GrDrawTarget::drawIndexed(GrPipelineBuilder* pipelineBuilder, 442 const GrGeometryProcessor* gp, 443 GrPrimitiveType type, 444 int startVertex, 445 int startIndex, 446 int vertexCount, 447 int indexCount, 448 const SkRect* devBounds) { 449 SkASSERT(pipelineBuilder); 450 if (indexCount > 0 && 451 this->checkDraw(*pipelineBuilder, gp, type, startVertex, startIndex, vertexCount, 452 indexCount)) { 453 454 // Setup clip 455 GrScissorState scissorState; 456 GrPipelineBuilder::AutoRestoreEffects are; 457 GrPipelineBuilder::AutoRestoreStencil ars; 458 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, devBounds)) { 459 return; 460 } 461 462 DrawInfo info; 463 info.fPrimitiveType = type; 464 info.fStartVertex = startVertex; 465 info.fStartIndex = startIndex; 466 info.fVertexCount = vertexCount; 467 info.fIndexCount = indexCount; 468 469 info.fInstanceCount = 0; 470 info.fVerticesPerInstance = 0; 471 info.fIndicesPerInstance = 0; 472 473 if (devBounds) { 474 info.setDevBounds(*devBounds); 475 } 476 477 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds, 478 this); 479 if (pipelineInfo.mustSkipDraw()) { 480 return; 481 } 482 483 this->setDrawBuffers(&info, gp->getVertexStride()); 484 485 this->onDraw(gp, info, pipelineInfo); 486 } 487} 488 489void GrDrawTarget::drawNonIndexed(GrPipelineBuilder* pipelineBuilder, 490 const GrGeometryProcessor* gp, 491 GrPrimitiveType type, 492 int startVertex, 493 int vertexCount, 494 const SkRect* devBounds) { 495 SkASSERT(pipelineBuilder); 496 if (vertexCount > 0 && this->checkDraw(*pipelineBuilder, gp, type, startVertex, -1, vertexCount, 497 -1)) { 498 499 // Setup clip 500 GrScissorState scissorState; 501 GrPipelineBuilder::AutoRestoreEffects are; 502 GrPipelineBuilder::AutoRestoreStencil ars; 503 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, devBounds)) { 504 return; 505 } 506 507 DrawInfo info; 508 info.fPrimitiveType = type; 509 info.fStartVertex = startVertex; 510 info.fStartIndex = 0; 511 info.fVertexCount = vertexCount; 512 info.fIndexCount = 0; 513 514 info.fInstanceCount = 0; 515 info.fVerticesPerInstance = 0; 516 info.fIndicesPerInstance = 0; 517 518 if (devBounds) { 519 info.setDevBounds(*devBounds); 520 } 521 522 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds, 523 this); 524 if (pipelineInfo.mustSkipDraw()) { 525 return; 526 } 527 528 this->setDrawBuffers(&info, gp->getVertexStride()); 529 530 this->onDraw(gp, info, pipelineInfo); 531 } 532} 533 534 535void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder, 536 GrBatch* batch, 537 const SkRect* devBounds) { 538 SkASSERT(pipelineBuilder); 539 // TODO some kind of checkdraw, but not at this level 540 541 // Setup clip 542 GrScissorState scissorState; 543 GrPipelineBuilder::AutoRestoreEffects are; 544 GrPipelineBuilder::AutoRestoreStencil ars; 545 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, devBounds)) { 546 return; 547 } 548 549 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, batch, devBounds, this); 550 if (pipelineInfo.mustSkipDraw()) { 551 return; 552 } 553 554 this->onDrawBatch(batch, pipelineInfo); 555} 556 557static const GrStencilSettings& winding_path_stencil_settings() { 558 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 559 kIncClamp_StencilOp, 560 kIncClamp_StencilOp, 561 kAlwaysIfInClip_StencilFunc, 562 0xFFFF, 0xFFFF, 0xFFFF); 563 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 564} 565 566static const GrStencilSettings& even_odd_path_stencil_settings() { 567 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 568 kInvert_StencilOp, 569 kInvert_StencilOp, 570 kAlwaysIfInClip_StencilFunc, 571 0xFFFF, 0xFFFF, 0xFFFF); 572 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 573} 574 575void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill, 576 const GrStencilBuffer* sb, 577 GrStencilSettings* outStencilSettings) { 578 579 switch (fill) { 580 default: 581 SkFAIL("Unexpected path fill."); 582 case GrPathRendering::kWinding_FillType: 583 *outStencilSettings = winding_path_stencil_settings(); 584 break; 585 case GrPathRendering::kEvenOdd_FillType: 586 *outStencilSettings = even_odd_path_stencil_settings(); 587 break; 588 } 589 this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings); 590} 591 592void GrDrawTarget::stencilPath(GrPipelineBuilder* pipelineBuilder, 593 const GrPathProcessor* pathProc, 594 const GrPath* path, 595 GrPathRendering::FillType fill) { 596 // TODO: extract portions of checkDraw that are relevant to path stenciling. 597 SkASSERT(path); 598 SkASSERT(this->caps()->pathRenderingSupport()); 599 SkASSERT(pipelineBuilder); 600 601 // Setup clip 602 GrScissorState scissorState; 603 GrPipelineBuilder::AutoRestoreEffects are; 604 GrPipelineBuilder::AutoRestoreStencil ars; 605 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, NULL)) { 606 return; 607 } 608 609 // set stencil settings for path 610 GrStencilSettings stencilSettings; 611 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 612 GrStencilBuffer* sb = rt->renderTargetPriv().attachStencilBuffer(); 613 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 614 615 this->onStencilPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings); 616} 617 618void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder, 619 const GrPathProcessor* pathProc, 620 const GrPath* path, 621 GrPathRendering::FillType fill) { 622 // TODO: extract portions of checkDraw that are relevant to path rendering. 623 SkASSERT(path); 624 SkASSERT(this->caps()->pathRenderingSupport()); 625 SkASSERT(pipelineBuilder); 626 627 SkRect devBounds = path->getBounds(); 628 pathProc->viewMatrix().mapRect(&devBounds); 629 630 // Setup clip 631 GrScissorState scissorState; 632 GrPipelineBuilder::AutoRestoreEffects are; 633 GrPipelineBuilder::AutoRestoreStencil ars; 634 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, &devBounds)) { 635 return; 636 } 637 638 // set stencil settings for path 639 GrStencilSettings stencilSettings; 640 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 641 GrStencilBuffer* sb = rt->renderTargetPriv().attachStencilBuffer(); 642 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 643 644 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, &devBounds, 645 this); 646 if (pipelineInfo.mustSkipDraw()) { 647 return; 648 } 649 650 this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo); 651} 652 653void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder, 654 const GrPathProcessor* pathProc, 655 const GrPathRange* pathRange, 656 const void* indices, 657 PathIndexType indexType, 658 const float transformValues[], 659 PathTransformType transformType, 660 int count, 661 GrPathRendering::FillType fill) { 662 SkASSERT(this->caps()->pathRenderingSupport()); 663 SkASSERT(pathRange); 664 SkASSERT(indices); 665 SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType)); 666 SkASSERT(transformValues); 667 SkASSERT(pipelineBuilder); 668 669 // Setup clip 670 GrScissorState scissorState; 671 GrPipelineBuilder::AutoRestoreEffects are; 672 GrPipelineBuilder::AutoRestoreStencil ars; 673 674 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, NULL)) { 675 return; 676 } 677 678 // set stencil settings for path 679 GrStencilSettings stencilSettings; 680 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 681 GrStencilBuffer* sb = rt->renderTargetPriv().attachStencilBuffer(); 682 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings); 683 684 // Don't compute a bounding box for dst copy texture, we'll opt 685 // instead for it to just copy the entire dst. Realistically this is a moot 686 // point, because any context that supports NV_path_rendering will also 687 // support NV_blend_equation_advanced. 688 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, NULL, this); 689 if (pipelineInfo.mustSkipDraw()) { 690 return; 691 } 692 693 this->onDrawPaths(pathProc, pathRange, indices, indexType, transformValues, 694 transformType, count, stencilSettings, pipelineInfo); 695} 696 697void GrDrawTarget::clear(const SkIRect* rect, 698 GrColor color, 699 bool canIgnoreRect, 700 GrRenderTarget* renderTarget) { 701 if (fCaps->useDrawInsteadOfClear()) { 702 // This works around a driver bug with clear by drawing a rect instead. 703 // The driver will ignore a clear if it is the only thing rendered to a 704 // target before the target is read. 705 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height()); 706 if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) { 707 rect = &rtRect; 708 // We first issue a discard() since that may help tilers. 709 this->discard(renderTarget); 710 } 711 712 GrPipelineBuilder pipelineBuilder; 713 pipelineBuilder.setRenderTarget(renderTarget); 714 715 this->drawSimpleRect(&pipelineBuilder, color, SkMatrix::I(), *rect); 716 } else { 717 this->onClear(rect, color, canIgnoreRect, renderTarget); 718 } 719} 720 721typedef GrTraceMarkerSet::Iter TMIter; 722void GrDrawTarget::saveActiveTraceMarkers() { 723 if (this->caps()->gpuTracingSupport()) { 724 SkASSERT(0 == fStoredTraceMarkers.count()); 725 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 726 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 727 this->removeGpuTraceMarker(&(*iter)); 728 } 729 } 730} 731 732void GrDrawTarget::restoreActiveTraceMarkers() { 733 if (this->caps()->gpuTracingSupport()) { 734 SkASSERT(0 == fActiveTraceMarkers.count()); 735 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 736 this->addGpuTraceMarker(&(*iter)); 737 } 738 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 739 this->fStoredTraceMarkers.remove(*iter); 740 } 741 } 742} 743 744void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 745 if (this->caps()->gpuTracingSupport()) { 746 SkASSERT(fGpuTraceMarkerCount >= 0); 747 this->fActiveTraceMarkers.add(*marker); 748 ++fGpuTraceMarkerCount; 749 } 750} 751 752void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 753 if (this->caps()->gpuTracingSupport()) { 754 SkASSERT(fGpuTraceMarkerCount >= 1); 755 this->fActiveTraceMarkers.remove(*marker); 756 --fGpuTraceMarkerCount; 757 } 758} 759 760//////////////////////////////////////////////////////////////////////////////// 761 762void GrDrawTarget::drawIndexedInstances(GrPipelineBuilder* pipelineBuilder, 763 const GrGeometryProcessor* gp, 764 GrPrimitiveType type, 765 int instanceCount, 766 int verticesPerInstance, 767 int indicesPerInstance, 768 const SkRect* devBounds) { 769 SkASSERT(pipelineBuilder); 770 771 if (!verticesPerInstance || !indicesPerInstance) { 772 return; 773 } 774 775 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 776 if (!maxInstancesPerDraw) { 777 return; 778 } 779 780 // Setup clip 781 GrScissorState scissorState; 782 GrPipelineBuilder::AutoRestoreEffects are; 783 GrPipelineBuilder::AutoRestoreStencil ars; 784 if (!this->setupClip(pipelineBuilder, &are, &ars, &scissorState, devBounds)) { 785 return; 786 } 787 788 DrawInfo info; 789 info.fPrimitiveType = type; 790 info.fStartIndex = 0; 791 info.fStartVertex = 0; 792 info.fIndicesPerInstance = indicesPerInstance; 793 info.fVerticesPerInstance = verticesPerInstance; 794 795 // Set the same bounds for all the draws. 796 if (devBounds) { 797 info.setDevBounds(*devBounds); 798 } 799 800 while (instanceCount) { 801 info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw); 802 info.fVertexCount = info.fInstanceCount * verticesPerInstance; 803 info.fIndexCount = info.fInstanceCount * indicesPerInstance; 804 805 if (this->checkDraw(*pipelineBuilder, 806 gp, 807 type, 808 info.fStartVertex, 809 info.fStartIndex, 810 info.fVertexCount, 811 info.fIndexCount)) { 812 813 GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds, 814 this); 815 if (pipelineInfo.mustSkipDraw()) { 816 return; 817 } 818 819 this->setDrawBuffers(&info, gp->getVertexStride()); 820 this->onDraw(gp, info, pipelineInfo); 821 } 822 info.fStartVertex += info.fVertexCount; 823 instanceCount -= info.fInstanceCount; 824 } 825} 826 827//////////////////////////////////////////////////////////////////////////////// 828 829GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 830 GrDrawTarget* target, 831 int vertexCount, 832 size_t vertexStride, 833 int indexCount) { 834 fTarget = NULL; 835 this->set(target, vertexCount, vertexStride, indexCount); 836} 837 838GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 839 fTarget = NULL; 840} 841 842GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 843 this->reset(); 844} 845 846bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 847 int vertexCount, 848 size_t vertexStride, 849 int indexCount) { 850 this->reset(); 851 fTarget = target; 852 bool success = true; 853 if (fTarget) { 854 success = target->reserveVertexAndIndexSpace(vertexCount, 855 vertexStride, 856 indexCount, 857 &fVertices, 858 &fIndices); 859 if (!success) { 860 fTarget = NULL; 861 this->reset(); 862 } 863 } 864 SkASSERT(success == SkToBool(fTarget)); 865 return success; 866} 867 868void GrDrawTarget::AutoReleaseGeometry::reset() { 869 if (fTarget) { 870 if (fVertices) { 871 fTarget->resetVertexSource(); 872 } 873 if (fIndices) { 874 fTarget->resetIndexSource(); 875 } 876 fTarget = NULL; 877 } 878 fVertices = NULL; 879 fIndices = NULL; 880} 881 882GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 883 fTarget = target; 884 fClip = fTarget->getClip(); 885 fStack.init(); 886 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 887 fReplacementClip.fClipStack.reset(SkRef(fStack.get())); 888 target->setClip(&fReplacementClip); 889} 890 891namespace { 892// returns true if the read/written rect intersects the src/dst and false if not. 893bool clip_srcrect_and_dstpoint(const GrSurface* dst, 894 const GrSurface* src, 895 const SkIRect& srcRect, 896 const SkIPoint& dstPoint, 897 SkIRect* clippedSrcRect, 898 SkIPoint* clippedDstPoint) { 899 *clippedSrcRect = srcRect; 900 *clippedDstPoint = dstPoint; 901 902 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 903 if (clippedSrcRect->fLeft < 0) { 904 clippedDstPoint->fX -= clippedSrcRect->fLeft; 905 clippedSrcRect->fLeft = 0; 906 } 907 if (clippedDstPoint->fX < 0) { 908 clippedSrcRect->fLeft -= clippedDstPoint->fX; 909 clippedDstPoint->fX = 0; 910 } 911 912 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 913 if (clippedSrcRect->fTop < 0) { 914 clippedDstPoint->fY -= clippedSrcRect->fTop; 915 clippedSrcRect->fTop = 0; 916 } 917 if (clippedDstPoint->fY < 0) { 918 clippedSrcRect->fTop -= clippedDstPoint->fY; 919 clippedDstPoint->fY = 0; 920 } 921 922 // clip the right edge to the src and dst bounds. 923 if (clippedSrcRect->fRight > src->width()) { 924 clippedSrcRect->fRight = src->width(); 925 } 926 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 927 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 928 } 929 930 // clip the bottom edge to the src and dst bounds. 931 if (clippedSrcRect->fBottom > src->height()) { 932 clippedSrcRect->fBottom = src->height(); 933 } 934 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 935 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 936 } 937 938 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 939 // dst bounds. 940 return !clippedSrcRect->isEmpty(); 941} 942} 943 944bool GrDrawTarget::copySurface(GrSurface* dst, 945 GrSurface* src, 946 const SkIRect& srcRect, 947 const SkIPoint& dstPoint) { 948 SkASSERT(dst); 949 SkASSERT(src); 950 951 SkIRect clippedSrcRect; 952 SkIPoint clippedDstPoint; 953 // If the rect is outside the src or dst then we've already succeeded. 954 if (!clip_srcrect_and_dstpoint(dst, 955 src, 956 srcRect, 957 dstPoint, 958 &clippedSrcRect, 959 &clippedDstPoint)) { 960 return true; 961 } 962 963 if (this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint)) { 964 return true; 965 } 966 967 GrRenderTarget* rt = dst->asRenderTarget(); 968 GrTexture* tex = src->asTexture(); 969 970 if ((dst == src) || !rt || !tex) { 971 return false; 972 } 973 974 GrPipelineBuilder pipelineBuilder; 975 pipelineBuilder.setRenderTarget(rt); 976 SkMatrix matrix; 977 matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX), 978 SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY)); 979 matrix.postIDiv(tex->width(), tex->height()); 980 pipelineBuilder.addColorTextureProcessor(tex, matrix); 981 SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX, 982 clippedDstPoint.fY, 983 clippedSrcRect.width(), 984 clippedSrcRect.height()); 985 this->drawSimpleRect(&pipelineBuilder, GrColor_WHITE, SkMatrix::I(), dstRect); 986 return true; 987} 988 989bool GrDrawTarget::canCopySurface(const GrSurface* dst, 990 const GrSurface* src, 991 const SkIRect& srcRect, 992 const SkIPoint& dstPoint) { 993 SkASSERT(dst); 994 SkASSERT(src); 995 996 SkIRect clippedSrcRect; 997 SkIPoint clippedDstPoint; 998 // If the rect is outside the src or dst then we're guaranteed success 999 if (!clip_srcrect_and_dstpoint(dst, 1000 src, 1001 srcRect, 1002 dstPoint, 1003 &clippedSrcRect, 1004 &clippedDstPoint)) { 1005 return true; 1006 } 1007 return this->internalCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 1008} 1009 1010bool GrDrawTarget::internalCanCopySurface(const GrSurface* dst, 1011 const GrSurface* src, 1012 const SkIRect& clippedSrcRect, 1013 const SkIPoint& clippedDstPoint) { 1014 // Check that the read/write rects are contained within the src/dst bounds. 1015 SkASSERT(!clippedSrcRect.isEmpty()); 1016 SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(clippedSrcRect)); 1017 SkASSERT(clippedDstPoint.fX >= 0 && clippedDstPoint.fY >= 0); 1018 SkASSERT(clippedDstPoint.fX + clippedSrcRect.width() <= dst->width() && 1019 clippedDstPoint.fY + clippedSrcRect.height() <= dst->height()); 1020 1021 // The base class can do it as a draw or the subclass may be able to handle it. 1022 return ((dst != src) && dst->asRenderTarget() && src->asTexture()) || 1023 this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 1024} 1025 1026void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo, 1027 GrPipeline* pipeline) { 1028 SkNEW_PLACEMENT_ARGS(pipeline, GrPipeline, (*pipelineInfo.fPipelineBuilder, 1029 pipelineInfo.fColorPOI, 1030 pipelineInfo.fCoveragePOI, 1031 *this->caps(), 1032 *pipelineInfo.fScissor, 1033 &pipelineInfo.fDstCopy)); 1034} 1035/////////////////////////////////////////////////////////////////////////////// 1036 1037GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder, 1038 GrScissorState* scissor, 1039 const GrPrimitiveProcessor* primProc, 1040 const SkRect* devBounds, 1041 GrDrawTarget* target) 1042 : fPipelineBuilder(pipelineBuilder) 1043 , fScissor(scissor) { 1044 fColorPOI = fPipelineBuilder->colorProcInfo(primProc); 1045 fCoveragePOI = fPipelineBuilder->coverageProcInfo(primProc); 1046 if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI, 1047 &fDstCopy, devBounds)) { 1048 fPipelineBuilder = NULL; 1049 } 1050} 1051 1052GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder, 1053 GrScissorState* scissor, 1054 const GrBatch* batch, 1055 const SkRect* devBounds, 1056 GrDrawTarget* target) 1057 : fPipelineBuilder(pipelineBuilder) 1058 , fScissor(scissor) { 1059 fColorPOI = fPipelineBuilder->colorProcInfo(batch); 1060 fCoveragePOI = fPipelineBuilder->coverageProcInfo(batch); 1061 if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI, 1062 &fDstCopy, devBounds)) { 1063 fPipelineBuilder = NULL; 1064 } 1065} 1066 1067/////////////////////////////////////////////////////////////////////////////// 1068 1069void GrDrawTargetCaps::reset() { 1070 fMipMapSupport = false; 1071 fNPOTTextureTileSupport = false; 1072 fTwoSidedStencilSupport = false; 1073 fStencilWrapOpsSupport = false; 1074 fHWAALineSupport = false; 1075 fShaderDerivativeSupport = false; 1076 fGeometryShaderSupport = false; 1077 fDualSourceBlendingSupport = false; 1078 fPathRenderingSupport = false; 1079 fDstReadInShaderSupport = false; 1080 fDiscardRenderTargetSupport = false; 1081 fReuseScratchTextures = true; 1082 fGpuTracingSupport = false; 1083 fCompressedTexSubImageSupport = false; 1084 fOversizedStencilSupport = false; 1085 1086 fUseDrawInsteadOfClear = false; 1087 1088 fMapBufferFlags = kNone_MapFlags; 1089 1090 fMaxRenderTargetSize = 0; 1091 fMaxTextureSize = 0; 1092 fMaxSampleCount = 0; 1093 1094 fShaderPrecisionVaries = false; 1095 1096 memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport)); 1097 memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport)); 1098} 1099 1100GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 1101 fMipMapSupport = other.fMipMapSupport; 1102 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 1103 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 1104 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 1105 fHWAALineSupport = other.fHWAALineSupport; 1106 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 1107 fGeometryShaderSupport = other.fGeometryShaderSupport; 1108 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 1109 fPathRenderingSupport = other.fPathRenderingSupport; 1110 fDstReadInShaderSupport = other.fDstReadInShaderSupport; 1111 fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport; 1112 fReuseScratchTextures = other.fReuseScratchTextures; 1113 fGpuTracingSupport = other.fGpuTracingSupport; 1114 fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport; 1115 fOversizedStencilSupport = other.fOversizedStencilSupport; 1116 1117 fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear; 1118 1119 fMapBufferFlags = other.fMapBufferFlags; 1120 1121 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 1122 fMaxTextureSize = other.fMaxTextureSize; 1123 fMaxSampleCount = other.fMaxSampleCount; 1124 1125 memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport)); 1126 memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport)); 1127 1128 fShaderPrecisionVaries = other.fShaderPrecisionVaries; 1129 for (int s = 0; s < kGrShaderTypeCount; ++s) { 1130 for (int p = 0; p < kGrSLPrecisionCount; ++p) { 1131 fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p]; 1132 } 1133 } 1134 return *this; 1135} 1136 1137static SkString map_flags_to_string(uint32_t flags) { 1138 SkString str; 1139 if (GrDrawTargetCaps::kNone_MapFlags == flags) { 1140 str = "none"; 1141 } else { 1142 SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags); 1143 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag); 1144 str = "can_map"; 1145 1146 if (GrDrawTargetCaps::kSubset_MapFlag & flags) { 1147 str.append(" partial"); 1148 } else { 1149 str.append(" full"); 1150 } 1151 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag); 1152 } 1153 SkASSERT(0 == flags); // Make sure we handled all the flags. 1154 return str; 1155} 1156 1157static const char* shader_type_to_string(GrShaderType type) { 1158 switch (type) { 1159 case kVertex_GrShaderType: 1160 return "vertex"; 1161 case kGeometry_GrShaderType: 1162 return "geometry"; 1163 case kFragment_GrShaderType: 1164 return "fragment"; 1165 } 1166 return ""; 1167} 1168 1169static const char* precision_to_string(GrSLPrecision p) { 1170 switch (p) { 1171 case kLow_GrSLPrecision: 1172 return "low"; 1173 case kMedium_GrSLPrecision: 1174 return "medium"; 1175 case kHigh_GrSLPrecision: 1176 return "high"; 1177 } 1178 return ""; 1179} 1180 1181SkString GrDrawTargetCaps::dump() const { 1182 SkString r; 1183 static const char* gNY[] = {"NO", "YES"}; 1184 r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); 1185 r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 1186 r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 1187 r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 1188 r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 1189 r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 1190 r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 1191 r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); 1192 r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); 1193 r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 1194 r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); 1195 r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 1196 r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); 1197 r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); 1198 r.appendf("Oversized Stencil Support : %s\n", gNY[fOversizedStencilSupport]); 1199 r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); 1200 1201 r.appendf("Max Texture Size : %d\n", fMaxTextureSize); 1202 r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 1203 r.appendf("Max Sample Count : %d\n", fMaxSampleCount); 1204 1205 r.appendf("Map Buffer Support : %s\n", 1206 map_flags_to_string(fMapBufferFlags).c_str()); 1207 1208 static const char* kConfigNames[] = { 1209 "Unknown", // kUnknown_GrPixelConfig 1210 "Alpha8", // kAlpha_8_GrPixelConfig, 1211 "Index8", // kIndex_8_GrPixelConfig, 1212 "RGB565", // kRGB_565_GrPixelConfig, 1213 "RGBA444", // kRGBA_4444_GrPixelConfig, 1214 "RGBA8888", // kRGBA_8888_GrPixelConfig, 1215 "BGRA8888", // kBGRA_8888_GrPixelConfig, 1216 "SRGBA8888",// kSRGBA_8888_GrPixelConfig, 1217 "ETC1", // kETC1_GrPixelConfig, 1218 "LATC", // kLATC_GrPixelConfig, 1219 "R11EAC", // kR11_EAC_GrPixelConfig, 1220 "ASTC12x12",// kASTC_12x12_GrPixelConfig, 1221 "RGBAFloat",// kRGBA_float_GrPixelConfig 1222 "AlphaHalf",// kAlpha_half_GrPixelConfig 1223 }; 1224 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); 1225 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); 1226 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); 1227 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); 1228 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); 1229 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); 1230 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); 1231 GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); 1232 GR_STATIC_ASSERT(8 == kETC1_GrPixelConfig); 1233 GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig); 1234 GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig); 1235 GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig); 1236 GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig); 1237 GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig); 1238 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); 1239 1240 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); 1241 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); 1242 1243 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1244 r.appendf("%s is renderable: %s, with MSAA: %s\n", 1245 kConfigNames[i], 1246 gNY[fConfigRenderSupport[i][0]], 1247 gNY[fConfigRenderSupport[i][1]]); 1248 } 1249 1250 SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]); 1251 1252 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1253 r.appendf("%s is uploadable to a texture: %s\n", 1254 kConfigNames[i], 1255 gNY[fConfigTextureSupport[i]]); 1256 } 1257 1258 r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]); 1259 1260 for (int s = 0; s < kGrShaderTypeCount; ++s) { 1261 GrShaderType shaderType = static_cast<GrShaderType>(s); 1262 r.appendf("\t%s:\n", shader_type_to_string(shaderType)); 1263 for (int p = 0; p < kGrSLPrecisionCount; ++p) { 1264 if (fFloatPrecisions[s][p].supported()) { 1265 GrSLPrecision precision = static_cast<GrSLPrecision>(p); 1266 r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n", 1267 precision_to_string(precision), 1268 fFloatPrecisions[s][p].fLogRangeLow, 1269 fFloatPrecisions[s][p].fLogRangeHigh, 1270 fFloatPrecisions[s][p].fBits); 1271 } 1272 } 1273 } 1274 1275 return r; 1276} 1277 1278uint32_t GrDrawTargetCaps::CreateUniqueID() { 1279 static int32_t gUniqueID = SK_InvalidUniqueID; 1280 uint32_t id; 1281 do { 1282 id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1); 1283 } while (id == SK_InvalidUniqueID); 1284 return id; 1285} 1286 1287/////////////////////////////////////////////////////////////////////////////////////////////////// 1288 1289bool GrClipTarget::setupClip(GrPipelineBuilder* pipelineBuilder, 1290 GrPipelineBuilder::AutoRestoreEffects* are, 1291 GrPipelineBuilder::AutoRestoreStencil* ars, 1292 GrScissorState* scissorState, 1293 const SkRect* devBounds) { 1294 return fClipMaskManager.setupClipping(pipelineBuilder, 1295 are, 1296 ars, 1297 scissorState, 1298 this->getClip(), 1299 devBounds); 1300} 1301