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