OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrContext.h" | 9 #include "GrContext.h" |
10 | 10 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 if (fGpu->caps()->pathRenderingSupport() && renderTarget->getStencilBuffer()
&& | 216 if (fGpu->caps()->pathRenderingSupport() && renderTarget->getStencilBuffer()
&& |
217 renderTarget->isMultisampled())
{ | 217 renderTarget->isMultisampled())
{ |
218 return GrStencilAndCoverTextContext::Create(this, leakyProperties); | 218 return GrStencilAndCoverTextContext::Create(this, leakyProperties); |
219 } | 219 } |
220 | 220 |
221 return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDista
nceFieldFonts); | 221 return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDista
nceFieldFonts); |
222 } | 222 } |
223 | 223 |
224 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
225 | 225 |
226 GrTexture* GrContext::createTexture(const GrSurfaceDesc& desc, const void* srcDa
ta, | 226 static void stretch_image(void* dst, |
227 size_t rowBytes) { | 227 int dstW, |
228 return fGpu->createTexture(desc, true, srcData, rowBytes); | 228 int dstH, |
| 229 const void* src, |
| 230 int srcW, |
| 231 int srcH, |
| 232 size_t bpp) { |
| 233 SkFixed dx = (srcW << 16) / dstW; |
| 234 SkFixed dy = (srcH << 16) / dstH; |
| 235 |
| 236 SkFixed y = dy >> 1; |
| 237 |
| 238 size_t dstXLimit = dstW*bpp; |
| 239 for (int j = 0; j < dstH; ++j) { |
| 240 SkFixed x = dx >> 1; |
| 241 const uint8_t* srcRow = reinterpret_cast<const uint8_t *>(src) + (y>>16)
*srcW*bpp; |
| 242 uint8_t* dstRow = reinterpret_cast<uint8_t *>(dst) + j*dstW*bpp; |
| 243 for (size_t i = 0; i < dstXLimit; i += bpp) { |
| 244 memcpy(dstRow + i, srcRow + (x>>16)*bpp, bpp); |
| 245 x += dx; |
| 246 } |
| 247 y += dy; |
| 248 } |
| 249 } |
| 250 |
| 251 enum ResizeFlags { |
| 252 /** |
| 253 * The kStretchToPOT bit is set when the texture is NPOT and is being repeat
ed or mipped but the |
| 254 * hardware doesn't support that feature. |
| 255 */ |
| 256 kStretchToPOT_ResizeFlag = 0x1, |
| 257 /** |
| 258 * The kBilerp bit can only be set when the kStretchToPOT flag is set and in
dicates whether the |
| 259 * stretched texture should be bilerped. |
| 260 */ |
| 261 kBilerp_ResizeFlag = 0x2, |
| 262 }; |
| 263 |
| 264 static uint32_t get_texture_flags(const GrGpu* gpu, |
| 265 const GrTextureParams* params, |
| 266 const GrSurfaceDesc& desc) { |
| 267 uint32_t flags = 0; |
| 268 bool tiled = params && params->isTiled(); |
| 269 if (tiled && !gpu->caps()->npotTextureTileSupport()) { |
| 270 if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) { |
| 271 flags |= kStretchToPOT_ResizeFlag; |
| 272 switch(params->filterMode()) { |
| 273 case GrTextureParams::kNone_FilterMode: |
| 274 break; |
| 275 case GrTextureParams::kBilerp_FilterMode: |
| 276 case GrTextureParams::kMipMap_FilterMode: |
| 277 flags |= kBilerp_ResizeFlag; |
| 278 break; |
| 279 } |
| 280 } |
| 281 } |
| 282 return flags; |
| 283 } |
| 284 // The desired texture is NPOT and tiled but that isn't supported by |
| 285 // the current hardware. Resize the texture to be a POT |
| 286 GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, |
| 287 const GrContentKey& origKey, |
| 288 const void* srcData, |
| 289 size_t rowBytes, |
| 290 bool filter) { |
| 291 SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, origKey
, NULL)); |
| 292 if (NULL == clampedTexture) { |
| 293 clampedTexture.reset(this->createTexture(NULL, desc, origKey, srcData, r
owBytes)); |
| 294 |
| 295 if (NULL == clampedTexture) { |
| 296 return NULL; |
| 297 } |
| 298 clampedTexture->cacheAccess().setContentKey(origKey); |
| 299 } |
| 300 |
| 301 GrSurfaceDesc rtDesc = desc; |
| 302 rtDesc.fFlags = rtDesc.fFlags | |
| 303 kRenderTarget_GrSurfaceFlag | |
| 304 kNoStencil_GrSurfaceFlag; |
| 305 rtDesc.fWidth = GrNextPow2(desc.fWidth); |
| 306 rtDesc.fHeight = GrNextPow2(desc.fHeight); |
| 307 |
| 308 GrTexture* texture = fGpu->createTexture(rtDesc, true, NULL, 0); |
| 309 |
| 310 if (texture) { |
| 311 GrPipelineBuilder pipelineBuilder; |
| 312 pipelineBuilder.setRenderTarget(texture->asRenderTarget()); |
| 313 |
| 314 // if filtering is not desired then we want to ensure all |
| 315 // texels in the resampled image are copies of texels from |
| 316 // the original. |
| 317 GrTextureParams params(SkShader::kClamp_TileMode, |
| 318 filter ? GrTextureParams::kBilerp_FilterMode : |
| 319 GrTextureParams::kNone_FilterMode); |
| 320 pipelineBuilder.addColorTextureProcessor(clampedTexture, SkMatrix::I(),
params); |
| 321 |
| 322 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | |
| 323 GrDefaultGeoProcFactory::kLocalCoord_GPType; |
| 324 SkAutoTUnref<const GrGeometryProcessor> gp( |
| 325 GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE)); |
| 326 |
| 327 GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, gp->getVertexStrid
e(), 0); |
| 328 SkASSERT(gp->getVertexStride() == 2 * sizeof(SkPoint)); |
| 329 |
| 330 if (arg.succeeded()) { |
| 331 SkPoint* verts = (SkPoint*) arg.vertices(); |
| 332 verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 *
sizeof(SkPoint)); |
| 333 verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint)); |
| 334 fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPri
mitiveType, 0, 4); |
| 335 } else { |
| 336 texture->unref(); |
| 337 texture = NULL; |
| 338 } |
| 339 } else { |
| 340 // TODO: Our CPU stretch doesn't filter. But we create separate |
| 341 // stretched textures when the texture params is either filtered or |
| 342 // not. Either implement filtered stretch blit on CPU or just create |
| 343 // one when FBO case fails. |
| 344 |
| 345 rtDesc.fFlags = kNone_GrSurfaceFlags; |
| 346 // no longer need to clamp at min RT size. |
| 347 rtDesc.fWidth = GrNextPow2(desc.fWidth); |
| 348 rtDesc.fHeight = GrNextPow2(desc.fHeight); |
| 349 |
| 350 // We shouldn't be resizing a compressed texture. |
| 351 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); |
| 352 |
| 353 size_t bpp = GrBytesPerPixel(desc.fConfig); |
| 354 GrAutoMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHe
ight); |
| 355 stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight, |
| 356 srcData, desc.fWidth, desc.fHeight, bpp); |
| 357 |
| 358 size_t stretchedRowBytes = rtDesc.fWidth * bpp; |
| 359 |
| 360 texture = fGpu->createTexture(rtDesc, true, stretchedPixels.get(), stret
chedRowBytes); |
| 361 SkASSERT(texture); |
| 362 } |
| 363 |
| 364 return texture; |
| 365 } |
| 366 |
| 367 static GrContentKey::Domain ResizeDomain() { |
| 368 static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); |
| 369 return kDomain; |
| 370 } |
| 371 |
| 372 GrTexture* GrContext::createTexture(const GrTextureParams* params, |
| 373 const GrSurfaceDesc& desc, |
| 374 const GrContentKey& origKey, |
| 375 const void* srcData, |
| 376 size_t rowBytes, |
| 377 GrContentKey* outKey) { |
| 378 GrTexture* texture; |
| 379 uint32_t flags = get_texture_flags(fGpu, params, desc); |
| 380 SkTCopyOnFirstWrite<GrContentKey> key(origKey); |
| 381 if (flags) { |
| 382 // We don't have a code path to resize compressed textures. |
| 383 if (GrPixelConfigIsCompressed(desc.fConfig)) { |
| 384 return NULL; |
| 385 } |
| 386 texture = this->createResizedTexture(desc, origKey, srcData, rowBytes, |
| 387 SkToBool(flags & kBilerp_ResizeFlag
)); |
| 388 |
| 389 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); |
| 390 builder[0] = flags; |
| 391 |
| 392 } else { |
| 393 texture = fGpu->createTexture(desc, true, srcData, rowBytes); |
| 394 } |
| 395 |
| 396 if (texture) { |
| 397 if (texture->cacheAccess().setContentKey(*key)) { |
| 398 if (outKey) { |
| 399 *outKey = *key; |
| 400 } |
| 401 } else { |
| 402 texture->unref(); |
| 403 texture = NULL; |
| 404 } |
| 405 } |
| 406 |
| 407 return texture; |
| 408 } |
| 409 |
| 410 GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc, |
| 411 const GrContentKey& origKey, |
| 412 const GrTextureParams* params) { |
| 413 uint32_t flags = get_texture_flags(fGpu, params, desc); |
| 414 SkTCopyOnFirstWrite<GrContentKey> key(origKey); |
| 415 if (flags) { |
| 416 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); |
| 417 builder[0] = flags; |
| 418 } |
| 419 |
| 420 GrGpuResource* resource = this->findAndRefCachedResource(*key); |
| 421 if (resource) { |
| 422 SkASSERT(static_cast<GrSurface*>(resource)->asTexture()); |
| 423 return static_cast<GrSurface*>(resource)->asTexture(); |
| 424 } |
| 425 return NULL; |
| 426 } |
| 427 |
| 428 bool GrContext::isTextureInCache(const GrSurfaceDesc& desc, |
| 429 const GrContentKey& origKey, |
| 430 const GrTextureParams* params) const { |
| 431 uint32_t flags = get_texture_flags(fGpu, params, desc); |
| 432 SkTCopyOnFirstWrite<GrContentKey> key(origKey); |
| 433 if (flags) { |
| 434 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); |
| 435 builder[0] = flags; |
| 436 } |
| 437 |
| 438 return fResourceCache2->hasContentKey(*key); |
229 } | 439 } |
230 | 440 |
231 GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
atch match, | 441 GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
atch match, |
232 bool calledDuringFlush) { | 442 bool calledDuringFlush) { |
233 // kNoStencil has no meaning if kRT isn't set. | 443 // kNoStencil has no meaning if kRT isn't set. |
234 SkASSERT((inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || | 444 SkASSERT((inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || |
235 !(inDesc.fFlags & kNoStencil_GrSurfaceFlag)); | 445 !(inDesc.fFlags & kNoStencil_GrSurfaceFlag)); |
236 | 446 |
237 // Make sure caller has checked for renderability if kRT is set. | 447 // Make sure caller has checked for renderability if kRT is set. |
238 SkASSERT(!(inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || | 448 SkASSERT(!(inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 // Flush the InOrderDrawBuffer to possibly free up some textures | 519 // Flush the InOrderDrawBuffer to possibly free up some textures |
310 context->fFlushToReduceCacheSize = true; | 520 context->fFlushToReduceCacheSize = true; |
311 } | 521 } |
312 | 522 |
313 GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc, | 523 GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc, |
314 void* srcData, | 524 void* srcData, |
315 size_t rowBytes) { | 525 size_t rowBytes) { |
316 return fGpu->createTexture(desc, false, srcData, rowBytes); | 526 return fGpu->createTexture(desc, false, srcData, rowBytes); |
317 } | 527 } |
318 | 528 |
| 529 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes
) const { |
| 530 if (maxTextures) { |
| 531 *maxTextures = fResourceCache2->getMaxResourceCount(); |
| 532 } |
| 533 if (maxTextureBytes) { |
| 534 *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); |
| 535 } |
| 536 } |
| 537 |
| 538 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
{ |
| 539 fResourceCache2->setLimits(maxTextures, maxTextureBytes); |
| 540 } |
| 541 |
319 int GrContext::getMaxTextureSize() const { | 542 int GrContext::getMaxTextureSize() const { |
320 return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); | 543 return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); |
321 } | 544 } |
322 | 545 |
323 int GrContext::getMaxRenderTargetSize() const { | 546 int GrContext::getMaxRenderTargetSize() const { |
324 return fGpu->caps()->maxRenderTargetSize(); | 547 return fGpu->caps()->maxRenderTargetSize(); |
325 } | 548 } |
326 | 549 |
327 int GrContext::getMaxSampleCount() const { | 550 int GrContext::getMaxSampleCount() const { |
328 return fGpu->caps()->maxSampleCount(); | 551 return fGpu->caps()->maxSampleCount(); |
329 } | 552 } |
330 | 553 |
331 /////////////////////////////////////////////////////////////////////////////// | 554 /////////////////////////////////////////////////////////////////////////////// |
332 | 555 |
333 GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) { | 556 GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) { |
334 return fGpu->wrapBackendTexture(desc); | 557 return fGpu->wrapBackendTexture(desc); |
335 } | 558 } |
336 | 559 |
337 GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe
sc& desc) { | 560 GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe
sc& desc) { |
338 return fGpu->wrapBackendRenderTarget(desc); | 561 return fGpu->wrapBackendRenderTarget(desc); |
339 } | 562 } |
340 | 563 |
341 /////////////////////////////////////////////////////////////////////////////// | 564 /////////////////////////////////////////////////////////////////////////////// |
342 | 565 |
343 bool GrContext::supportsIndex8PixelConfig() const { | 566 bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params, |
| 567 int width, int height) const { |
344 const GrDrawTargetCaps* caps = fGpu->caps(); | 568 const GrDrawTargetCaps* caps = fGpu->caps(); |
345 return caps->isConfigTexturable(kIndex_8_GrPixelConfig); | 569 if (!caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { |
| 570 return false; |
| 571 } |
| 572 |
| 573 bool isPow2 = SkIsPow2(width) && SkIsPow2(height); |
| 574 |
| 575 if (!isPow2) { |
| 576 bool tiled = params && params->isTiled(); |
| 577 if (tiled && !caps->npotTextureTileSupport()) { |
| 578 return false; |
| 579 } |
| 580 } |
| 581 return true; |
346 } | 582 } |
347 | 583 |
348 | 584 |
349 //////////////////////////////////////////////////////////////////////////////// | 585 //////////////////////////////////////////////////////////////////////////////// |
350 | 586 |
351 void GrContext::clear(const SkIRect* rect, | 587 void GrContext::clear(const SkIRect* rect, |
352 const GrColor color, | 588 const GrColor color, |
353 bool canIgnoreRect, | 589 bool canIgnoreRect, |
354 GrRenderTarget* renderTarget) { | 590 GrRenderTarget* renderTarget) { |
355 ASSERT_OWNED_RESOURCE(renderTarget); | 591 ASSERT_OWNED_RESOURCE(renderTarget); |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 } | 1760 } |
1525 GrConfigConversionEffect::PMConversion upmToPM = | 1761 GrConfigConversionEffect::PMConversion upmToPM = |
1526 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); | 1762 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); |
1527 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { | 1763 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { |
1528 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat
rix); | 1764 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat
rix); |
1529 } else { | 1765 } else { |
1530 return NULL; | 1766 return NULL; |
1531 } | 1767 } |
1532 } | 1768 } |
1533 | 1769 |
1534 ////////////////////////////////////////////////////////////////////////////// | 1770 void GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resou
rce) { |
1535 | 1771 resource->cacheAccess().setContentKey(key); |
1536 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes
) const { | |
1537 if (maxTextures) { | |
1538 *maxTextures = fResourceCache2->getMaxResourceCount(); | |
1539 } | |
1540 if (maxTextureBytes) { | |
1541 *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); | |
1542 } | |
1543 } | |
1544 | |
1545 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
{ | |
1546 fResourceCache2->setLimits(maxTextures, maxTextureBytes); | |
1547 } | |
1548 | |
1549 bool GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resou
rce) { | |
1550 ASSERT_OWNED_RESOURCE(resource); | |
1551 if (!resource || resource->wasDestroyed()) { | |
1552 return false; | |
1553 } | |
1554 return resource->cacheAccess().setContentKey(key); | |
1555 } | |
1556 | |
1557 bool GrContext::isResourceInCache(const GrContentKey& key) const { | |
1558 return fResourceCache2->hasContentKey(key); | |
1559 } | 1772 } |
1560 | 1773 |
1561 GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { | 1774 GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { |
1562 return fResourceCache2->findAndRefContentResource(key); | 1775 return fResourceCache2->findAndRefContentResource(key); |
1563 } | 1776 } |
1564 | 1777 |
1565 ////////////////////////////////////////////////////////////////////////////// | |
1566 | |
1567 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { | 1778 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { |
1568 fGpu->addGpuTraceMarker(marker); | 1779 fGpu->addGpuTraceMarker(marker); |
1569 if (fDrawBuffer) { | 1780 if (fDrawBuffer) { |
1570 fDrawBuffer->addGpuTraceMarker(marker); | 1781 fDrawBuffer->addGpuTraceMarker(marker); |
1571 } | 1782 } |
1572 } | 1783 } |
1573 | 1784 |
1574 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 1785 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
1575 fGpu->removeGpuTraceMarker(marker); | 1786 fGpu->removeGpuTraceMarker(marker); |
1576 if (fDrawBuffer) { | 1787 if (fDrawBuffer) { |
1577 fDrawBuffer->removeGpuTraceMarker(marker); | 1788 fDrawBuffer->removeGpuTraceMarker(marker); |
1578 } | 1789 } |
1579 } | 1790 } |
1580 | 1791 |
1581 /////////////////////////////////////////////////////////////////////////////// | 1792 /////////////////////////////////////////////////////////////////////////////// |
1582 #if GR_CACHE_STATS | 1793 #if GR_CACHE_STATS |
1583 void GrContext::printCacheStats() const { | 1794 void GrContext::printCacheStats() const { |
1584 fResourceCache2->printStats(); | 1795 fResourceCache2->printStats(); |
1585 } | 1796 } |
1586 #endif | 1797 #endif |
1587 | 1798 |
1588 #if GR_GPU_STATS | 1799 #if GR_GPU_STATS |
1589 const GrContext::GPUStats* GrContext::gpuStats() const { | 1800 const GrContext::GPUStats* GrContext::gpuStats() const { |
1590 return fGpu->gpuStats(); | 1801 return fGpu->gpuStats(); |
1591 } | 1802 } |
1592 #endif | 1803 #endif |
1593 | 1804 |
OLD | NEW |