GrDrawTarget.cpp revision 5b3e890c376f2211218c43edd11939cfc78fd60a
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 10 11#include "GrDrawTarget.h" 12#include "GrGpuVertex.h" 13#include "GrIndexBuffer.h" 14#include "GrRenderTarget.h" 15#include "GrTexture.h" 16#include "GrVertexBuffer.h" 17 18SK_DEFINE_INST_COUNT(GrDrawTarget) 19 20namespace { 21 22/** 23 * This function generates some masks that we like to have known at compile 24 * time. When the number of stages or tex coords is bumped or the way bits 25 * are defined in GrDrawTarget.h changes this function should be rerun to 26 * generate the new masks. (We attempted to force the compiler to generate the 27 * masks using recursive templates but always wound up with static initializers 28 * under gcc, even if they were just a series of immediate->memory moves.) 29 * 30 */ 31void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks, 32 GrVertexLayout* texCoordMasks) { 33 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 34 stageTexCoordMasks[s] = 0; 35 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 36 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t); 37 } 38 } 39 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 40 texCoordMasks[t] = 0; 41 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 42 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t); 43 } 44 } 45} 46 47/** 48 * Run this function to generate the code that declares the global masks. 49 */ 50void gen_globals() { 51 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages]; 52 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords]; 53 gen_mask_arrays(stageTexCoordMasks, texCoordMasks); 54 55 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n"); 56 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 57 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]); 58 } 59 GrPrintf("};\n"); 60 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n"); 61 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n"); 62 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 63 GrPrintf(" 0x%x,\n", texCoordMasks[t]); 64 } 65 GrPrintf("};\n"); 66 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n"); 67} 68 69/* These values were generated by the above function */ 70 71const GrVertexLayout gStageTexCoordMasks[] = { 72 0x108421, 73 0x210842, 74 0x421084, 75 0x842108, 76 0x1084210, 77}; 78GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks)); 79 80const GrVertexLayout gTexCoordMasks[] = { 81 0x1f, 82 0x3e0, 83 0x7c00, 84 0xf8000, 85 0x1f00000, 86}; 87GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks)); 88 89bool check_layout(GrVertexLayout layout) { 90 // can only have 1 or 0 bits set for each stage. 91 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 92 int stageBits = layout & gStageTexCoordMasks[s]; 93 if (stageBits && !GrIsPow2(stageBits)) { 94 return false; 95 } 96 } 97 return true; 98} 99 100int num_tex_coords(GrVertexLayout layout) { 101 int cnt = 0; 102 // figure out how many tex coordinates are present 103 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 104 if (gTexCoordMasks[t] & layout) { 105 ++cnt; 106 } 107 } 108 return cnt; 109} 110 111} //unnamed namespace 112 113size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) { 114 GrAssert(check_layout(vertexLayout)); 115 116 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 117 sizeof(GrGpuTextVertex) : 118 sizeof(GrPoint); 119 120 size_t size = vecSize; // position 121 size += num_tex_coords(vertexLayout) * vecSize; 122 if (vertexLayout & kColor_VertexLayoutBit) { 123 size += sizeof(GrColor); 124 } 125 if (vertexLayout & kCoverage_VertexLayoutBit) { 126 size += sizeof(GrColor); 127 } 128 if (vertexLayout & kEdge_VertexLayoutBit) { 129 size += 4 * sizeof(GrScalar); 130 } 131 return size; 132} 133 134//////////////////////////////////////////////////////////////////////////////// 135 136/** 137 * Functions for computing offsets of various components from the layout 138 * bitfield. 139 * 140 * Order of vertex components: 141 * Position 142 * Tex Coord 0 143 * ... 144 * Tex Coord GrDrawState::kMaxTexCoords-1 145 * Color 146 * Coverage 147 */ 148 149int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) { 150 GrAssert(check_layout(vertexLayout)); 151 152 if (!StageUsesTexCoords(vertexLayout, stage)) { 153 return 0; 154 } 155 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout); 156 if (tcIdx >= 0) { 157 158 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 159 sizeof(GrGpuTextVertex) : 160 sizeof(GrPoint); 161 int offset = vecSize; // position 162 // figure out how many tex coordinates are present and precede this one. 163 for (int t = 0; t < tcIdx; ++t) { 164 if (gTexCoordMasks[t] & vertexLayout) { 165 offset += vecSize; 166 } 167 } 168 return offset; 169 } 170 171 return -1; 172} 173 174int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) { 175 GrAssert(check_layout(vertexLayout)); 176 177 if (vertexLayout & kColor_VertexLayoutBit) { 178 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 179 sizeof(GrGpuTextVertex) : 180 sizeof(GrPoint); 181 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos 182 } 183 return -1; 184} 185 186int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) { 187 GrAssert(check_layout(vertexLayout)); 188 189 if (vertexLayout & kCoverage_VertexLayoutBit) { 190 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 191 sizeof(GrGpuTextVertex) : 192 sizeof(GrPoint); 193 194 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); 195 if (vertexLayout & kColor_VertexLayoutBit) { 196 offset += sizeof(GrColor); 197 } 198 return offset; 199 } 200 return -1; 201} 202 203int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) { 204 GrAssert(check_layout(vertexLayout)); 205 206 // edge pts are after the pos, tex coords, and color 207 if (vertexLayout & kEdge_VertexLayoutBit) { 208 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 209 sizeof(GrGpuTextVertex) : 210 sizeof(GrPoint); 211 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos 212 if (vertexLayout & kColor_VertexLayoutBit) { 213 offset += sizeof(GrColor); 214 } 215 if (vertexLayout & kCoverage_VertexLayoutBit) { 216 offset += sizeof(GrColor); 217 } 218 return offset; 219 } 220 return -1; 221} 222 223int GrDrawTarget::VertexSizeAndOffsetsByIdx( 224 GrVertexLayout vertexLayout, 225 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords], 226 int* colorOffset, 227 int* coverageOffset, 228 int* edgeOffset) { 229 GrAssert(check_layout(vertexLayout)); 230 231 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? 232 sizeof(GrGpuTextVertex) : 233 sizeof(GrPoint); 234 int size = vecSize; // position 235 236 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 237 if (gTexCoordMasks[t] & vertexLayout) { 238 if (NULL != texCoordOffsetsByIdx) { 239 texCoordOffsetsByIdx[t] = size; 240 } 241 size += vecSize; 242 } else { 243 if (NULL != texCoordOffsetsByIdx) { 244 texCoordOffsetsByIdx[t] = -1; 245 } 246 } 247 } 248 if (kColor_VertexLayoutBit & vertexLayout) { 249 if (NULL != colorOffset) { 250 *colorOffset = size; 251 } 252 size += sizeof(GrColor); 253 } else { 254 if (NULL != colorOffset) { 255 *colorOffset = -1; 256 } 257 } 258 if (kCoverage_VertexLayoutBit & vertexLayout) { 259 if (NULL != coverageOffset) { 260 *coverageOffset = size; 261 } 262 size += sizeof(GrColor); 263 } else { 264 if (NULL != coverageOffset) { 265 *coverageOffset = -1; 266 } 267 } 268 if (kEdge_VertexLayoutBit & vertexLayout) { 269 if (NULL != edgeOffset) { 270 *edgeOffset = size; 271 } 272 size += 4 * sizeof(GrScalar); 273 } else { 274 if (NULL != edgeOffset) { 275 *edgeOffset = -1; 276 } 277 } 278 return size; 279} 280 281int GrDrawTarget::VertexSizeAndOffsetsByStage( 282 GrVertexLayout vertexLayout, 283 int texCoordOffsetsByStage[GrDrawState::kNumStages], 284 int* colorOffset, 285 int* coverageOffset, 286 int* edgeOffset) { 287 GrAssert(check_layout(vertexLayout)); 288 289 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords]; 290 int size = VertexSizeAndOffsetsByIdx(vertexLayout, 291 (NULL == texCoordOffsetsByStage) ? 292 NULL : 293 texCoordOffsetsByIdx, 294 colorOffset, 295 coverageOffset, 296 edgeOffset); 297 if (NULL != texCoordOffsetsByStage) { 298 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 299 int tcIdx = VertexTexCoordsForStage(s, vertexLayout); 300 texCoordOffsetsByStage[s] = 301 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx]; 302 } 303 } 304 return size; 305} 306 307//////////////////////////////////////////////////////////////////////////////// 308 309bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex, 310 GrVertexLayout vertexLayout) { 311 GrAssert(coordIndex < GrDrawState::kMaxTexCoords); 312 GrAssert(check_layout(vertexLayout)); 313 return !!(gTexCoordMasks[coordIndex] & vertexLayout); 314} 315 316int GrDrawTarget::VertexTexCoordsForStage(int stage, 317 GrVertexLayout vertexLayout) { 318 GrAssert(stage < GrDrawState::kNumStages); 319 GrAssert(check_layout(vertexLayout)); 320 int bit = vertexLayout & gStageTexCoordMasks[stage]; 321 if (bit) { 322 // figure out which set of texture coordates is used 323 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ... 324 // and start at bit 0. 325 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t)); 326 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages; 327 } 328 return -1; 329} 330 331//////////////////////////////////////////////////////////////////////////////// 332 333void GrDrawTarget::VertexLayoutUnitTest() { 334 // Ensure that our globals mask arrays are correct 335 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages]; 336 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords]; 337 gen_mask_arrays(stageTexCoordMasks, texCoordMasks); 338 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 339 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]); 340 } 341 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 342 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]); 343 } 344 345 // not necessarily exhaustive 346 static bool run; 347 if (!run) { 348 run = true; 349 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 350 351 GrVertexLayout stageMask = 0; 352 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 353 stageMask |= StageTexCoordVertexLayoutBit(s,t); 354 } 355 GrAssert(1 == GrDrawState::kMaxTexCoords || 356 !check_layout(stageMask)); 357 GrAssert(gStageTexCoordMasks[s] == stageMask); 358 GrAssert(!check_layout(stageMask)); 359 } 360 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 361 GrVertexLayout tcMask = 0; 362 GrAssert(!VertexUsesTexCoordIdx(t, 0)); 363 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 364 tcMask |= StageTexCoordVertexLayoutBit(s,t); 365 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); 366 GrAssert(VertexUsesTexCoordIdx(t, tcMask)); 367 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); 368 GrAssert(t == VertexTexCoordsForStage(s, tcMask)); 369 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) { 370 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask)); 371 372 #if GR_DEBUG 373 GrVertexLayout posAsTex = tcMask; 374 #endif 375 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex)); 376 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex)); 377 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex)); 378 GrAssert(-1 == VertexEdgeOffset(posAsTex)); 379 } 380 GrAssert(-1 == VertexEdgeOffset(tcMask)); 381 GrAssert(-1 == VertexColorOffset(tcMask)); 382 GrAssert(-1 == VertexCoverageOffset(tcMask)); 383 #if GR_DEBUG 384 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit; 385 #endif 386 GrAssert(-1 == VertexCoverageOffset(withColor)); 387 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor)); 388 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor)); 389 #if GR_DEBUG 390 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit; 391 #endif 392 GrAssert(-1 == VertexColorOffset(withEdge)); 393 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge)); 394 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge)); 395 #if GR_DEBUG 396 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit; 397 #endif 398 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge)); 399 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge)); 400 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge)); 401 #if GR_DEBUG 402 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit; 403 #endif 404 GrAssert(-1 == VertexColorOffset(withCoverage)); 405 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage)); 406 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage)); 407 #if GR_DEBUG 408 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit | 409 kColor_VertexLayoutBit; 410 #endif 411 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor)); 412 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor)); 413 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor)); 414 } 415 GrAssert(gTexCoordMasks[t] == tcMask); 416 GrAssert(check_layout(tcMask)); 417 418 int stageOffsets[GrDrawState::kNumStages]; 419 int colorOffset; 420 int edgeOffset; 421 int coverageOffset; 422 int size; 423 size = VertexSizeAndOffsetsByStage(tcMask, 424 stageOffsets, &colorOffset, 425 &coverageOffset, &edgeOffset); 426 GrAssert(2*sizeof(GrPoint) == size); 427 GrAssert(-1 == colorOffset); 428 GrAssert(-1 == coverageOffset); 429 GrAssert(-1 == edgeOffset); 430 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 431 GrAssert(sizeof(GrPoint) == stageOffsets[s]); 432 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); 433 } 434 } 435 } 436} 437 438//////////////////////////////////////////////////////////////////////////////// 439 440#define DEBUG_INVAL_BUFFER 0xdeadcafe 441#define DEBUG_INVAL_START_IDX -1 442 443GrDrawTarget::GrDrawTarget() : fClip(NULL) { 444#if GR_DEBUG 445 VertexLayoutUnitTest(); 446#endif 447 fDrawState = &fDefaultDrawState; 448 // We assume that fDrawState always owns a ref to the object it points at. 449 fDefaultDrawState.ref(); 450 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); 451#if GR_DEBUG 452 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; 453 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 454 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; 455 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 456#endif 457 geoSrc.fVertexSrc = kNone_GeometrySrcType; 458 geoSrc.fIndexSrc = kNone_GeometrySrcType; 459} 460 461GrDrawTarget::~GrDrawTarget() { 462 GrAssert(1 == fGeoSrcStateStack.count()); 463 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 464 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc); 465 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc); 466 fDrawState->unref(); 467} 468 469void GrDrawTarget::releaseGeometry() { 470 int popCnt = fGeoSrcStateStack.count() - 1; 471 while (popCnt) { 472 this->popGeometrySource(); 473 --popCnt; 474 } 475 this->resetVertexSource(); 476 this->resetIndexSource(); 477} 478 479void GrDrawTarget::setClip(const GrClipData* clip) { 480 clipWillBeSet(clip); 481 fClip = clip; 482} 483 484const GrClipData* GrDrawTarget::getClip() const { 485 return fClip; 486} 487 488void GrDrawTarget::setDrawState(GrDrawState* drawState) { 489 GrAssert(NULL != fDrawState); 490 if (NULL == drawState) { 491 drawState = &fDefaultDrawState; 492 } 493 if (fDrawState != drawState) { 494 fDrawState->unref(); 495 drawState->ref(); 496 fDrawState = drawState; 497 } 498} 499 500bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout, 501 int vertexCount, 502 void** vertices) { 503 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 504 bool acquired = false; 505 if (vertexCount > 0) { 506 GrAssert(NULL != vertices); 507 this->releasePreviousVertexSource(); 508 geoSrc.fVertexSrc = kNone_GeometrySrcType; 509 510 acquired = this->onReserveVertexSpace(vertexLayout, 511 vertexCount, 512 vertices); 513 } 514 if (acquired) { 515 geoSrc.fVertexSrc = kReserved_GeometrySrcType; 516 geoSrc.fVertexCount = vertexCount; 517 geoSrc.fVertexLayout = vertexLayout; 518 } else if (NULL != vertices) { 519 *vertices = NULL; 520 } 521 return acquired; 522} 523 524bool GrDrawTarget::reserveIndexSpace(int indexCount, 525 void** indices) { 526 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 527 bool acquired = false; 528 if (indexCount > 0) { 529 GrAssert(NULL != indices); 530 this->releasePreviousIndexSource(); 531 geoSrc.fIndexSrc = kNone_GeometrySrcType; 532 533 acquired = this->onReserveIndexSpace(indexCount, indices); 534 } 535 if (acquired) { 536 geoSrc.fIndexSrc = kReserved_GeometrySrcType; 537 geoSrc.fIndexCount = indexCount; 538 } else if (NULL != indices) { 539 *indices = NULL; 540 } 541 return acquired; 542 543} 544 545bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) { 546 return SkToBool(layout & gStageTexCoordMasks[stage]); 547} 548 549bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout, 550 int vertexCount, 551 int indexCount, 552 void** vertices, 553 void** indices) { 554 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount); 555 if (vertexCount) { 556 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) { 557 if (indexCount) { 558 this->resetIndexSource(); 559 } 560 return false; 561 } 562 } 563 if (indexCount) { 564 if (!this->reserveIndexSpace(indexCount, indices)) { 565 if (vertexCount) { 566 this->resetVertexSource(); 567 } 568 return false; 569 } 570 } 571 return true; 572} 573 574bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout, 575 int32_t* vertexCount, 576 int32_t* indexCount) const { 577 if (NULL != vertexCount) { 578 *vertexCount = -1; 579 } 580 if (NULL != indexCount) { 581 *indexCount = -1; 582 } 583 return false; 584} 585 586void GrDrawTarget::releasePreviousVertexSource() { 587 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 588 switch (geoSrc.fVertexSrc) { 589 case kNone_GeometrySrcType: 590 break; 591 case kArray_GeometrySrcType: 592 this->releaseVertexArray(); 593 break; 594 case kReserved_GeometrySrcType: 595 this->releaseReservedVertexSpace(); 596 break; 597 case kBuffer_GeometrySrcType: 598 geoSrc.fVertexBuffer->unref(); 599#if GR_DEBUG 600 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 601#endif 602 break; 603 default: 604 GrCrash("Unknown Vertex Source Type."); 605 break; 606 } 607} 608 609void GrDrawTarget::releasePreviousIndexSource() { 610 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 611 switch (geoSrc.fIndexSrc) { 612 case kNone_GeometrySrcType: // these two don't require 613 break; 614 case kArray_GeometrySrcType: 615 this->releaseIndexArray(); 616 break; 617 case kReserved_GeometrySrcType: 618 this->releaseReservedIndexSpace(); 619 break; 620 case kBuffer_GeometrySrcType: 621 geoSrc.fIndexBuffer->unref(); 622#if GR_DEBUG 623 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 624#endif 625 break; 626 default: 627 GrCrash("Unknown Index Source Type."); 628 break; 629 } 630} 631 632void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout, 633 const void* vertexArray, 634 int vertexCount) { 635 this->releasePreviousVertexSource(); 636 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 637 geoSrc.fVertexSrc = kArray_GeometrySrcType; 638 geoSrc.fVertexLayout = vertexLayout; 639 geoSrc.fVertexCount = vertexCount; 640 this->onSetVertexSourceToArray(vertexArray, vertexCount); 641} 642 643void GrDrawTarget::setIndexSourceToArray(const void* indexArray, 644 int indexCount) { 645 this->releasePreviousIndexSource(); 646 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 647 geoSrc.fIndexSrc = kArray_GeometrySrcType; 648 geoSrc.fIndexCount = indexCount; 649 this->onSetIndexSourceToArray(indexArray, indexCount); 650} 651 652void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout, 653 const GrVertexBuffer* buffer) { 654 this->releasePreviousVertexSource(); 655 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 656 geoSrc.fVertexSrc = kBuffer_GeometrySrcType; 657 geoSrc.fVertexBuffer = buffer; 658 buffer->ref(); 659 geoSrc.fVertexLayout = vertexLayout; 660} 661 662void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { 663 this->releasePreviousIndexSource(); 664 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 665 geoSrc.fIndexSrc = kBuffer_GeometrySrcType; 666 geoSrc.fIndexBuffer = buffer; 667 buffer->ref(); 668} 669 670void GrDrawTarget::resetVertexSource() { 671 this->releasePreviousVertexSource(); 672 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 673 geoSrc.fVertexSrc = kNone_GeometrySrcType; 674} 675 676void GrDrawTarget::resetIndexSource() { 677 this->releasePreviousIndexSource(); 678 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 679 geoSrc.fIndexSrc = kNone_GeometrySrcType; 680} 681 682void GrDrawTarget::pushGeometrySource() { 683 this->geometrySourceWillPush(); 684 GeometrySrcState& newState = fGeoSrcStateStack.push_back(); 685 newState.fIndexSrc = kNone_GeometrySrcType; 686 newState.fVertexSrc = kNone_GeometrySrcType; 687#if GR_DEBUG 688 newState.fVertexCount = ~0; 689 newState.fVertexBuffer = (GrVertexBuffer*)~0; 690 newState.fIndexCount = ~0; 691 newState.fIndexBuffer = (GrIndexBuffer*)~0; 692#endif 693} 694 695void GrDrawTarget::popGeometrySource() { 696 // if popping last element then pops are unbalanced with pushes 697 GrAssert(fGeoSrcStateStack.count() > 1); 698 699 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); 700 this->releasePreviousVertexSource(); 701 this->releasePreviousIndexSource(); 702 fGeoSrcStateStack.pop_back(); 703} 704 705//////////////////////////////////////////////////////////////////////////////// 706 707bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, 708 int startIndex, int vertexCount, 709 int indexCount) const { 710 const GrDrawState& drawState = this->getDrawState(); 711#if GR_DEBUG 712 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 713 int maxVertex = startVertex + vertexCount; 714 int maxValidVertex; 715 switch (geoSrc.fVertexSrc) { 716 case kNone_GeometrySrcType: 717 GrCrash("Attempting to draw without vertex src."); 718 case kReserved_GeometrySrcType: // fallthrough 719 case kArray_GeometrySrcType: 720 maxValidVertex = geoSrc.fVertexCount; 721 break; 722 case kBuffer_GeometrySrcType: 723 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout); 724 break; 725 } 726 if (maxVertex > maxValidVertex) { 727 GrCrash("Drawing outside valid vertex range."); 728 } 729 if (indexCount > 0) { 730 int maxIndex = startIndex + indexCount; 731 int maxValidIndex; 732 switch (geoSrc.fIndexSrc) { 733 case kNone_GeometrySrcType: 734 GrCrash("Attempting to draw indexed geom without index src."); 735 case kReserved_GeometrySrcType: // fallthrough 736 case kArray_GeometrySrcType: 737 maxValidIndex = geoSrc.fIndexCount; 738 break; 739 case kBuffer_GeometrySrcType: 740 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t); 741 break; 742 } 743 if (maxIndex > maxValidIndex) { 744 GrCrash("Index reads outside valid index range."); 745 } 746 } 747 748 GrAssert(NULL != drawState.getRenderTarget()); 749 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 750 if (drawState.isStageEnabled(s)) { 751 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage(); 752 int numTextures = stage->numTextures(); 753 for (int t = 0; t < numTextures; ++t) { 754 GrTexture* texture = stage->texture(t); 755 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget()); 756 } 757 } 758 } 759#endif 760 if (NULL == drawState.getRenderTarget()) { 761 return false; 762 } 763 return true; 764} 765 766void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex, 767 int startIndex, int vertexCount, 768 int indexCount) { 769 if (indexCount > 0 && 770 this->checkDraw(type, startVertex, startIndex, 771 vertexCount, indexCount)) { 772 this->onDrawIndexed(type, startVertex, startIndex, 773 vertexCount, indexCount); 774 } 775} 776 777void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 778 int startVertex, 779 int vertexCount) { 780 if (vertexCount > 0 && 781 this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 782 this->onDrawNonIndexed(type, startVertex, vertexCount); 783 } 784} 785 786void GrDrawTarget::stencilPath(const GrPath* path, GrPathFill fill) { 787 // TODO: extract portions of checkDraw that are relevant to path stenciling. 788 GrAssert(NULL != path); 789 GrAssert(fCaps.pathStencilingSupport()); 790 GrAssert(kHairLine_GrPathFill != fill); 791 GrAssert(!GrIsFillInverted(fill)); 792 this->onStencilPath(path, fill); 793} 794 795//////////////////////////////////////////////////////////////////////////////// 796 797// Some blend modes allow folding a partial coverage value into the color's 798// alpha channel, while others will blend incorrectly. 799bool GrDrawTarget::canTweakAlphaForCoverage() const { 800 /** 801 * The fractional coverage is f 802 * The src and dst coeffs are Cs and Cd 803 * The dst and src colors are S and D 804 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D 805 * By tweaking the source color's alpha we're replacing S with S'=fS. It's 806 * obvious that that first term will always be ok. The second term can be 807 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities 808 * for Cd we find that only 1, ISA, and ISC produce the correct depth 809 * coeffecient in terms of S' and D. 810 */ 811 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff(); 812 return kOne_GrBlendCoeff == dstCoeff || 813 kISA_GrBlendCoeff == dstCoeff || 814 kISC_GrBlendCoeff == dstCoeff; 815} 816 817bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const { 818 const GrDrawState& drawState = this->getDrawState(); 819 820 // Check if per-vertex or constant color may have partial alpha 821 if ((layout & kColor_VertexLayoutBit) || 822 0xff != GrColorUnpackA(drawState.getColor())) { 823 return false; 824 } 825 // Check if color filter could introduce an alpha 826 // (TODO: Consider being more aggressive with regards to detecting 0xff 827 // final alpha from color filter). 828 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) { 829 return false; 830 } 831 // Check if a color stage could create a partial alpha 832 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) { 833 if (this->isStageEnabled(s)) { 834 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage(); 835 // FIXME: The param indicates whether the texture is opaque or not. However, the stage 836 // already controls its textures. It really needs to know whether the incoming color 837 // (from a uni, per-vertex colors, or previous stage) is opaque or not. 838 if (!stage->isOpaque(true)) { 839 return false; 840 } 841 } 842 } 843 return true; 844} 845 846namespace { 847GrVertexLayout default_blend_opts_vertex_layout() { 848 GrVertexLayout layout = 0; 849 return layout; 850} 851} 852 853GrDrawTarget::BlendOptFlags 854GrDrawTarget::getBlendOpts(bool forceCoverage, 855 GrBlendCoeff* srcCoeff, 856 GrBlendCoeff* dstCoeff) const { 857 858 GrVertexLayout layout; 859 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) { 860 layout = default_blend_opts_vertex_layout(); 861 } else { 862 layout = this->getVertexLayout(); 863 } 864 865 const GrDrawState& drawState = this->getDrawState(); 866 867 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; 868 if (NULL == srcCoeff) { 869 srcCoeff = &bogusSrcCoeff; 870 } 871 *srcCoeff = drawState.getSrcBlendCoeff(); 872 873 if (NULL == dstCoeff) { 874 dstCoeff = &bogusDstCoeff; 875 } 876 *dstCoeff = drawState.getDstBlendCoeff(); 877 878 // We don't ever expect source coeffecients to reference the source 879 GrAssert(kSA_GrBlendCoeff != *srcCoeff && 880 kISA_GrBlendCoeff != *srcCoeff && 881 kSC_GrBlendCoeff != *srcCoeff && 882 kISC_GrBlendCoeff != *srcCoeff); 883 // same for dst 884 GrAssert(kDA_GrBlendCoeff != *dstCoeff && 885 kIDA_GrBlendCoeff != *dstCoeff && 886 kDC_GrBlendCoeff != *dstCoeff && 887 kIDC_GrBlendCoeff != *dstCoeff); 888 889 if (drawState.isColorWriteDisabled()) { 890 *srcCoeff = kZero_GrBlendCoeff; 891 *dstCoeff = kOne_GrBlendCoeff; 892 } 893 894 bool srcAIsOne = this->srcAlphaWillBeOne(layout); 895 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || 896 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); 897 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || 898 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); 899 900 901 // When coeffs are (0,1) there is no reason to draw at all, unless 902 // stenciling is enabled. Having color writes disabled is effectively 903 // (0,1). The same applies when coverage is known to be 0. 904 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || 905 (!(layout & kCoverage_VertexLayoutBit) && 906 0 == drawState.getCoverage())) { 907 if (drawState.getStencil().doesWrite()) { 908 return kDisableBlend_BlendOptFlag | 909 kEmitTransBlack_BlendOptFlag; 910 } else { 911 return kSkipDraw_BlendOptFlag; 912 } 913 } 914 915 // check for coverage due to constant coverage, per-vertex coverage, 916 // edge aa or coverage texture stage 917 bool hasCoverage = forceCoverage || 918 0xffffffff != drawState.getCoverage() || 919 (layout & kCoverage_VertexLayoutBit) || 920 (layout & kEdge_VertexLayoutBit); 921 for (int s = drawState.getFirstCoverageStage(); 922 !hasCoverage && s < GrDrawState::kNumStages; 923 ++s) { 924 if (this->isStageEnabled(s)) { 925 hasCoverage = true; 926 } 927 } 928 929 // if we don't have coverage we can check whether the dst 930 // has to read at all. If not, we'll disable blending. 931 if (!hasCoverage) { 932 if (dstCoeffIsZero) { 933 if (kOne_GrBlendCoeff == *srcCoeff) { 934 // if there is no coverage and coeffs are (1,0) then we 935 // won't need to read the dst at all, it gets replaced by src 936 return kDisableBlend_BlendOptFlag; 937 } else if (kZero_GrBlendCoeff == *srcCoeff) { 938 // if the op is "clear" then we don't need to emit a color 939 // or blend, just write transparent black into the dst. 940 *srcCoeff = kOne_GrBlendCoeff; 941 *dstCoeff = kZero_GrBlendCoeff; 942 return kDisableBlend_BlendOptFlag | 943 kEmitTransBlack_BlendOptFlag; 944 } 945 } 946 } else { 947 // check whether coverage can be safely rolled into alpha 948 // of if we can skip color computation and just emit coverage 949 if (this->canTweakAlphaForCoverage()) { 950 return kCoverageAsAlpha_BlendOptFlag; 951 } 952 if (dstCoeffIsZero) { 953 if (kZero_GrBlendCoeff == *srcCoeff) { 954 // the source color is not included in the blend 955 // the dst coeff is effectively zero so blend works out to: 956 // (c)(0)D + (1-c)D = (1-c)D. 957 *dstCoeff = kISA_GrBlendCoeff; 958 return kEmitCoverage_BlendOptFlag; 959 } else if (srcAIsOne) { 960 // the dst coeff is effectively zero so blend works out to: 961 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. 962 // If Sa is 1 then we can replace Sa with c 963 // and set dst coeff to 1-Sa. 964 *dstCoeff = kISA_GrBlendCoeff; 965 return kCoverageAsAlpha_BlendOptFlag; 966 } 967 } else if (dstCoeffIsOne) { 968 // the dst coeff is effectively one so blend works out to: 969 // cS + (c)(1)D + (1-c)D = cS + D. 970 *dstCoeff = kOne_GrBlendCoeff; 971 return kCoverageAsAlpha_BlendOptFlag; 972 } 973 } 974 return kNone_BlendOpt; 975} 976 977bool GrDrawTarget::willUseHWAALines() const { 978 // there is a conflict between using smooth lines and our use of 979 // premultiplied alpha. Smooth lines tweak the incoming alpha value 980 // but not in a premul-alpha way. So we only use them when our alpha 981 // is 0xff and tweaking the color for partial coverage is OK 982 if (!fCaps.hwAALineSupport() || 983 !this->getDrawState().isHWAntialiasState()) { 984 return false; 985 } 986 BlendOptFlags opts = this->getBlendOpts(); 987 return (kDisableBlend_BlendOptFlag & opts) && 988 (kCoverageAsAlpha_BlendOptFlag & opts); 989} 990 991bool GrDrawTarget::canApplyCoverage() const { 992 // we can correctly apply coverage if a) we have dual source blending 993 // or b) one of our blend optimizations applies. 994 return this->getCaps().dualSourceBlendingSupport() || 995 kNone_BlendOpt != this->getBlendOpts(true); 996} 997 998//////////////////////////////////////////////////////////////////////////////// 999 1000void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 1001 int instanceCount, 1002 int verticesPerInstance, 1003 int indicesPerInstance) { 1004 if (!verticesPerInstance || !indicesPerInstance) { 1005 return; 1006 } 1007 1008 int instancesPerDraw = this->indexCountInCurrentSource() / 1009 indicesPerInstance; 1010 if (!instancesPerDraw) { 1011 return; 1012 } 1013 1014 instancesPerDraw = GrMin(instanceCount, instancesPerDraw); 1015 int startVertex = 0; 1016 while (instanceCount) { 1017 this->drawIndexed(type, 1018 startVertex, 1019 0, 1020 verticesPerInstance * instancesPerDraw, 1021 indicesPerInstance * instancesPerDraw); 1022 startVertex += verticesPerInstance; 1023 instanceCount -= instancesPerDraw; 1024 } 1025} 1026 1027//////////////////////////////////////////////////////////////////////////////// 1028 1029void GrDrawTarget::drawRect(const GrRect& rect, 1030 const GrMatrix* matrix, 1031 const GrRect* srcRects[], 1032 const GrMatrix* srcMatrices[]) { 1033 GrVertexLayout layout = GetRectVertexLayout(srcRects); 1034 1035 AutoReleaseGeometry geo(this, layout, 4, 0); 1036 if (!geo.succeeded()) { 1037 GrPrintf("Failed to get space for vertices!\n"); 1038 return; 1039 } 1040 1041 SetRectVertices(rect, matrix, srcRects, 1042 srcMatrices, SK_ColorBLACK, layout, geo.vertices()); 1043 1044 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); 1045} 1046 1047GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) { 1048 if (NULL == srcRects) { 1049 return 0; 1050 } 1051 1052 GrVertexLayout layout = 0; 1053 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 1054 int numTC = 0; 1055 if (NULL != srcRects[i]) { 1056 layout |= StageTexCoordVertexLayoutBit(i, numTC); 1057 ++numTC; 1058 } 1059 } 1060 return layout; 1061} 1062 1063// This method fills int the four vertices for drawing 'rect'. 1064// matrix - is applied to each vertex 1065// srcRects - provide the uvs for each vertex 1066// srcMatrices - are applied to the corresponding 'srcRect' 1067// color - vertex color (replicated in each vertex) 1068// layout - specifies which uvs and/or color are present 1069// vertices - storage for the resulting vertices 1070// Note: the color parameter will only be used when kColor_VertexLayoutBit 1071// is present in 'layout' 1072void GrDrawTarget::SetRectVertices(const GrRect& rect, 1073 const GrMatrix* matrix, 1074 const GrRect* srcRects[], 1075 const GrMatrix* srcMatrices[], 1076 GrColor color, 1077 GrVertexLayout layout, 1078 void* vertices) { 1079#if GR_DEBUG 1080 // check that the layout and srcRects agree 1081 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 1082 if (VertexTexCoordsForStage(i, layout) >= 0) { 1083 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]); 1084 } else { 1085 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]); 1086 } 1087 } 1088#endif 1089 1090 int stageOffsets[GrDrawState::kNumStages], colorOffset; 1091 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, 1092 &colorOffset, NULL, NULL); 1093 1094 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop, 1095 rect.fRight, rect.fBottom, 1096 vsize); 1097 if (NULL != matrix) { 1098 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4); 1099 } 1100 1101 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 1102 if (stageOffsets[i] > 0) { 1103 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) + 1104 stageOffsets[i]); 1105 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop, 1106 srcRects[i]->fRight, srcRects[i]->fBottom, 1107 vsize); 1108 if (NULL != srcMatrices && NULL != srcMatrices[i]) { 1109 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4); 1110 } 1111 } 1112 } 1113 1114 if (layout & kColor_VertexLayoutBit) { 1115 1116 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset); 1117 1118 for (int i = 0; i < 4; ++i) { 1119 *vertCol = color; 1120 vertCol = (GrColor*) ((intptr_t) vertCol + vsize); 1121 } 1122 } 1123} 1124 1125//////////////////////////////////////////////////////////////////////////////// 1126 1127GrDrawTarget::AutoStateRestore::AutoStateRestore() { 1128 fDrawTarget = NULL; 1129} 1130 1131GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 1132 ASRInit init) { 1133 fDrawTarget = NULL; 1134 this->set(target, init); 1135} 1136 1137GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 1138 if (NULL != fDrawTarget) { 1139 fDrawTarget->setDrawState(fSavedState); 1140 fSavedState->unref(); 1141 } 1142} 1143 1144void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) { 1145 GrAssert(NULL == fDrawTarget); 1146 fDrawTarget = target; 1147 fSavedState = target->drawState(); 1148 GrAssert(fSavedState); 1149 fSavedState->ref(); 1150 if (kReset_ASRInit == init) { 1151 // calls the default cons 1152 fTempState.init(); 1153 } else { 1154 GrAssert(kPreserve_ASRInit == init); 1155 // calls the copy cons 1156 fTempState.set(*fSavedState); 1157 } 1158 target->setDrawState(fTempState.get()); 1159} 1160 1161//////////////////////////////////////////////////////////////////////////////// 1162 1163GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 1164 GrDrawTarget* target, 1165 GrVertexLayout vertexLayout, 1166 int vertexCount, 1167 int indexCount) { 1168 fTarget = NULL; 1169 this->set(target, vertexLayout, vertexCount, indexCount); 1170} 1171 1172GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 1173 fTarget = NULL; 1174} 1175 1176GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 1177 this->reset(); 1178} 1179 1180bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 1181 GrVertexLayout vertexLayout, 1182 int vertexCount, 1183 int indexCount) { 1184 this->reset(); 1185 fTarget = target; 1186 bool success = true; 1187 if (NULL != fTarget) { 1188 fTarget = target; 1189 success = target->reserveVertexAndIndexSpace(vertexLayout, 1190 vertexCount, 1191 indexCount, 1192 &fVertices, 1193 &fIndices); 1194 if (!success) { 1195 fTarget = NULL; 1196 this->reset(); 1197 } 1198 } 1199 GrAssert(success == (NULL != fTarget)); 1200 return success; 1201} 1202 1203void GrDrawTarget::AutoReleaseGeometry::reset() { 1204 if (NULL != fTarget) { 1205 if (NULL != fVertices) { 1206 fTarget->resetVertexSource(); 1207 } 1208 if (NULL != fIndices) { 1209 fTarget->resetIndexSource(); 1210 } 1211 fTarget = NULL; 1212 } 1213 fVertices = NULL; 1214 fIndices = NULL; 1215} 1216 1217void GrDrawTarget::Caps::print() const { 1218 static const char* gNY[] = {"NO", "YES"}; 1219 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]); 1220 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]); 1221 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]); 1222 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]); 1223 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]); 1224 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]); 1225 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]); 1226 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]); 1227 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]); 1228 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]); 1229 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]); 1230 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize); 1231 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize); 1232} 1233