1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrDrawTarget.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1081 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2010 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 + 1.14 +#include "GrDrawTarget.h" 1.15 +#include "GrContext.h" 1.16 +#include "GrDrawTargetCaps.h" 1.17 +#include "GrPath.h" 1.18 +#include "GrRenderTarget.h" 1.19 +#include "GrTexture.h" 1.20 +#include "GrVertexBuffer.h" 1.21 + 1.22 +#include "SkStrokeRec.h" 1.23 + 1.24 +//////////////////////////////////////////////////////////////////////////////// 1.25 + 1.26 +GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) { 1.27 + fPrimitiveType = di.fPrimitiveType; 1.28 + fStartVertex = di.fStartVertex; 1.29 + fStartIndex = di.fStartIndex; 1.30 + fVertexCount = di.fVertexCount; 1.31 + fIndexCount = di.fIndexCount; 1.32 + 1.33 + fInstanceCount = di.fInstanceCount; 1.34 + fVerticesPerInstance = di.fVerticesPerInstance; 1.35 + fIndicesPerInstance = di.fIndicesPerInstance; 1.36 + 1.37 + if (NULL != di.fDevBounds) { 1.38 + SkASSERT(di.fDevBounds == &di.fDevBoundsStorage); 1.39 + fDevBoundsStorage = di.fDevBoundsStorage; 1.40 + fDevBounds = &fDevBoundsStorage; 1.41 + } else { 1.42 + fDevBounds = NULL; 1.43 + } 1.44 + 1.45 + fDstCopy = di.fDstCopy; 1.46 + 1.47 + return *this; 1.48 +} 1.49 + 1.50 +#ifdef SK_DEBUG 1.51 +bool GrDrawTarget::DrawInfo::isInstanced() const { 1.52 + if (fInstanceCount > 0) { 1.53 + SkASSERT(0 == fIndexCount % fIndicesPerInstance); 1.54 + SkASSERT(0 == fVertexCount % fVerticesPerInstance); 1.55 + SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount); 1.56 + SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount); 1.57 + // there is no way to specify a non-zero start index to drawIndexedInstances(). 1.58 + SkASSERT(0 == fStartIndex); 1.59 + return true; 1.60 + } else { 1.61 + SkASSERT(!fVerticesPerInstance); 1.62 + SkASSERT(!fIndicesPerInstance); 1.63 + return false; 1.64 + } 1.65 +} 1.66 +#endif 1.67 + 1.68 +void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) { 1.69 + SkASSERT(this->isInstanced()); 1.70 + SkASSERT(instanceOffset + fInstanceCount >= 0); 1.71 + fInstanceCount += instanceOffset; 1.72 + fVertexCount = fVerticesPerInstance * fInstanceCount; 1.73 + fIndexCount = fIndicesPerInstance * fInstanceCount; 1.74 +} 1.75 + 1.76 +void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) { 1.77 + fStartVertex += vertexOffset; 1.78 + SkASSERT(fStartVertex >= 0); 1.79 +} 1.80 + 1.81 +void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) { 1.82 + SkASSERT(this->isIndexed()); 1.83 + fStartIndex += indexOffset; 1.84 + SkASSERT(fStartIndex >= 0); 1.85 +} 1.86 + 1.87 +//////////////////////////////////////////////////////////////////////////////// 1.88 + 1.89 +#define DEBUG_INVAL_BUFFER 0xdeadcafe 1.90 +#define DEBUG_INVAL_START_IDX -1 1.91 + 1.92 +GrDrawTarget::GrDrawTarget(GrContext* context) 1.93 + : fClip(NULL) 1.94 + , fContext(context) 1.95 + , fPushGpuTraceCount(0) { 1.96 + SkASSERT(NULL != context); 1.97 + 1.98 + fDrawState = &fDefaultDrawState; 1.99 + // We assume that fDrawState always owns a ref to the object it points at. 1.100 + fDefaultDrawState.ref(); 1.101 + GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); 1.102 +#ifdef SK_DEBUG 1.103 + geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; 1.104 + geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 1.105 + geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; 1.106 + geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 1.107 +#endif 1.108 + geoSrc.fVertexSrc = kNone_GeometrySrcType; 1.109 + geoSrc.fIndexSrc = kNone_GeometrySrcType; 1.110 +} 1.111 + 1.112 +GrDrawTarget::~GrDrawTarget() { 1.113 + SkASSERT(1 == fGeoSrcStateStack.count()); 1.114 + SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back()); 1.115 + SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc); 1.116 + SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc); 1.117 + fDrawState->unref(); 1.118 +} 1.119 + 1.120 +void GrDrawTarget::releaseGeometry() { 1.121 + int popCnt = fGeoSrcStateStack.count() - 1; 1.122 + while (popCnt) { 1.123 + this->popGeometrySource(); 1.124 + --popCnt; 1.125 + } 1.126 + this->resetVertexSource(); 1.127 + this->resetIndexSource(); 1.128 +} 1.129 + 1.130 +void GrDrawTarget::setClip(const GrClipData* clip) { 1.131 + clipWillBeSet(clip); 1.132 + fClip = clip; 1.133 +} 1.134 + 1.135 +const GrClipData* GrDrawTarget::getClip() const { 1.136 + return fClip; 1.137 +} 1.138 + 1.139 +void GrDrawTarget::setDrawState(GrDrawState* drawState) { 1.140 + SkASSERT(NULL != fDrawState); 1.141 + if (NULL == drawState) { 1.142 + drawState = &fDefaultDrawState; 1.143 + } 1.144 + if (fDrawState != drawState) { 1.145 + fDrawState->unref(); 1.146 + drawState->ref(); 1.147 + fDrawState = drawState; 1.148 + } 1.149 +} 1.150 + 1.151 +bool GrDrawTarget::reserveVertexSpace(size_t vertexSize, 1.152 + int vertexCount, 1.153 + void** vertices) { 1.154 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.155 + bool acquired = false; 1.156 + if (vertexCount > 0) { 1.157 + SkASSERT(NULL != vertices); 1.158 + this->releasePreviousVertexSource(); 1.159 + geoSrc.fVertexSrc = kNone_GeometrySrcType; 1.160 + 1.161 + acquired = this->onReserveVertexSpace(vertexSize, 1.162 + vertexCount, 1.163 + vertices); 1.164 + } 1.165 + if (acquired) { 1.166 + geoSrc.fVertexSrc = kReserved_GeometrySrcType; 1.167 + geoSrc.fVertexCount = vertexCount; 1.168 + geoSrc.fVertexSize = vertexSize; 1.169 + } else if (NULL != vertices) { 1.170 + *vertices = NULL; 1.171 + } 1.172 + return acquired; 1.173 +} 1.174 + 1.175 +bool GrDrawTarget::reserveIndexSpace(int indexCount, 1.176 + void** indices) { 1.177 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.178 + bool acquired = false; 1.179 + if (indexCount > 0) { 1.180 + SkASSERT(NULL != indices); 1.181 + this->releasePreviousIndexSource(); 1.182 + geoSrc.fIndexSrc = kNone_GeometrySrcType; 1.183 + 1.184 + acquired = this->onReserveIndexSpace(indexCount, indices); 1.185 + } 1.186 + if (acquired) { 1.187 + geoSrc.fIndexSrc = kReserved_GeometrySrcType; 1.188 + geoSrc.fIndexCount = indexCount; 1.189 + } else if (NULL != indices) { 1.190 + *indices = NULL; 1.191 + } 1.192 + return acquired; 1.193 + 1.194 +} 1.195 + 1.196 +bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount, 1.197 + int indexCount, 1.198 + void** vertices, 1.199 + void** indices) { 1.200 + size_t vertexSize = this->drawState()->getVertexSize(); 1.201 + this->willReserveVertexAndIndexSpace(vertexCount, indexCount); 1.202 + if (vertexCount) { 1.203 + if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) { 1.204 + if (indexCount) { 1.205 + this->resetIndexSource(); 1.206 + } 1.207 + return false; 1.208 + } 1.209 + } 1.210 + if (indexCount) { 1.211 + if (!this->reserveIndexSpace(indexCount, indices)) { 1.212 + if (vertexCount) { 1.213 + this->resetVertexSource(); 1.214 + } 1.215 + return false; 1.216 + } 1.217 + } 1.218 + return true; 1.219 +} 1.220 + 1.221 +bool GrDrawTarget::geometryHints(int32_t* vertexCount, 1.222 + int32_t* indexCount) const { 1.223 + if (NULL != vertexCount) { 1.224 + *vertexCount = -1; 1.225 + } 1.226 + if (NULL != indexCount) { 1.227 + *indexCount = -1; 1.228 + } 1.229 + return false; 1.230 +} 1.231 + 1.232 +void GrDrawTarget::releasePreviousVertexSource() { 1.233 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.234 + switch (geoSrc.fVertexSrc) { 1.235 + case kNone_GeometrySrcType: 1.236 + break; 1.237 + case kArray_GeometrySrcType: 1.238 + this->releaseVertexArray(); 1.239 + break; 1.240 + case kReserved_GeometrySrcType: 1.241 + this->releaseReservedVertexSpace(); 1.242 + break; 1.243 + case kBuffer_GeometrySrcType: 1.244 + geoSrc.fVertexBuffer->unref(); 1.245 +#ifdef SK_DEBUG 1.246 + geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 1.247 +#endif 1.248 + break; 1.249 + default: 1.250 + GrCrash("Unknown Vertex Source Type."); 1.251 + break; 1.252 + } 1.253 +} 1.254 + 1.255 +void GrDrawTarget::releasePreviousIndexSource() { 1.256 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.257 + switch (geoSrc.fIndexSrc) { 1.258 + case kNone_GeometrySrcType: // these two don't require 1.259 + break; 1.260 + case kArray_GeometrySrcType: 1.261 + this->releaseIndexArray(); 1.262 + break; 1.263 + case kReserved_GeometrySrcType: 1.264 + this->releaseReservedIndexSpace(); 1.265 + break; 1.266 + case kBuffer_GeometrySrcType: 1.267 + geoSrc.fIndexBuffer->unref(); 1.268 +#ifdef SK_DEBUG 1.269 + geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 1.270 +#endif 1.271 + break; 1.272 + default: 1.273 + GrCrash("Unknown Index Source Type."); 1.274 + break; 1.275 + } 1.276 +} 1.277 + 1.278 +void GrDrawTarget::setVertexSourceToArray(const void* vertexArray, 1.279 + int vertexCount) { 1.280 + this->releasePreviousVertexSource(); 1.281 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.282 + geoSrc.fVertexSrc = kArray_GeometrySrcType; 1.283 + geoSrc.fVertexSize = this->drawState()->getVertexSize(); 1.284 + geoSrc.fVertexCount = vertexCount; 1.285 + this->onSetVertexSourceToArray(vertexArray, vertexCount); 1.286 +} 1.287 + 1.288 +void GrDrawTarget::setIndexSourceToArray(const void* indexArray, 1.289 + int indexCount) { 1.290 + this->releasePreviousIndexSource(); 1.291 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.292 + geoSrc.fIndexSrc = kArray_GeometrySrcType; 1.293 + geoSrc.fIndexCount = indexCount; 1.294 + this->onSetIndexSourceToArray(indexArray, indexCount); 1.295 +} 1.296 + 1.297 +void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) { 1.298 + this->releasePreviousVertexSource(); 1.299 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.300 + geoSrc.fVertexSrc = kBuffer_GeometrySrcType; 1.301 + geoSrc.fVertexBuffer = buffer; 1.302 + buffer->ref(); 1.303 + geoSrc.fVertexSize = this->drawState()->getVertexSize(); 1.304 +} 1.305 + 1.306 +void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { 1.307 + this->releasePreviousIndexSource(); 1.308 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.309 + geoSrc.fIndexSrc = kBuffer_GeometrySrcType; 1.310 + geoSrc.fIndexBuffer = buffer; 1.311 + buffer->ref(); 1.312 +} 1.313 + 1.314 +void GrDrawTarget::resetVertexSource() { 1.315 + this->releasePreviousVertexSource(); 1.316 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.317 + geoSrc.fVertexSrc = kNone_GeometrySrcType; 1.318 +} 1.319 + 1.320 +void GrDrawTarget::resetIndexSource() { 1.321 + this->releasePreviousIndexSource(); 1.322 + GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.323 + geoSrc.fIndexSrc = kNone_GeometrySrcType; 1.324 +} 1.325 + 1.326 +void GrDrawTarget::pushGeometrySource() { 1.327 + this->geometrySourceWillPush(); 1.328 + GeometrySrcState& newState = fGeoSrcStateStack.push_back(); 1.329 + newState.fIndexSrc = kNone_GeometrySrcType; 1.330 + newState.fVertexSrc = kNone_GeometrySrcType; 1.331 +#ifdef SK_DEBUG 1.332 + newState.fVertexCount = ~0; 1.333 + newState.fVertexBuffer = (GrVertexBuffer*)~0; 1.334 + newState.fIndexCount = ~0; 1.335 + newState.fIndexBuffer = (GrIndexBuffer*)~0; 1.336 +#endif 1.337 +} 1.338 + 1.339 +void GrDrawTarget::popGeometrySource() { 1.340 + // if popping last element then pops are unbalanced with pushes 1.341 + SkASSERT(fGeoSrcStateStack.count() > 1); 1.342 + 1.343 + this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); 1.344 + this->releasePreviousVertexSource(); 1.345 + this->releasePreviousIndexSource(); 1.346 + fGeoSrcStateStack.pop_back(); 1.347 +} 1.348 + 1.349 +//////////////////////////////////////////////////////////////////////////////// 1.350 + 1.351 +bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, 1.352 + int startIndex, int vertexCount, 1.353 + int indexCount) const { 1.354 + const GrDrawState& drawState = this->getDrawState(); 1.355 +#ifdef SK_DEBUG 1.356 + const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 1.357 + int maxVertex = startVertex + vertexCount; 1.358 + int maxValidVertex; 1.359 + switch (geoSrc.fVertexSrc) { 1.360 + case kNone_GeometrySrcType: 1.361 + GrCrash("Attempting to draw without vertex src."); 1.362 + case kReserved_GeometrySrcType: // fallthrough 1.363 + case kArray_GeometrySrcType: 1.364 + maxValidVertex = geoSrc.fVertexCount; 1.365 + break; 1.366 + case kBuffer_GeometrySrcType: 1.367 + maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize); 1.368 + break; 1.369 + } 1.370 + if (maxVertex > maxValidVertex) { 1.371 + GrCrash("Drawing outside valid vertex range."); 1.372 + } 1.373 + if (indexCount > 0) { 1.374 + int maxIndex = startIndex + indexCount; 1.375 + int maxValidIndex; 1.376 + switch (geoSrc.fIndexSrc) { 1.377 + case kNone_GeometrySrcType: 1.378 + GrCrash("Attempting to draw indexed geom without index src."); 1.379 + case kReserved_GeometrySrcType: // fallthrough 1.380 + case kArray_GeometrySrcType: 1.381 + maxValidIndex = geoSrc.fIndexCount; 1.382 + break; 1.383 + case kBuffer_GeometrySrcType: 1.384 + maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t)); 1.385 + break; 1.386 + } 1.387 + if (maxIndex > maxValidIndex) { 1.388 + GrCrash("Index reads outside valid index range."); 1.389 + } 1.390 + } 1.391 + 1.392 + SkASSERT(NULL != drawState.getRenderTarget()); 1.393 + 1.394 + for (int s = 0; s < drawState.numColorStages(); ++s) { 1.395 + const GrEffectRef& effect = *drawState.getColorStage(s).getEffect(); 1.396 + int numTextures = effect->numTextures(); 1.397 + for (int t = 0; t < numTextures; ++t) { 1.398 + GrTexture* texture = effect->texture(t); 1.399 + SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 1.400 + } 1.401 + } 1.402 + for (int s = 0; s < drawState.numCoverageStages(); ++s) { 1.403 + const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect(); 1.404 + int numTextures = effect->numTextures(); 1.405 + for (int t = 0; t < numTextures; ++t) { 1.406 + GrTexture* texture = effect->texture(t); 1.407 + SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 1.408 + } 1.409 + } 1.410 + 1.411 + SkASSERT(drawState.validateVertexAttribs()); 1.412 +#endif 1.413 + if (NULL == drawState.getRenderTarget()) { 1.414 + return false; 1.415 + } 1.416 + return true; 1.417 +} 1.418 + 1.419 +bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) { 1.420 + if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) { 1.421 + return true; 1.422 + } 1.423 + GrRenderTarget* rt = this->drawState()->getRenderTarget(); 1.424 + SkIRect copyRect; 1.425 + const GrClipData* clip = this->getClip(); 1.426 + clip->getConservativeBounds(rt, ©Rect); 1.427 + 1.428 + if (NULL != drawBounds) { 1.429 + SkIRect drawIBounds; 1.430 + drawBounds->roundOut(&drawIBounds); 1.431 + if (!copyRect.intersect(drawIBounds)) { 1.432 +#ifdef SK_DEBUG 1.433 + GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 1.434 +#endif 1.435 + return false; 1.436 + } 1.437 + } else { 1.438 +#ifdef SK_DEBUG 1.439 + //GrPrintf("No dev bounds when dst copy is made.\n"); 1.440 +#endif 1.441 + } 1.442 + 1.443 + // MSAA consideration: When there is support for reading MSAA samples in the shader we could 1.444 + // have per-sample dst values by making the copy multisampled. 1.445 + GrTextureDesc desc; 1.446 + this->initCopySurfaceDstDesc(rt, &desc); 1.447 + desc.fWidth = copyRect.width(); 1.448 + desc.fHeight = copyRect.height(); 1.449 + 1.450 + GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); 1.451 + 1.452 + if (NULL == ast.texture()) { 1.453 + GrPrintf("Failed to create temporary copy of destination texture.\n"); 1.454 + return false; 1.455 + } 1.456 + SkIPoint dstPoint = {0, 0}; 1.457 + if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) { 1.458 + dstCopy->setTexture(ast.texture()); 1.459 + dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); 1.460 + return true; 1.461 + } else { 1.462 + return false; 1.463 + } 1.464 +} 1.465 + 1.466 +void GrDrawTarget::drawIndexed(GrPrimitiveType type, 1.467 + int startVertex, 1.468 + int startIndex, 1.469 + int vertexCount, 1.470 + int indexCount, 1.471 + const SkRect* devBounds) { 1.472 + if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) { 1.473 + DrawInfo info; 1.474 + info.fPrimitiveType = type; 1.475 + info.fStartVertex = startVertex; 1.476 + info.fStartIndex = startIndex; 1.477 + info.fVertexCount = vertexCount; 1.478 + info.fIndexCount = indexCount; 1.479 + 1.480 + info.fInstanceCount = 0; 1.481 + info.fVerticesPerInstance = 0; 1.482 + info.fIndicesPerInstance = 0; 1.483 + 1.484 + if (NULL != devBounds) { 1.485 + info.setDevBounds(*devBounds); 1.486 + } 1.487 + // TODO: We should continue with incorrect blending. 1.488 + if (!this->setupDstReadIfNecessary(&info)) { 1.489 + return; 1.490 + } 1.491 + this->onDraw(info); 1.492 + } 1.493 +} 1.494 + 1.495 +void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 1.496 + int startVertex, 1.497 + int vertexCount, 1.498 + const SkRect* devBounds) { 1.499 + if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 1.500 + DrawInfo info; 1.501 + info.fPrimitiveType = type; 1.502 + info.fStartVertex = startVertex; 1.503 + info.fStartIndex = 0; 1.504 + info.fVertexCount = vertexCount; 1.505 + info.fIndexCount = 0; 1.506 + 1.507 + info.fInstanceCount = 0; 1.508 + info.fVerticesPerInstance = 0; 1.509 + info.fIndicesPerInstance = 0; 1.510 + 1.511 + if (NULL != devBounds) { 1.512 + info.setDevBounds(*devBounds); 1.513 + } 1.514 + // TODO: We should continue with incorrect blending. 1.515 + if (!this->setupDstReadIfNecessary(&info)) { 1.516 + return; 1.517 + } 1.518 + this->onDraw(info); 1.519 + } 1.520 +} 1.521 + 1.522 +void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) { 1.523 + // TODO: extract portions of checkDraw that are relevant to path stenciling. 1.524 + SkASSERT(NULL != path); 1.525 + SkASSERT(this->caps()->pathRenderingSupport()); 1.526 + SkASSERT(!SkPath::IsInverseFillType(fill)); 1.527 + this->onStencilPath(path, fill); 1.528 +} 1.529 + 1.530 +void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) { 1.531 + // TODO: extract portions of checkDraw that are relevant to path rendering. 1.532 + SkASSERT(NULL != path); 1.533 + SkASSERT(this->caps()->pathRenderingSupport()); 1.534 + const GrDrawState* drawState = &getDrawState(); 1.535 + 1.536 + SkRect devBounds; 1.537 + if (SkPath::IsInverseFillType(fill)) { 1.538 + devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()), 1.539 + SkIntToScalar(drawState->getRenderTarget()->height())); 1.540 + } else { 1.541 + devBounds = path->getBounds(); 1.542 + } 1.543 + SkMatrix viewM = drawState->getViewMatrix(); 1.544 + viewM.mapRect(&devBounds); 1.545 + 1.546 + GrDeviceCoordTexture dstCopy; 1.547 + if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) { 1.548 + return; 1.549 + } 1.550 + 1.551 + this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL); 1.552 +} 1.553 + 1.554 +void GrDrawTarget::instantGpuTraceEvent(const char* marker) { 1.555 + if (this->caps()->gpuTracingSupport()) { 1.556 + this->onInstantGpuTraceEvent(marker); 1.557 + } 1.558 +} 1.559 + 1.560 +void GrDrawTarget::pushGpuTraceEvent(const char* marker) { 1.561 + SkASSERT(fPushGpuTraceCount >= 0); 1.562 + if (this->caps()->gpuTracingSupport()) { 1.563 + this->onPushGpuTraceEvent(marker); 1.564 + ++fPushGpuTraceCount; 1.565 + } 1.566 +} 1.567 + 1.568 +void GrDrawTarget::popGpuTraceEvent() { 1.569 + SkASSERT(fPushGpuTraceCount >= 1); 1.570 + if (this->caps()->gpuTracingSupport()) { 1.571 + this->onPopGpuTraceEvent(); 1.572 + --fPushGpuTraceCount; 1.573 + } 1.574 +} 1.575 + 1.576 +//////////////////////////////////////////////////////////////////////////////// 1.577 + 1.578 +bool GrDrawTarget::willUseHWAALines() const { 1.579 + // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth 1.580 + // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when 1.581 + // our alpha is 0xff and tweaking the color for partial coverage is OK 1.582 + if (!this->caps()->hwAALineSupport() || 1.583 + !this->getDrawState().isHWAntialiasState()) { 1.584 + return false; 1.585 + } 1.586 + GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts(); 1.587 + return (GrDrawState::kDisableBlend_BlendOptFlag & opts) && 1.588 + (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts); 1.589 +} 1.590 + 1.591 +bool GrDrawTarget::canApplyCoverage() const { 1.592 + // we can correctly apply coverage if a) we have dual source blending 1.593 + // or b) one of our blend optimizations applies. 1.594 + return this->caps()->dualSourceBlendingSupport() || 1.595 + GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true); 1.596 +} 1.597 + 1.598 +//////////////////////////////////////////////////////////////////////////////// 1.599 + 1.600 +void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 1.601 + int instanceCount, 1.602 + int verticesPerInstance, 1.603 + int indicesPerInstance, 1.604 + const SkRect* devBounds) { 1.605 + if (!verticesPerInstance || !indicesPerInstance) { 1.606 + return; 1.607 + } 1.608 + 1.609 + int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 1.610 + if (!maxInstancesPerDraw) { 1.611 + return; 1.612 + } 1.613 + 1.614 + DrawInfo info; 1.615 + info.fPrimitiveType = type; 1.616 + info.fStartIndex = 0; 1.617 + info.fStartVertex = 0; 1.618 + info.fIndicesPerInstance = indicesPerInstance; 1.619 + info.fVerticesPerInstance = verticesPerInstance; 1.620 + 1.621 + // Set the same bounds for all the draws. 1.622 + if (NULL != devBounds) { 1.623 + info.setDevBounds(*devBounds); 1.624 + } 1.625 + // TODO: We should continue with incorrect blending. 1.626 + if (!this->setupDstReadIfNecessary(&info)) { 1.627 + return; 1.628 + } 1.629 + 1.630 + while (instanceCount) { 1.631 + info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw); 1.632 + info.fVertexCount = info.fInstanceCount * verticesPerInstance; 1.633 + info.fIndexCount = info.fInstanceCount * indicesPerInstance; 1.634 + 1.635 + if (this->checkDraw(type, 1.636 + info.fStartVertex, 1.637 + info.fStartIndex, 1.638 + info.fVertexCount, 1.639 + info.fIndexCount)) { 1.640 + this->onDraw(info); 1.641 + } 1.642 + info.fStartVertex += info.fVertexCount; 1.643 + instanceCount -= info.fInstanceCount; 1.644 + } 1.645 +} 1.646 + 1.647 +//////////////////////////////////////////////////////////////////////////////// 1.648 + 1.649 +namespace { 1.650 + 1.651 +// position + (optional) texture coord 1.652 +extern const GrVertexAttrib gBWRectPosUVAttribs[] = { 1.653 + {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 1.654 + {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding} 1.655 +}; 1.656 + 1.657 +void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) { 1.658 + if (hasUVs) { 1.659 + drawState->setVertexAttribs<gBWRectPosUVAttribs>(2); 1.660 + } else { 1.661 + drawState->setVertexAttribs<gBWRectPosUVAttribs>(1); 1.662 + } 1.663 +} 1.664 + 1.665 +}; 1.666 + 1.667 +void GrDrawTarget::onDrawRect(const SkRect& rect, 1.668 + const SkMatrix* matrix, 1.669 + const SkRect* localRect, 1.670 + const SkMatrix* localMatrix) { 1.671 + 1.672 + GrDrawState::AutoViewMatrixRestore avmr; 1.673 + if (NULL != matrix) { 1.674 + avmr.set(this->drawState(), *matrix); 1.675 + } 1.676 + 1.677 + set_vertex_attributes(this->drawState(), NULL != localRect); 1.678 + 1.679 + AutoReleaseGeometry geo(this, 4, 0); 1.680 + if (!geo.succeeded()) { 1.681 + GrPrintf("Failed to get space for vertices!\n"); 1.682 + return; 1.683 + } 1.684 + 1.685 + size_t vsize = this->drawState()->getVertexSize(); 1.686 + geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); 1.687 + if (NULL != localRect) { 1.688 + GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + 1.689 + sizeof(GrPoint)); 1.690 + coords->setRectFan(localRect->fLeft, localRect->fTop, 1.691 + localRect->fRight, localRect->fBottom, 1.692 + vsize); 1.693 + if (NULL != localMatrix) { 1.694 + localMatrix->mapPointsWithStride(coords, vsize, 4); 1.695 + } 1.696 + } 1.697 + SkRect bounds; 1.698 + this->getDrawState().getViewMatrix().mapRect(&bounds, rect); 1.699 + 1.700 + this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds); 1.701 +} 1.702 + 1.703 +void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) { 1.704 +} 1.705 + 1.706 +//////////////////////////////////////////////////////////////////////////////// 1.707 + 1.708 +GrDrawTarget::AutoStateRestore::AutoStateRestore() { 1.709 + fDrawTarget = NULL; 1.710 +} 1.711 + 1.712 +GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 1.713 + ASRInit init, 1.714 + const SkMatrix* vm) { 1.715 + fDrawTarget = NULL; 1.716 + this->set(target, init, vm); 1.717 +} 1.718 + 1.719 +GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 1.720 + if (NULL != fDrawTarget) { 1.721 + fDrawTarget->setDrawState(fSavedState); 1.722 + fSavedState->unref(); 1.723 + } 1.724 +} 1.725 + 1.726 +void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) { 1.727 + SkASSERT(NULL == fDrawTarget); 1.728 + fDrawTarget = target; 1.729 + fSavedState = target->drawState(); 1.730 + SkASSERT(fSavedState); 1.731 + fSavedState->ref(); 1.732 + if (kReset_ASRInit == init) { 1.733 + if (NULL == vm) { 1.734 + // calls the default cons 1.735 + fTempState.init(); 1.736 + } else { 1.737 + SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm)); 1.738 + } 1.739 + } else { 1.740 + SkASSERT(kPreserve_ASRInit == init); 1.741 + if (NULL == vm) { 1.742 + fTempState.set(*fSavedState); 1.743 + } else { 1.744 + SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm)); 1.745 + } 1.746 + } 1.747 + target->setDrawState(fTempState.get()); 1.748 +} 1.749 + 1.750 +bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) { 1.751 + SkASSERT(NULL == fDrawTarget); 1.752 + fDrawTarget = target; 1.753 + fSavedState = target->drawState(); 1.754 + SkASSERT(fSavedState); 1.755 + fSavedState->ref(); 1.756 + if (kReset_ASRInit == init) { 1.757 + // calls the default cons 1.758 + fTempState.init(); 1.759 + } else { 1.760 + SkASSERT(kPreserve_ASRInit == init); 1.761 + // calls the copy cons 1.762 + fTempState.set(*fSavedState); 1.763 + if (!fTempState.get()->setIdentityViewMatrix()) { 1.764 + // let go of any resources held by the temp 1.765 + fTempState.get()->reset(); 1.766 + fDrawTarget = NULL; 1.767 + fSavedState->unref(); 1.768 + fSavedState = NULL; 1.769 + return false; 1.770 + } 1.771 + } 1.772 + target->setDrawState(fTempState.get()); 1.773 + return true; 1.774 +} 1.775 + 1.776 +//////////////////////////////////////////////////////////////////////////////// 1.777 + 1.778 +GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 1.779 + GrDrawTarget* target, 1.780 + int vertexCount, 1.781 + int indexCount) { 1.782 + fTarget = NULL; 1.783 + this->set(target, vertexCount, indexCount); 1.784 +} 1.785 + 1.786 +GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 1.787 + fTarget = NULL; 1.788 +} 1.789 + 1.790 +GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 1.791 + this->reset(); 1.792 +} 1.793 + 1.794 +bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 1.795 + int vertexCount, 1.796 + int indexCount) { 1.797 + this->reset(); 1.798 + fTarget = target; 1.799 + bool success = true; 1.800 + if (NULL != fTarget) { 1.801 + fTarget = target; 1.802 + success = target->reserveVertexAndIndexSpace(vertexCount, 1.803 + indexCount, 1.804 + &fVertices, 1.805 + &fIndices); 1.806 + if (!success) { 1.807 + fTarget = NULL; 1.808 + this->reset(); 1.809 + } 1.810 + } 1.811 + SkASSERT(success == (NULL != fTarget)); 1.812 + return success; 1.813 +} 1.814 + 1.815 +void GrDrawTarget::AutoReleaseGeometry::reset() { 1.816 + if (NULL != fTarget) { 1.817 + if (NULL != fVertices) { 1.818 + fTarget->resetVertexSource(); 1.819 + } 1.820 + if (NULL != fIndices) { 1.821 + fTarget->resetIndexSource(); 1.822 + } 1.823 + fTarget = NULL; 1.824 + } 1.825 + fVertices = NULL; 1.826 + fIndices = NULL; 1.827 +} 1.828 + 1.829 +GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 1.830 + fTarget = target; 1.831 + fClip = fTarget->getClip(); 1.832 + fStack.init(); 1.833 + fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 1.834 + fReplacementClip.fClipStack = fStack.get(); 1.835 + target->setClip(&fReplacementClip); 1.836 +} 1.837 + 1.838 +namespace { 1.839 +// returns true if the read/written rect intersects the src/dst and false if not. 1.840 +bool clip_srcrect_and_dstpoint(const GrSurface* dst, 1.841 + const GrSurface* src, 1.842 + const SkIRect& srcRect, 1.843 + const SkIPoint& dstPoint, 1.844 + SkIRect* clippedSrcRect, 1.845 + SkIPoint* clippedDstPoint) { 1.846 + *clippedSrcRect = srcRect; 1.847 + *clippedDstPoint = dstPoint; 1.848 + 1.849 + // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 1.850 + if (clippedSrcRect->fLeft < 0) { 1.851 + clippedDstPoint->fX -= clippedSrcRect->fLeft; 1.852 + clippedSrcRect->fLeft = 0; 1.853 + } 1.854 + if (clippedDstPoint->fX < 0) { 1.855 + clippedSrcRect->fLeft -= clippedDstPoint->fX; 1.856 + clippedDstPoint->fX = 0; 1.857 + } 1.858 + 1.859 + // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 1.860 + if (clippedSrcRect->fTop < 0) { 1.861 + clippedDstPoint->fY -= clippedSrcRect->fTop; 1.862 + clippedSrcRect->fTop = 0; 1.863 + } 1.864 + if (clippedDstPoint->fY < 0) { 1.865 + clippedSrcRect->fTop -= clippedDstPoint->fY; 1.866 + clippedDstPoint->fY = 0; 1.867 + } 1.868 + 1.869 + // clip the right edge to the src and dst bounds. 1.870 + if (clippedSrcRect->fRight > src->width()) { 1.871 + clippedSrcRect->fRight = src->width(); 1.872 + } 1.873 + if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 1.874 + clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 1.875 + } 1.876 + 1.877 + // clip the bottom edge to the src and dst bounds. 1.878 + if (clippedSrcRect->fBottom > src->height()) { 1.879 + clippedSrcRect->fBottom = src->height(); 1.880 + } 1.881 + if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 1.882 + clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 1.883 + } 1.884 + 1.885 + // The above clipping steps may have inverted the rect if it didn't intersect either the src or 1.886 + // dst bounds. 1.887 + return !clippedSrcRect->isEmpty(); 1.888 +} 1.889 +} 1.890 + 1.891 +bool GrDrawTarget::copySurface(GrSurface* dst, 1.892 + GrSurface* src, 1.893 + const SkIRect& srcRect, 1.894 + const SkIPoint& dstPoint) { 1.895 + SkASSERT(NULL != dst); 1.896 + SkASSERT(NULL != src); 1.897 + 1.898 + SkIRect clippedSrcRect; 1.899 + SkIPoint clippedDstPoint; 1.900 + // If the rect is outside the src or dst then we've already succeeded. 1.901 + if (!clip_srcrect_and_dstpoint(dst, 1.902 + src, 1.903 + srcRect, 1.904 + dstPoint, 1.905 + &clippedSrcRect, 1.906 + &clippedDstPoint)) { 1.907 + SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint)); 1.908 + return true; 1.909 + } 1.910 + 1.911 + bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 1.912 + SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)); 1.913 + return result; 1.914 +} 1.915 + 1.916 +bool GrDrawTarget::canCopySurface(GrSurface* dst, 1.917 + GrSurface* src, 1.918 + const SkIRect& srcRect, 1.919 + const SkIPoint& dstPoint) { 1.920 + SkASSERT(NULL != dst); 1.921 + SkASSERT(NULL != src); 1.922 + 1.923 + SkIRect clippedSrcRect; 1.924 + SkIPoint clippedDstPoint; 1.925 + // If the rect is outside the src or dst then we're guaranteed success 1.926 + if (!clip_srcrect_and_dstpoint(dst, 1.927 + src, 1.928 + srcRect, 1.929 + dstPoint, 1.930 + &clippedSrcRect, 1.931 + &clippedDstPoint)) { 1.932 + return true; 1.933 + } 1.934 + return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 1.935 +} 1.936 + 1.937 +bool GrDrawTarget::onCanCopySurface(GrSurface* dst, 1.938 + GrSurface* src, 1.939 + const SkIRect& srcRect, 1.940 + const SkIPoint& dstPoint) { 1.941 + // Check that the read/write rects are contained within the src/dst bounds. 1.942 + SkASSERT(!srcRect.isEmpty()); 1.943 + SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect)); 1.944 + SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0); 1.945 + SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() && 1.946 + dstPoint.fY + srcRect.height() <= dst->height()); 1.947 + 1.948 + return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture(); 1.949 +} 1.950 + 1.951 +bool GrDrawTarget::onCopySurface(GrSurface* dst, 1.952 + GrSurface* src, 1.953 + const SkIRect& srcRect, 1.954 + const SkIPoint& dstPoint) { 1.955 + if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) { 1.956 + return false; 1.957 + } 1.958 + 1.959 + GrRenderTarget* rt = dst->asRenderTarget(); 1.960 + GrTexture* tex = src->asTexture(); 1.961 + 1.962 + GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit); 1.963 + this->drawState()->setRenderTarget(rt); 1.964 + SkMatrix matrix; 1.965 + matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX), 1.966 + SkIntToScalar(srcRect.fTop - dstPoint.fY)); 1.967 + matrix.postIDiv(tex->width(), tex->height()); 1.968 + this->drawState()->addColorTextureEffect(tex, matrix); 1.969 + SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, 1.970 + dstPoint.fY, 1.971 + srcRect.width(), 1.972 + srcRect.height()); 1.973 + this->drawSimpleRect(dstRect); 1.974 + return true; 1.975 +} 1.976 + 1.977 +void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) { 1.978 + // Make the dst of the copy be a render target because the default copySurface draws to the dst. 1.979 + desc->fOrigin = kDefault_GrSurfaceOrigin; 1.980 + desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 1.981 + desc->fConfig = src->config(); 1.982 +} 1.983 + 1.984 +/////////////////////////////////////////////////////////////////////////////// 1.985 + 1.986 +void GrDrawTargetCaps::reset() { 1.987 + f8BitPaletteSupport = false; 1.988 + fMipMapSupport = false; 1.989 + fNPOTTextureTileSupport = false; 1.990 + fTwoSidedStencilSupport = false; 1.991 + fStencilWrapOpsSupport = false; 1.992 + fHWAALineSupport = false; 1.993 + fShaderDerivativeSupport = false; 1.994 + fGeometryShaderSupport = false; 1.995 + fDualSourceBlendingSupport = false; 1.996 + fBufferLockSupport = false; 1.997 + fPathRenderingSupport = false; 1.998 + fDstReadInShaderSupport = false; 1.999 + fReuseScratchTextures = true; 1.1000 + fGpuTracingSupport = false; 1.1001 + 1.1002 + fMaxRenderTargetSize = 0; 1.1003 + fMaxTextureSize = 0; 1.1004 + fMaxSampleCount = 0; 1.1005 + 1.1006 + memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport)); 1.1007 +} 1.1008 + 1.1009 +GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 1.1010 + f8BitPaletteSupport = other.f8BitPaletteSupport; 1.1011 + fMipMapSupport = other.fMipMapSupport; 1.1012 + fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 1.1013 + fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 1.1014 + fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 1.1015 + fHWAALineSupport = other.fHWAALineSupport; 1.1016 + fShaderDerivativeSupport = other.fShaderDerivativeSupport; 1.1017 + fGeometryShaderSupport = other.fGeometryShaderSupport; 1.1018 + fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 1.1019 + fBufferLockSupport = other.fBufferLockSupport; 1.1020 + fPathRenderingSupport = other.fPathRenderingSupport; 1.1021 + fDstReadInShaderSupport = other.fDstReadInShaderSupport; 1.1022 + fReuseScratchTextures = other.fReuseScratchTextures; 1.1023 + fGpuTracingSupport = other.fGpuTracingSupport; 1.1024 + 1.1025 + fMaxRenderTargetSize = other.fMaxRenderTargetSize; 1.1026 + fMaxTextureSize = other.fMaxTextureSize; 1.1027 + fMaxSampleCount = other.fMaxSampleCount; 1.1028 + 1.1029 + memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport)); 1.1030 + 1.1031 + return *this; 1.1032 +} 1.1033 + 1.1034 +SkString GrDrawTargetCaps::dump() const { 1.1035 + SkString r; 1.1036 + static const char* gNY[] = {"NO", "YES"}; 1.1037 + r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); 1.1038 + r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); 1.1039 + r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 1.1040 + r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 1.1041 + r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 1.1042 + r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 1.1043 + r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 1.1044 + r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 1.1045 + r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); 1.1046 + r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); 1.1047 + r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); 1.1048 + r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 1.1049 + r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 1.1050 + r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); 1.1051 + r.appendf("Max Texture Size : %d\n", fMaxTextureSize); 1.1052 + r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 1.1053 + r.appendf("Max Sample Count : %d\n", fMaxSampleCount); 1.1054 + 1.1055 + static const char* kConfigNames[] = { 1.1056 + "Unknown", // kUnknown_GrPixelConfig 1.1057 + "Alpha8", // kAlpha_8_GrPixelConfig, 1.1058 + "Index8", // kIndex_8_GrPixelConfig, 1.1059 + "RGB565", // kRGB_565_GrPixelConfig, 1.1060 + "RGBA444", // kRGBA_4444_GrPixelConfig, 1.1061 + "RGBA8888", // kRGBA_8888_GrPixelConfig, 1.1062 + "BGRA8888", // kBGRA_8888_GrPixelConfig, 1.1063 + }; 1.1064 + GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); 1.1065 + GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); 1.1066 + GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); 1.1067 + GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); 1.1068 + GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); 1.1069 + GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); 1.1070 + GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); 1.1071 + GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); 1.1072 + 1.1073 + SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); 1.1074 + SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); 1.1075 + for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1.1076 + if (i != kUnknown_GrPixelConfig) { 1.1077 + r.appendf("%s is renderable: %s, with MSAA: %s\n", 1.1078 + kConfigNames[i], 1.1079 + gNY[fConfigRenderSupport[i][0]], 1.1080 + gNY[fConfigRenderSupport[i][1]]); 1.1081 + } 1.1082 + } 1.1083 + return r; 1.1084 +}