gfx/skia/trunk/src/gpu/GrDrawTarget.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2010 Google Inc.
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10
michael@0 11 #include "GrDrawTarget.h"
michael@0 12 #include "GrContext.h"
michael@0 13 #include "GrDrawTargetCaps.h"
michael@0 14 #include "GrPath.h"
michael@0 15 #include "GrRenderTarget.h"
michael@0 16 #include "GrTexture.h"
michael@0 17 #include "GrVertexBuffer.h"
michael@0 18
michael@0 19 #include "SkStrokeRec.h"
michael@0 20
michael@0 21 ////////////////////////////////////////////////////////////////////////////////
michael@0 22
michael@0 23 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
michael@0 24 fPrimitiveType = di.fPrimitiveType;
michael@0 25 fStartVertex = di.fStartVertex;
michael@0 26 fStartIndex = di.fStartIndex;
michael@0 27 fVertexCount = di.fVertexCount;
michael@0 28 fIndexCount = di.fIndexCount;
michael@0 29
michael@0 30 fInstanceCount = di.fInstanceCount;
michael@0 31 fVerticesPerInstance = di.fVerticesPerInstance;
michael@0 32 fIndicesPerInstance = di.fIndicesPerInstance;
michael@0 33
michael@0 34 if (NULL != di.fDevBounds) {
michael@0 35 SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
michael@0 36 fDevBoundsStorage = di.fDevBoundsStorage;
michael@0 37 fDevBounds = &fDevBoundsStorage;
michael@0 38 } else {
michael@0 39 fDevBounds = NULL;
michael@0 40 }
michael@0 41
michael@0 42 fDstCopy = di.fDstCopy;
michael@0 43
michael@0 44 return *this;
michael@0 45 }
michael@0 46
michael@0 47 #ifdef SK_DEBUG
michael@0 48 bool GrDrawTarget::DrawInfo::isInstanced() const {
michael@0 49 if (fInstanceCount > 0) {
michael@0 50 SkASSERT(0 == fIndexCount % fIndicesPerInstance);
michael@0 51 SkASSERT(0 == fVertexCount % fVerticesPerInstance);
michael@0 52 SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount);
michael@0 53 SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount);
michael@0 54 // there is no way to specify a non-zero start index to drawIndexedInstances().
michael@0 55 SkASSERT(0 == fStartIndex);
michael@0 56 return true;
michael@0 57 } else {
michael@0 58 SkASSERT(!fVerticesPerInstance);
michael@0 59 SkASSERT(!fIndicesPerInstance);
michael@0 60 return false;
michael@0 61 }
michael@0 62 }
michael@0 63 #endif
michael@0 64
michael@0 65 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
michael@0 66 SkASSERT(this->isInstanced());
michael@0 67 SkASSERT(instanceOffset + fInstanceCount >= 0);
michael@0 68 fInstanceCount += instanceOffset;
michael@0 69 fVertexCount = fVerticesPerInstance * fInstanceCount;
michael@0 70 fIndexCount = fIndicesPerInstance * fInstanceCount;
michael@0 71 }
michael@0 72
michael@0 73 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
michael@0 74 fStartVertex += vertexOffset;
michael@0 75 SkASSERT(fStartVertex >= 0);
michael@0 76 }
michael@0 77
michael@0 78 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
michael@0 79 SkASSERT(this->isIndexed());
michael@0 80 fStartIndex += indexOffset;
michael@0 81 SkASSERT(fStartIndex >= 0);
michael@0 82 }
michael@0 83
michael@0 84 ////////////////////////////////////////////////////////////////////////////////
michael@0 85
michael@0 86 #define DEBUG_INVAL_BUFFER 0xdeadcafe
michael@0 87 #define DEBUG_INVAL_START_IDX -1
michael@0 88
michael@0 89 GrDrawTarget::GrDrawTarget(GrContext* context)
michael@0 90 : fClip(NULL)
michael@0 91 , fContext(context)
michael@0 92 , fPushGpuTraceCount(0) {
michael@0 93 SkASSERT(NULL != context);
michael@0 94
michael@0 95 fDrawState = &fDefaultDrawState;
michael@0 96 // We assume that fDrawState always owns a ref to the object it points at.
michael@0 97 fDefaultDrawState.ref();
michael@0 98 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
michael@0 99 #ifdef SK_DEBUG
michael@0 100 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
michael@0 101 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
michael@0 102 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
michael@0 103 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
michael@0 104 #endif
michael@0 105 geoSrc.fVertexSrc = kNone_GeometrySrcType;
michael@0 106 geoSrc.fIndexSrc = kNone_GeometrySrcType;
michael@0 107 }
michael@0 108
michael@0 109 GrDrawTarget::~GrDrawTarget() {
michael@0 110 SkASSERT(1 == fGeoSrcStateStack.count());
michael@0 111 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
michael@0 112 SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
michael@0 113 SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
michael@0 114 fDrawState->unref();
michael@0 115 }
michael@0 116
michael@0 117 void GrDrawTarget::releaseGeometry() {
michael@0 118 int popCnt = fGeoSrcStateStack.count() - 1;
michael@0 119 while (popCnt) {
michael@0 120 this->popGeometrySource();
michael@0 121 --popCnt;
michael@0 122 }
michael@0 123 this->resetVertexSource();
michael@0 124 this->resetIndexSource();
michael@0 125 }
michael@0 126
michael@0 127 void GrDrawTarget::setClip(const GrClipData* clip) {
michael@0 128 clipWillBeSet(clip);
michael@0 129 fClip = clip;
michael@0 130 }
michael@0 131
michael@0 132 const GrClipData* GrDrawTarget::getClip() const {
michael@0 133 return fClip;
michael@0 134 }
michael@0 135
michael@0 136 void GrDrawTarget::setDrawState(GrDrawState* drawState) {
michael@0 137 SkASSERT(NULL != fDrawState);
michael@0 138 if (NULL == drawState) {
michael@0 139 drawState = &fDefaultDrawState;
michael@0 140 }
michael@0 141 if (fDrawState != drawState) {
michael@0 142 fDrawState->unref();
michael@0 143 drawState->ref();
michael@0 144 fDrawState = drawState;
michael@0 145 }
michael@0 146 }
michael@0 147
michael@0 148 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
michael@0 149 int vertexCount,
michael@0 150 void** vertices) {
michael@0 151 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 152 bool acquired = false;
michael@0 153 if (vertexCount > 0) {
michael@0 154 SkASSERT(NULL != vertices);
michael@0 155 this->releasePreviousVertexSource();
michael@0 156 geoSrc.fVertexSrc = kNone_GeometrySrcType;
michael@0 157
michael@0 158 acquired = this->onReserveVertexSpace(vertexSize,
michael@0 159 vertexCount,
michael@0 160 vertices);
michael@0 161 }
michael@0 162 if (acquired) {
michael@0 163 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
michael@0 164 geoSrc.fVertexCount = vertexCount;
michael@0 165 geoSrc.fVertexSize = vertexSize;
michael@0 166 } else if (NULL != vertices) {
michael@0 167 *vertices = NULL;
michael@0 168 }
michael@0 169 return acquired;
michael@0 170 }
michael@0 171
michael@0 172 bool GrDrawTarget::reserveIndexSpace(int indexCount,
michael@0 173 void** indices) {
michael@0 174 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 175 bool acquired = false;
michael@0 176 if (indexCount > 0) {
michael@0 177 SkASSERT(NULL != indices);
michael@0 178 this->releasePreviousIndexSource();
michael@0 179 geoSrc.fIndexSrc = kNone_GeometrySrcType;
michael@0 180
michael@0 181 acquired = this->onReserveIndexSpace(indexCount, indices);
michael@0 182 }
michael@0 183 if (acquired) {
michael@0 184 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
michael@0 185 geoSrc.fIndexCount = indexCount;
michael@0 186 } else if (NULL != indices) {
michael@0 187 *indices = NULL;
michael@0 188 }
michael@0 189 return acquired;
michael@0 190
michael@0 191 }
michael@0 192
michael@0 193 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
michael@0 194 int indexCount,
michael@0 195 void** vertices,
michael@0 196 void** indices) {
michael@0 197 size_t vertexSize = this->drawState()->getVertexSize();
michael@0 198 this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
michael@0 199 if (vertexCount) {
michael@0 200 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
michael@0 201 if (indexCount) {
michael@0 202 this->resetIndexSource();
michael@0 203 }
michael@0 204 return false;
michael@0 205 }
michael@0 206 }
michael@0 207 if (indexCount) {
michael@0 208 if (!this->reserveIndexSpace(indexCount, indices)) {
michael@0 209 if (vertexCount) {
michael@0 210 this->resetVertexSource();
michael@0 211 }
michael@0 212 return false;
michael@0 213 }
michael@0 214 }
michael@0 215 return true;
michael@0 216 }
michael@0 217
michael@0 218 bool GrDrawTarget::geometryHints(int32_t* vertexCount,
michael@0 219 int32_t* indexCount) const {
michael@0 220 if (NULL != vertexCount) {
michael@0 221 *vertexCount = -1;
michael@0 222 }
michael@0 223 if (NULL != indexCount) {
michael@0 224 *indexCount = -1;
michael@0 225 }
michael@0 226 return false;
michael@0 227 }
michael@0 228
michael@0 229 void GrDrawTarget::releasePreviousVertexSource() {
michael@0 230 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 231 switch (geoSrc.fVertexSrc) {
michael@0 232 case kNone_GeometrySrcType:
michael@0 233 break;
michael@0 234 case kArray_GeometrySrcType:
michael@0 235 this->releaseVertexArray();
michael@0 236 break;
michael@0 237 case kReserved_GeometrySrcType:
michael@0 238 this->releaseReservedVertexSpace();
michael@0 239 break;
michael@0 240 case kBuffer_GeometrySrcType:
michael@0 241 geoSrc.fVertexBuffer->unref();
michael@0 242 #ifdef SK_DEBUG
michael@0 243 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
michael@0 244 #endif
michael@0 245 break;
michael@0 246 default:
michael@0 247 GrCrash("Unknown Vertex Source Type.");
michael@0 248 break;
michael@0 249 }
michael@0 250 }
michael@0 251
michael@0 252 void GrDrawTarget::releasePreviousIndexSource() {
michael@0 253 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 254 switch (geoSrc.fIndexSrc) {
michael@0 255 case kNone_GeometrySrcType: // these two don't require
michael@0 256 break;
michael@0 257 case kArray_GeometrySrcType:
michael@0 258 this->releaseIndexArray();
michael@0 259 break;
michael@0 260 case kReserved_GeometrySrcType:
michael@0 261 this->releaseReservedIndexSpace();
michael@0 262 break;
michael@0 263 case kBuffer_GeometrySrcType:
michael@0 264 geoSrc.fIndexBuffer->unref();
michael@0 265 #ifdef SK_DEBUG
michael@0 266 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
michael@0 267 #endif
michael@0 268 break;
michael@0 269 default:
michael@0 270 GrCrash("Unknown Index Source Type.");
michael@0 271 break;
michael@0 272 }
michael@0 273 }
michael@0 274
michael@0 275 void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
michael@0 276 int vertexCount) {
michael@0 277 this->releasePreviousVertexSource();
michael@0 278 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 279 geoSrc.fVertexSrc = kArray_GeometrySrcType;
michael@0 280 geoSrc.fVertexSize = this->drawState()->getVertexSize();
michael@0 281 geoSrc.fVertexCount = vertexCount;
michael@0 282 this->onSetVertexSourceToArray(vertexArray, vertexCount);
michael@0 283 }
michael@0 284
michael@0 285 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
michael@0 286 int indexCount) {
michael@0 287 this->releasePreviousIndexSource();
michael@0 288 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 289 geoSrc.fIndexSrc = kArray_GeometrySrcType;
michael@0 290 geoSrc.fIndexCount = indexCount;
michael@0 291 this->onSetIndexSourceToArray(indexArray, indexCount);
michael@0 292 }
michael@0 293
michael@0 294 void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
michael@0 295 this->releasePreviousVertexSource();
michael@0 296 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 297 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
michael@0 298 geoSrc.fVertexBuffer = buffer;
michael@0 299 buffer->ref();
michael@0 300 geoSrc.fVertexSize = this->drawState()->getVertexSize();
michael@0 301 }
michael@0 302
michael@0 303 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
michael@0 304 this->releasePreviousIndexSource();
michael@0 305 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 306 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
michael@0 307 geoSrc.fIndexBuffer = buffer;
michael@0 308 buffer->ref();
michael@0 309 }
michael@0 310
michael@0 311 void GrDrawTarget::resetVertexSource() {
michael@0 312 this->releasePreviousVertexSource();
michael@0 313 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 314 geoSrc.fVertexSrc = kNone_GeometrySrcType;
michael@0 315 }
michael@0 316
michael@0 317 void GrDrawTarget::resetIndexSource() {
michael@0 318 this->releasePreviousIndexSource();
michael@0 319 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 320 geoSrc.fIndexSrc = kNone_GeometrySrcType;
michael@0 321 }
michael@0 322
michael@0 323 void GrDrawTarget::pushGeometrySource() {
michael@0 324 this->geometrySourceWillPush();
michael@0 325 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
michael@0 326 newState.fIndexSrc = kNone_GeometrySrcType;
michael@0 327 newState.fVertexSrc = kNone_GeometrySrcType;
michael@0 328 #ifdef SK_DEBUG
michael@0 329 newState.fVertexCount = ~0;
michael@0 330 newState.fVertexBuffer = (GrVertexBuffer*)~0;
michael@0 331 newState.fIndexCount = ~0;
michael@0 332 newState.fIndexBuffer = (GrIndexBuffer*)~0;
michael@0 333 #endif
michael@0 334 }
michael@0 335
michael@0 336 void GrDrawTarget::popGeometrySource() {
michael@0 337 // if popping last element then pops are unbalanced with pushes
michael@0 338 SkASSERT(fGeoSrcStateStack.count() > 1);
michael@0 339
michael@0 340 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
michael@0 341 this->releasePreviousVertexSource();
michael@0 342 this->releasePreviousIndexSource();
michael@0 343 fGeoSrcStateStack.pop_back();
michael@0 344 }
michael@0 345
michael@0 346 ////////////////////////////////////////////////////////////////////////////////
michael@0 347
michael@0 348 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
michael@0 349 int startIndex, int vertexCount,
michael@0 350 int indexCount) const {
michael@0 351 const GrDrawState& drawState = this->getDrawState();
michael@0 352 #ifdef SK_DEBUG
michael@0 353 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
michael@0 354 int maxVertex = startVertex + vertexCount;
michael@0 355 int maxValidVertex;
michael@0 356 switch (geoSrc.fVertexSrc) {
michael@0 357 case kNone_GeometrySrcType:
michael@0 358 GrCrash("Attempting to draw without vertex src.");
michael@0 359 case kReserved_GeometrySrcType: // fallthrough
michael@0 360 case kArray_GeometrySrcType:
michael@0 361 maxValidVertex = geoSrc.fVertexCount;
michael@0 362 break;
michael@0 363 case kBuffer_GeometrySrcType:
michael@0 364 maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize);
michael@0 365 break;
michael@0 366 }
michael@0 367 if (maxVertex > maxValidVertex) {
michael@0 368 GrCrash("Drawing outside valid vertex range.");
michael@0 369 }
michael@0 370 if (indexCount > 0) {
michael@0 371 int maxIndex = startIndex + indexCount;
michael@0 372 int maxValidIndex;
michael@0 373 switch (geoSrc.fIndexSrc) {
michael@0 374 case kNone_GeometrySrcType:
michael@0 375 GrCrash("Attempting to draw indexed geom without index src.");
michael@0 376 case kReserved_GeometrySrcType: // fallthrough
michael@0 377 case kArray_GeometrySrcType:
michael@0 378 maxValidIndex = geoSrc.fIndexCount;
michael@0 379 break;
michael@0 380 case kBuffer_GeometrySrcType:
michael@0 381 maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
michael@0 382 break;
michael@0 383 }
michael@0 384 if (maxIndex > maxValidIndex) {
michael@0 385 GrCrash("Index reads outside valid index range.");
michael@0 386 }
michael@0 387 }
michael@0 388
michael@0 389 SkASSERT(NULL != drawState.getRenderTarget());
michael@0 390
michael@0 391 for (int s = 0; s < drawState.numColorStages(); ++s) {
michael@0 392 const GrEffectRef& effect = *drawState.getColorStage(s).getEffect();
michael@0 393 int numTextures = effect->numTextures();
michael@0 394 for (int t = 0; t < numTextures; ++t) {
michael@0 395 GrTexture* texture = effect->texture(t);
michael@0 396 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
michael@0 397 }
michael@0 398 }
michael@0 399 for (int s = 0; s < drawState.numCoverageStages(); ++s) {
michael@0 400 const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect();
michael@0 401 int numTextures = effect->numTextures();
michael@0 402 for (int t = 0; t < numTextures; ++t) {
michael@0 403 GrTexture* texture = effect->texture(t);
michael@0 404 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
michael@0 405 }
michael@0 406 }
michael@0 407
michael@0 408 SkASSERT(drawState.validateVertexAttribs());
michael@0 409 #endif
michael@0 410 if (NULL == drawState.getRenderTarget()) {
michael@0 411 return false;
michael@0 412 }
michael@0 413 return true;
michael@0 414 }
michael@0 415
michael@0 416 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
michael@0 417 if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
michael@0 418 return true;
michael@0 419 }
michael@0 420 GrRenderTarget* rt = this->drawState()->getRenderTarget();
michael@0 421 SkIRect copyRect;
michael@0 422 const GrClipData* clip = this->getClip();
michael@0 423 clip->getConservativeBounds(rt, &copyRect);
michael@0 424
michael@0 425 if (NULL != drawBounds) {
michael@0 426 SkIRect drawIBounds;
michael@0 427 drawBounds->roundOut(&drawIBounds);
michael@0 428 if (!copyRect.intersect(drawIBounds)) {
michael@0 429 #ifdef SK_DEBUG
michael@0 430 GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
michael@0 431 #endif
michael@0 432 return false;
michael@0 433 }
michael@0 434 } else {
michael@0 435 #ifdef SK_DEBUG
michael@0 436 //GrPrintf("No dev bounds when dst copy is made.\n");
michael@0 437 #endif
michael@0 438 }
michael@0 439
michael@0 440 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
michael@0 441 // have per-sample dst values by making the copy multisampled.
michael@0 442 GrTextureDesc desc;
michael@0 443 this->initCopySurfaceDstDesc(rt, &desc);
michael@0 444 desc.fWidth = copyRect.width();
michael@0 445 desc.fHeight = copyRect.height();
michael@0 446
michael@0 447 GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch);
michael@0 448
michael@0 449 if (NULL == ast.texture()) {
michael@0 450 GrPrintf("Failed to create temporary copy of destination texture.\n");
michael@0 451 return false;
michael@0 452 }
michael@0 453 SkIPoint dstPoint = {0, 0};
michael@0 454 if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) {
michael@0 455 dstCopy->setTexture(ast.texture());
michael@0 456 dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
michael@0 457 return true;
michael@0 458 } else {
michael@0 459 return false;
michael@0 460 }
michael@0 461 }
michael@0 462
michael@0 463 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
michael@0 464 int startVertex,
michael@0 465 int startIndex,
michael@0 466 int vertexCount,
michael@0 467 int indexCount,
michael@0 468 const SkRect* devBounds) {
michael@0 469 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
michael@0 470 DrawInfo info;
michael@0 471 info.fPrimitiveType = type;
michael@0 472 info.fStartVertex = startVertex;
michael@0 473 info.fStartIndex = startIndex;
michael@0 474 info.fVertexCount = vertexCount;
michael@0 475 info.fIndexCount = indexCount;
michael@0 476
michael@0 477 info.fInstanceCount = 0;
michael@0 478 info.fVerticesPerInstance = 0;
michael@0 479 info.fIndicesPerInstance = 0;
michael@0 480
michael@0 481 if (NULL != devBounds) {
michael@0 482 info.setDevBounds(*devBounds);
michael@0 483 }
michael@0 484 // TODO: We should continue with incorrect blending.
michael@0 485 if (!this->setupDstReadIfNecessary(&info)) {
michael@0 486 return;
michael@0 487 }
michael@0 488 this->onDraw(info);
michael@0 489 }
michael@0 490 }
michael@0 491
michael@0 492 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
michael@0 493 int startVertex,
michael@0 494 int vertexCount,
michael@0 495 const SkRect* devBounds) {
michael@0 496 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
michael@0 497 DrawInfo info;
michael@0 498 info.fPrimitiveType = type;
michael@0 499 info.fStartVertex = startVertex;
michael@0 500 info.fStartIndex = 0;
michael@0 501 info.fVertexCount = vertexCount;
michael@0 502 info.fIndexCount = 0;
michael@0 503
michael@0 504 info.fInstanceCount = 0;
michael@0 505 info.fVerticesPerInstance = 0;
michael@0 506 info.fIndicesPerInstance = 0;
michael@0 507
michael@0 508 if (NULL != devBounds) {
michael@0 509 info.setDevBounds(*devBounds);
michael@0 510 }
michael@0 511 // TODO: We should continue with incorrect blending.
michael@0 512 if (!this->setupDstReadIfNecessary(&info)) {
michael@0 513 return;
michael@0 514 }
michael@0 515 this->onDraw(info);
michael@0 516 }
michael@0 517 }
michael@0 518
michael@0 519 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
michael@0 520 // TODO: extract portions of checkDraw that are relevant to path stenciling.
michael@0 521 SkASSERT(NULL != path);
michael@0 522 SkASSERT(this->caps()->pathRenderingSupport());
michael@0 523 SkASSERT(!SkPath::IsInverseFillType(fill));
michael@0 524 this->onStencilPath(path, fill);
michael@0 525 }
michael@0 526
michael@0 527 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
michael@0 528 // TODO: extract portions of checkDraw that are relevant to path rendering.
michael@0 529 SkASSERT(NULL != path);
michael@0 530 SkASSERT(this->caps()->pathRenderingSupport());
michael@0 531 const GrDrawState* drawState = &getDrawState();
michael@0 532
michael@0 533 SkRect devBounds;
michael@0 534 if (SkPath::IsInverseFillType(fill)) {
michael@0 535 devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
michael@0 536 SkIntToScalar(drawState->getRenderTarget()->height()));
michael@0 537 } else {
michael@0 538 devBounds = path->getBounds();
michael@0 539 }
michael@0 540 SkMatrix viewM = drawState->getViewMatrix();
michael@0 541 viewM.mapRect(&devBounds);
michael@0 542
michael@0 543 GrDeviceCoordTexture dstCopy;
michael@0 544 if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
michael@0 545 return;
michael@0 546 }
michael@0 547
michael@0 548 this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
michael@0 549 }
michael@0 550
michael@0 551 void GrDrawTarget::instantGpuTraceEvent(const char* marker) {
michael@0 552 if (this->caps()->gpuTracingSupport()) {
michael@0 553 this->onInstantGpuTraceEvent(marker);
michael@0 554 }
michael@0 555 }
michael@0 556
michael@0 557 void GrDrawTarget::pushGpuTraceEvent(const char* marker) {
michael@0 558 SkASSERT(fPushGpuTraceCount >= 0);
michael@0 559 if (this->caps()->gpuTracingSupport()) {
michael@0 560 this->onPushGpuTraceEvent(marker);
michael@0 561 ++fPushGpuTraceCount;
michael@0 562 }
michael@0 563 }
michael@0 564
michael@0 565 void GrDrawTarget::popGpuTraceEvent() {
michael@0 566 SkASSERT(fPushGpuTraceCount >= 1);
michael@0 567 if (this->caps()->gpuTracingSupport()) {
michael@0 568 this->onPopGpuTraceEvent();
michael@0 569 --fPushGpuTraceCount;
michael@0 570 }
michael@0 571 }
michael@0 572
michael@0 573 ////////////////////////////////////////////////////////////////////////////////
michael@0 574
michael@0 575 bool GrDrawTarget::willUseHWAALines() const {
michael@0 576 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
michael@0 577 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
michael@0 578 // our alpha is 0xff and tweaking the color for partial coverage is OK
michael@0 579 if (!this->caps()->hwAALineSupport() ||
michael@0 580 !this->getDrawState().isHWAntialiasState()) {
michael@0 581 return false;
michael@0 582 }
michael@0 583 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
michael@0 584 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
michael@0 585 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
michael@0 586 }
michael@0 587
michael@0 588 bool GrDrawTarget::canApplyCoverage() const {
michael@0 589 // we can correctly apply coverage if a) we have dual source blending
michael@0 590 // or b) one of our blend optimizations applies.
michael@0 591 return this->caps()->dualSourceBlendingSupport() ||
michael@0 592 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
michael@0 593 }
michael@0 594
michael@0 595 ////////////////////////////////////////////////////////////////////////////////
michael@0 596
michael@0 597 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
michael@0 598 int instanceCount,
michael@0 599 int verticesPerInstance,
michael@0 600 int indicesPerInstance,
michael@0 601 const SkRect* devBounds) {
michael@0 602 if (!verticesPerInstance || !indicesPerInstance) {
michael@0 603 return;
michael@0 604 }
michael@0 605
michael@0 606 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
michael@0 607 if (!maxInstancesPerDraw) {
michael@0 608 return;
michael@0 609 }
michael@0 610
michael@0 611 DrawInfo info;
michael@0 612 info.fPrimitiveType = type;
michael@0 613 info.fStartIndex = 0;
michael@0 614 info.fStartVertex = 0;
michael@0 615 info.fIndicesPerInstance = indicesPerInstance;
michael@0 616 info.fVerticesPerInstance = verticesPerInstance;
michael@0 617
michael@0 618 // Set the same bounds for all the draws.
michael@0 619 if (NULL != devBounds) {
michael@0 620 info.setDevBounds(*devBounds);
michael@0 621 }
michael@0 622 // TODO: We should continue with incorrect blending.
michael@0 623 if (!this->setupDstReadIfNecessary(&info)) {
michael@0 624 return;
michael@0 625 }
michael@0 626
michael@0 627 while (instanceCount) {
michael@0 628 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
michael@0 629 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
michael@0 630 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
michael@0 631
michael@0 632 if (this->checkDraw(type,
michael@0 633 info.fStartVertex,
michael@0 634 info.fStartIndex,
michael@0 635 info.fVertexCount,
michael@0 636 info.fIndexCount)) {
michael@0 637 this->onDraw(info);
michael@0 638 }
michael@0 639 info.fStartVertex += info.fVertexCount;
michael@0 640 instanceCount -= info.fInstanceCount;
michael@0 641 }
michael@0 642 }
michael@0 643
michael@0 644 ////////////////////////////////////////////////////////////////////////////////
michael@0 645
michael@0 646 namespace {
michael@0 647
michael@0 648 // position + (optional) texture coord
michael@0 649 extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
michael@0 650 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
michael@0 651 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
michael@0 652 };
michael@0 653
michael@0 654 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
michael@0 655 if (hasUVs) {
michael@0 656 drawState->setVertexAttribs<gBWRectPosUVAttribs>(2);
michael@0 657 } else {
michael@0 658 drawState->setVertexAttribs<gBWRectPosUVAttribs>(1);
michael@0 659 }
michael@0 660 }
michael@0 661
michael@0 662 };
michael@0 663
michael@0 664 void GrDrawTarget::onDrawRect(const SkRect& rect,
michael@0 665 const SkMatrix* matrix,
michael@0 666 const SkRect* localRect,
michael@0 667 const SkMatrix* localMatrix) {
michael@0 668
michael@0 669 GrDrawState::AutoViewMatrixRestore avmr;
michael@0 670 if (NULL != matrix) {
michael@0 671 avmr.set(this->drawState(), *matrix);
michael@0 672 }
michael@0 673
michael@0 674 set_vertex_attributes(this->drawState(), NULL != localRect);
michael@0 675
michael@0 676 AutoReleaseGeometry geo(this, 4, 0);
michael@0 677 if (!geo.succeeded()) {
michael@0 678 GrPrintf("Failed to get space for vertices!\n");
michael@0 679 return;
michael@0 680 }
michael@0 681
michael@0 682 size_t vsize = this->drawState()->getVertexSize();
michael@0 683 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
michael@0 684 if (NULL != localRect) {
michael@0 685 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
michael@0 686 sizeof(GrPoint));
michael@0 687 coords->setRectFan(localRect->fLeft, localRect->fTop,
michael@0 688 localRect->fRight, localRect->fBottom,
michael@0 689 vsize);
michael@0 690 if (NULL != localMatrix) {
michael@0 691 localMatrix->mapPointsWithStride(coords, vsize, 4);
michael@0 692 }
michael@0 693 }
michael@0 694 SkRect bounds;
michael@0 695 this->getDrawState().getViewMatrix().mapRect(&bounds, rect);
michael@0 696
michael@0 697 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds);
michael@0 698 }
michael@0 699
michael@0 700 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
michael@0 701 }
michael@0 702
michael@0 703 ////////////////////////////////////////////////////////////////////////////////
michael@0 704
michael@0 705 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
michael@0 706 fDrawTarget = NULL;
michael@0 707 }
michael@0 708
michael@0 709 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
michael@0 710 ASRInit init,
michael@0 711 const SkMatrix* vm) {
michael@0 712 fDrawTarget = NULL;
michael@0 713 this->set(target, init, vm);
michael@0 714 }
michael@0 715
michael@0 716 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
michael@0 717 if (NULL != fDrawTarget) {
michael@0 718 fDrawTarget->setDrawState(fSavedState);
michael@0 719 fSavedState->unref();
michael@0 720 }
michael@0 721 }
michael@0 722
michael@0 723 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
michael@0 724 SkASSERT(NULL == fDrawTarget);
michael@0 725 fDrawTarget = target;
michael@0 726 fSavedState = target->drawState();
michael@0 727 SkASSERT(fSavedState);
michael@0 728 fSavedState->ref();
michael@0 729 if (kReset_ASRInit == init) {
michael@0 730 if (NULL == vm) {
michael@0 731 // calls the default cons
michael@0 732 fTempState.init();
michael@0 733 } else {
michael@0 734 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
michael@0 735 }
michael@0 736 } else {
michael@0 737 SkASSERT(kPreserve_ASRInit == init);
michael@0 738 if (NULL == vm) {
michael@0 739 fTempState.set(*fSavedState);
michael@0 740 } else {
michael@0 741 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
michael@0 742 }
michael@0 743 }
michael@0 744 target->setDrawState(fTempState.get());
michael@0 745 }
michael@0 746
michael@0 747 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
michael@0 748 SkASSERT(NULL == fDrawTarget);
michael@0 749 fDrawTarget = target;
michael@0 750 fSavedState = target->drawState();
michael@0 751 SkASSERT(fSavedState);
michael@0 752 fSavedState->ref();
michael@0 753 if (kReset_ASRInit == init) {
michael@0 754 // calls the default cons
michael@0 755 fTempState.init();
michael@0 756 } else {
michael@0 757 SkASSERT(kPreserve_ASRInit == init);
michael@0 758 // calls the copy cons
michael@0 759 fTempState.set(*fSavedState);
michael@0 760 if (!fTempState.get()->setIdentityViewMatrix()) {
michael@0 761 // let go of any resources held by the temp
michael@0 762 fTempState.get()->reset();
michael@0 763 fDrawTarget = NULL;
michael@0 764 fSavedState->unref();
michael@0 765 fSavedState = NULL;
michael@0 766 return false;
michael@0 767 }
michael@0 768 }
michael@0 769 target->setDrawState(fTempState.get());
michael@0 770 return true;
michael@0 771 }
michael@0 772
michael@0 773 ////////////////////////////////////////////////////////////////////////////////
michael@0 774
michael@0 775 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
michael@0 776 GrDrawTarget* target,
michael@0 777 int vertexCount,
michael@0 778 int indexCount) {
michael@0 779 fTarget = NULL;
michael@0 780 this->set(target, vertexCount, indexCount);
michael@0 781 }
michael@0 782
michael@0 783 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
michael@0 784 fTarget = NULL;
michael@0 785 }
michael@0 786
michael@0 787 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
michael@0 788 this->reset();
michael@0 789 }
michael@0 790
michael@0 791 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
michael@0 792 int vertexCount,
michael@0 793 int indexCount) {
michael@0 794 this->reset();
michael@0 795 fTarget = target;
michael@0 796 bool success = true;
michael@0 797 if (NULL != fTarget) {
michael@0 798 fTarget = target;
michael@0 799 success = target->reserveVertexAndIndexSpace(vertexCount,
michael@0 800 indexCount,
michael@0 801 &fVertices,
michael@0 802 &fIndices);
michael@0 803 if (!success) {
michael@0 804 fTarget = NULL;
michael@0 805 this->reset();
michael@0 806 }
michael@0 807 }
michael@0 808 SkASSERT(success == (NULL != fTarget));
michael@0 809 return success;
michael@0 810 }
michael@0 811
michael@0 812 void GrDrawTarget::AutoReleaseGeometry::reset() {
michael@0 813 if (NULL != fTarget) {
michael@0 814 if (NULL != fVertices) {
michael@0 815 fTarget->resetVertexSource();
michael@0 816 }
michael@0 817 if (NULL != fIndices) {
michael@0 818 fTarget->resetIndexSource();
michael@0 819 }
michael@0 820 fTarget = NULL;
michael@0 821 }
michael@0 822 fVertices = NULL;
michael@0 823 fIndices = NULL;
michael@0 824 }
michael@0 825
michael@0 826 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
michael@0 827 fTarget = target;
michael@0 828 fClip = fTarget->getClip();
michael@0 829 fStack.init();
michael@0 830 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
michael@0 831 fReplacementClip.fClipStack = fStack.get();
michael@0 832 target->setClip(&fReplacementClip);
michael@0 833 }
michael@0 834
michael@0 835 namespace {
michael@0 836 // returns true if the read/written rect intersects the src/dst and false if not.
michael@0 837 bool clip_srcrect_and_dstpoint(const GrSurface* dst,
michael@0 838 const GrSurface* src,
michael@0 839 const SkIRect& srcRect,
michael@0 840 const SkIPoint& dstPoint,
michael@0 841 SkIRect* clippedSrcRect,
michael@0 842 SkIPoint* clippedDstPoint) {
michael@0 843 *clippedSrcRect = srcRect;
michael@0 844 *clippedDstPoint = dstPoint;
michael@0 845
michael@0 846 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
michael@0 847 if (clippedSrcRect->fLeft < 0) {
michael@0 848 clippedDstPoint->fX -= clippedSrcRect->fLeft;
michael@0 849 clippedSrcRect->fLeft = 0;
michael@0 850 }
michael@0 851 if (clippedDstPoint->fX < 0) {
michael@0 852 clippedSrcRect->fLeft -= clippedDstPoint->fX;
michael@0 853 clippedDstPoint->fX = 0;
michael@0 854 }
michael@0 855
michael@0 856 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
michael@0 857 if (clippedSrcRect->fTop < 0) {
michael@0 858 clippedDstPoint->fY -= clippedSrcRect->fTop;
michael@0 859 clippedSrcRect->fTop = 0;
michael@0 860 }
michael@0 861 if (clippedDstPoint->fY < 0) {
michael@0 862 clippedSrcRect->fTop -= clippedDstPoint->fY;
michael@0 863 clippedDstPoint->fY = 0;
michael@0 864 }
michael@0 865
michael@0 866 // clip the right edge to the src and dst bounds.
michael@0 867 if (clippedSrcRect->fRight > src->width()) {
michael@0 868 clippedSrcRect->fRight = src->width();
michael@0 869 }
michael@0 870 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
michael@0 871 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
michael@0 872 }
michael@0 873
michael@0 874 // clip the bottom edge to the src and dst bounds.
michael@0 875 if (clippedSrcRect->fBottom > src->height()) {
michael@0 876 clippedSrcRect->fBottom = src->height();
michael@0 877 }
michael@0 878 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
michael@0 879 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
michael@0 880 }
michael@0 881
michael@0 882 // The above clipping steps may have inverted the rect if it didn't intersect either the src or
michael@0 883 // dst bounds.
michael@0 884 return !clippedSrcRect->isEmpty();
michael@0 885 }
michael@0 886 }
michael@0 887
michael@0 888 bool GrDrawTarget::copySurface(GrSurface* dst,
michael@0 889 GrSurface* src,
michael@0 890 const SkIRect& srcRect,
michael@0 891 const SkIPoint& dstPoint) {
michael@0 892 SkASSERT(NULL != dst);
michael@0 893 SkASSERT(NULL != src);
michael@0 894
michael@0 895 SkIRect clippedSrcRect;
michael@0 896 SkIPoint clippedDstPoint;
michael@0 897 // If the rect is outside the src or dst then we've already succeeded.
michael@0 898 if (!clip_srcrect_and_dstpoint(dst,
michael@0 899 src,
michael@0 900 srcRect,
michael@0 901 dstPoint,
michael@0 902 &clippedSrcRect,
michael@0 903 &clippedDstPoint)) {
michael@0 904 SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint));
michael@0 905 return true;
michael@0 906 }
michael@0 907
michael@0 908 bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
michael@0 909 SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint));
michael@0 910 return result;
michael@0 911 }
michael@0 912
michael@0 913 bool GrDrawTarget::canCopySurface(GrSurface* dst,
michael@0 914 GrSurface* src,
michael@0 915 const SkIRect& srcRect,
michael@0 916 const SkIPoint& dstPoint) {
michael@0 917 SkASSERT(NULL != dst);
michael@0 918 SkASSERT(NULL != src);
michael@0 919
michael@0 920 SkIRect clippedSrcRect;
michael@0 921 SkIPoint clippedDstPoint;
michael@0 922 // If the rect is outside the src or dst then we're guaranteed success
michael@0 923 if (!clip_srcrect_and_dstpoint(dst,
michael@0 924 src,
michael@0 925 srcRect,
michael@0 926 dstPoint,
michael@0 927 &clippedSrcRect,
michael@0 928 &clippedDstPoint)) {
michael@0 929 return true;
michael@0 930 }
michael@0 931 return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
michael@0 932 }
michael@0 933
michael@0 934 bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
michael@0 935 GrSurface* src,
michael@0 936 const SkIRect& srcRect,
michael@0 937 const SkIPoint& dstPoint) {
michael@0 938 // Check that the read/write rects are contained within the src/dst bounds.
michael@0 939 SkASSERT(!srcRect.isEmpty());
michael@0 940 SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
michael@0 941 SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0);
michael@0 942 SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
michael@0 943 dstPoint.fY + srcRect.height() <= dst->height());
michael@0 944
michael@0 945 return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture();
michael@0 946 }
michael@0 947
michael@0 948 bool GrDrawTarget::onCopySurface(GrSurface* dst,
michael@0 949 GrSurface* src,
michael@0 950 const SkIRect& srcRect,
michael@0 951 const SkIPoint& dstPoint) {
michael@0 952 if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
michael@0 953 return false;
michael@0 954 }
michael@0 955
michael@0 956 GrRenderTarget* rt = dst->asRenderTarget();
michael@0 957 GrTexture* tex = src->asTexture();
michael@0 958
michael@0 959 GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
michael@0 960 this->drawState()->setRenderTarget(rt);
michael@0 961 SkMatrix matrix;
michael@0 962 matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
michael@0 963 SkIntToScalar(srcRect.fTop - dstPoint.fY));
michael@0 964 matrix.postIDiv(tex->width(), tex->height());
michael@0 965 this->drawState()->addColorTextureEffect(tex, matrix);
michael@0 966 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
michael@0 967 dstPoint.fY,
michael@0 968 srcRect.width(),
michael@0 969 srcRect.height());
michael@0 970 this->drawSimpleRect(dstRect);
michael@0 971 return true;
michael@0 972 }
michael@0 973
michael@0 974 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
michael@0 975 // Make the dst of the copy be a render target because the default copySurface draws to the dst.
michael@0 976 desc->fOrigin = kDefault_GrSurfaceOrigin;
michael@0 977 desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
michael@0 978 desc->fConfig = src->config();
michael@0 979 }
michael@0 980
michael@0 981 ///////////////////////////////////////////////////////////////////////////////
michael@0 982
michael@0 983 void GrDrawTargetCaps::reset() {
michael@0 984 f8BitPaletteSupport = false;
michael@0 985 fMipMapSupport = false;
michael@0 986 fNPOTTextureTileSupport = false;
michael@0 987 fTwoSidedStencilSupport = false;
michael@0 988 fStencilWrapOpsSupport = false;
michael@0 989 fHWAALineSupport = false;
michael@0 990 fShaderDerivativeSupport = false;
michael@0 991 fGeometryShaderSupport = false;
michael@0 992 fDualSourceBlendingSupport = false;
michael@0 993 fBufferLockSupport = false;
michael@0 994 fPathRenderingSupport = false;
michael@0 995 fDstReadInShaderSupport = false;
michael@0 996 fReuseScratchTextures = true;
michael@0 997 fGpuTracingSupport = false;
michael@0 998
michael@0 999 fMaxRenderTargetSize = 0;
michael@0 1000 fMaxTextureSize = 0;
michael@0 1001 fMaxSampleCount = 0;
michael@0 1002
michael@0 1003 memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
michael@0 1004 }
michael@0 1005
michael@0 1006 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
michael@0 1007 f8BitPaletteSupport = other.f8BitPaletteSupport;
michael@0 1008 fMipMapSupport = other.fMipMapSupport;
michael@0 1009 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
michael@0 1010 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
michael@0 1011 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
michael@0 1012 fHWAALineSupport = other.fHWAALineSupport;
michael@0 1013 fShaderDerivativeSupport = other.fShaderDerivativeSupport;
michael@0 1014 fGeometryShaderSupport = other.fGeometryShaderSupport;
michael@0 1015 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
michael@0 1016 fBufferLockSupport = other.fBufferLockSupport;
michael@0 1017 fPathRenderingSupport = other.fPathRenderingSupport;
michael@0 1018 fDstReadInShaderSupport = other.fDstReadInShaderSupport;
michael@0 1019 fReuseScratchTextures = other.fReuseScratchTextures;
michael@0 1020 fGpuTracingSupport = other.fGpuTracingSupport;
michael@0 1021
michael@0 1022 fMaxRenderTargetSize = other.fMaxRenderTargetSize;
michael@0 1023 fMaxTextureSize = other.fMaxTextureSize;
michael@0 1024 fMaxSampleCount = other.fMaxSampleCount;
michael@0 1025
michael@0 1026 memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
michael@0 1027
michael@0 1028 return *this;
michael@0 1029 }
michael@0 1030
michael@0 1031 SkString GrDrawTargetCaps::dump() const {
michael@0 1032 SkString r;
michael@0 1033 static const char* gNY[] = {"NO", "YES"};
michael@0 1034 r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
michael@0 1035 r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]);
michael@0 1036 r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
michael@0 1037 r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
michael@0 1038 r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
michael@0 1039 r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
michael@0 1040 r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
michael@0 1041 r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
michael@0 1042 r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
michael@0 1043 r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
michael@0 1044 r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
michael@0 1045 r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
michael@0 1046 r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]);
michael@0 1047 r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]);
michael@0 1048 r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
michael@0 1049 r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
michael@0 1050 r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
michael@0 1051
michael@0 1052 static const char* kConfigNames[] = {
michael@0 1053 "Unknown", // kUnknown_GrPixelConfig
michael@0 1054 "Alpha8", // kAlpha_8_GrPixelConfig,
michael@0 1055 "Index8", // kIndex_8_GrPixelConfig,
michael@0 1056 "RGB565", // kRGB_565_GrPixelConfig,
michael@0 1057 "RGBA444", // kRGBA_4444_GrPixelConfig,
michael@0 1058 "RGBA8888", // kRGBA_8888_GrPixelConfig,
michael@0 1059 "BGRA8888", // kBGRA_8888_GrPixelConfig,
michael@0 1060 };
michael@0 1061 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
michael@0 1062 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
michael@0 1063 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
michael@0 1064 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
michael@0 1065 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
michael@0 1066 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
michael@0 1067 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
michael@0 1068 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
michael@0 1069
michael@0 1070 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
michael@0 1071 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
michael@0 1072 for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i) {
michael@0 1073 if (i != kUnknown_GrPixelConfig) {
michael@0 1074 r.appendf("%s is renderable: %s, with MSAA: %s\n",
michael@0 1075 kConfigNames[i],
michael@0 1076 gNY[fConfigRenderSupport[i][0]],
michael@0 1077 gNY[fConfigRenderSupport[i][1]]);
michael@0 1078 }
michael@0 1079 }
michael@0 1080 return r;
michael@0 1081 }

mercurial