1d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon/* 2d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * Copyright 2015 Google Inc. 3d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * 4d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * Use of this source code is governed by a BSD-style license that can be 5d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon * found in the LICENSE file. 6d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon */ 7d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 8d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrTextureProvider.h" 9d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrTexturePriv.h" 10d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrResourceCache.h" 11d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#include "GrGpu.h" 126d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#include "../private/GrSingleOwner.h" 136d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt 146d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#define ASSERT_SINGLE_OWNER \ 156d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) 16d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 17d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonenum ScratchTextureFlags { 18d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon kExact_ScratchTextureFlag = 0x1, 19d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon kNoPendingIO_ScratchTextureFlag = 0x2, 20d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon kNoCreate_ScratchTextureFlag = 0x4, 21d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon}; 22d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 236d0872d9bd97de5301214a258e141dd5fbeecffcjoshualittGrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner) 246d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt : fCache(cache) 256d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt , fGpu(gpu) 266d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#ifdef SK_DEBUG 276d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt , fSingleOwner(singleOwner) 286d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt#endif 296d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt { 306d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt} 316d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt 325ec26ae9bfca635ccc98283aad5deda11519d826bsalomonGrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, 33d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon const void* srcData, size_t rowBytes) { 346d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 35d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (this->isAbandoned()) { 3696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 37d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 38d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) && 39d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 4096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 41d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 429a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen if (!GrPixelConfigIsCompressed(desc.fConfig) && 439a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen !desc.fTextureStorageAllocator.fAllocateTextureStorage) { 44d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon static const uint32_t kFlags = kExact_ScratchTextureFlag | 45d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon kNoCreate_ScratchTextureFlag; 46eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) { 47d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 48d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon srcData, rowBytes)) { 495ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kNo == budgeted) { 50d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon texture->resourcePriv().makeUnbudgeted(); 51d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 52d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon return texture; 53d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 54d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon texture->unref(); 55d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 56d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 57d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon return fGpu->createTexture(desc, budgeted, srcData, rowBytes); 58d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 59d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 60eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) { 616d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 62eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon return this->internalCreateApproxTexture(desc, 0); 63eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon} 64eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon 65eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc, 66eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon uint32_t scratchFlags) { 676d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 68d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (this->isAbandoned()) { 6996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 70d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 71d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon // Currently we don't recycle compressed textures as scratch. 72d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (GrPixelConfigIsCompressed(desc.fConfig)) { 7396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 74d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } else { 75eae6200acbec2255ac00ab363ffbe16758ec9076bsalomon return this->refScratchTexture(desc, scratchFlags); 76d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 77d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 78d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 79eae6200acbec2255ac00ab363ffbe16758ec9076bsalomonGrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc, 807b77ac100e98f1037ae907c8830b808361f211e1brucedawson uint32_t flags) { 816d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 82d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon SkASSERT(!this->isAbandoned()); 83d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig)); 84d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 85d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc); 86d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 87d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) { 887b77ac100e98f1037ae907c8830b808361f211e1brucedawson if (!(kExact_ScratchTextureFlag & flags)) { 89d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon // bin by pow2 with a reasonable min 90100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon const int kMinSize = 16; 91d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon GrSurfaceDesc* wdesc = desc.writable(); 92100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon wdesc->fWidth = SkTMax(kMinSize, GrNextPow2(desc->fWidth)); 93100b8f8c079510a6b7572f9ed8058c1d4a2bfebabsalomon wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight)); 94d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 95d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 96d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon GrScratchKey key; 97d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon GrTexturePriv::ComputeScratchKey(*desc, &key); 98d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon uint32_t scratchFlags = 0; 997b77ac100e98f1037ae907c8830b808361f211e1brucedawson if (kNoPendingIO_ScratchTextureFlag & flags) { 100d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; 101d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) { 102d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon // If it is not a render target then it will most likely be populated by 103d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon // writePixels() which will trigger a flush if the texture has pending IO. 104d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; 105d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 1066e83ac778f8f90939abe3aee3ea865428dff592frobertphillips GrGpuResource* resource = fCache->findAndRefScratchResource(key, 1076e83ac778f8f90939abe3aee3ea865428dff592frobertphillips GrSurface::WorseCaseSize(*desc), 1086e83ac778f8f90939abe3aee3ea865428dff592frobertphillips scratchFlags); 109d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (resource) { 110d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon GrSurface* surface = static_cast<GrSurface*>(resource); 111d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon GrRenderTarget* rt = surface->asRenderTarget(); 112d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (rt && fGpu->caps()->discardRenderTargetSupport()) { 113d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon rt->discard(); 114d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 115d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon return surface->asTexture(); 116d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 117d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 118d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 1197b77ac100e98f1037ae907c8830b808361f211e1brucedawson if (!(kNoCreate_ScratchTextureFlag & flags)) { 1205ec26ae9bfca635ccc98283aad5deda11519d826bsalomon return fGpu->createTexture(*desc, SkBudgeted::kYes, nullptr, 0); 121d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 122d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 12396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 124d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 125d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 1266dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomonGrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc, 1276dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon GrWrapOwnership ownership) { 1286d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 129d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (this->isAbandoned()) { 13096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 131d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 1326dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon return fGpu->wrapBackendTexture(desc, ownership); 133d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 134d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 135d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonGrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) { 1366d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 13796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc, 1386d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt kBorrow_GrWrapOwnership); 139d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 140d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 141d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonvoid GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) { 1426d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 143d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon if (this->isAbandoned() || !resource) { 144d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon return; 145d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon } 146d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon resource->resourcePriv().setUniqueKey(key); 147d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 148d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 149d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonbool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const { 1506d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 151d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon return this->isAbandoned() ? false : fCache->hasUniqueKey(key); 152d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 153d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon 154d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomonGrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) { 1556d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 15696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key); 157d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon} 1586d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt 1596d0872d9bd97de5301214a258e141dd5fbeecffcjoshualittGrTexture* GrTextureProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) { 1606d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt ASSERT_SINGLE_OWNER 1616d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key); 1626d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt if (resource) { 1636d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture(); 1646d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt SkASSERT(texture); 1656d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt return texture; 1666d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt } 1676d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt return NULL; 1686d0872d9bd97de5301214a258e141dd5fbeecffcjoshualitt} 169