1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrTextureProvider.h" 9 #include "GrTexturePriv.h" 10 #include "GrResourceCache.h" 11 #include "GrGpu.h" 12 #include "../private/GrSingleOwner.h" 13 14 #define ASSERT_SINGLE_OWNER \ 15 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) 16 17 enum ScratchTextureFlags { 18 kExact_ScratchTextureFlag = 0x1, 19 kNoPendingIO_ScratchTextureFlag = 0x2, 20 kNoCreate_ScratchTextureFlag = 0x4, 21 }; 22 23 GrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner) 24 : fCache(cache) 25 , fGpu(gpu) 26 #ifdef SK_DEBUG 27 , fSingleOwner(singleOwner) 28 #endif 29 { 30 } 31 32 GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, 33 const void* srcData, size_t rowBytes) { 34 ASSERT_SINGLE_OWNER 35 if (this->isAbandoned()) { 36 return nullptr; 37 } 38 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) && 39 !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 40 return nullptr; 41 } 42 if (!GrPixelConfigIsCompressed(desc.fConfig) && 43 !desc.fTextureStorageAllocator.fAllocateTextureStorage) { 44 static const uint32_t kFlags = kExact_ScratchTextureFlag | 45 kNoCreate_ScratchTextureFlag; 46 if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) { 47 if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 48 srcData, rowBytes)) { 49 if (SkBudgeted::kNo == budgeted) { 50 texture->resourcePriv().makeUnbudgeted(); 51 } 52 return texture; 53 } 54 texture->unref(); 55 } 56 } 57 return fGpu->createTexture(desc, budgeted, srcData, rowBytes); 58 } 59 60 GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) { 61 ASSERT_SINGLE_OWNER 62 return this->internalCreateApproxTexture(desc, 0); 63 } 64 65 GrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc, 66 uint32_t scratchFlags) { 67 ASSERT_SINGLE_OWNER 68 if (this->isAbandoned()) { 69 return nullptr; 70 } 71 // Currently we don't recycle compressed textures as scratch. 72 if (GrPixelConfigIsCompressed(desc.fConfig)) { 73 return nullptr; 74 } else { 75 return this->refScratchTexture(desc, scratchFlags); 76 } 77 } 78 79 GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc, 80 uint32_t flags) { 81 ASSERT_SINGLE_OWNER 82 SkASSERT(!this->isAbandoned()); 83 SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig)); 84 85 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc); 86 87 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) { 88 if (!(kExact_ScratchTextureFlag & flags)) { 89 // bin by pow2 with a reasonable min 90 const int kMinSize = 16; 91 GrSurfaceDesc* wdesc = desc.writable(); 92 wdesc->fWidth = SkTMax(kMinSize, GrNextPow2(desc->fWidth)); 93 wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight)); 94 } 95 96 GrScratchKey key; 97 GrTexturePriv::ComputeScratchKey(*desc, &key); 98 uint32_t scratchFlags = 0; 99 if (kNoPendingIO_ScratchTextureFlag & flags) { 100 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; 101 } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) { 102 // If it is not a render target then it will most likely be populated by 103 // writePixels() which will trigger a flush if the texture has pending IO. 104 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; 105 } 106 GrGpuResource* resource = fCache->findAndRefScratchResource(key, 107 GrSurface::WorseCaseSize(*desc), 108 scratchFlags); 109 if (resource) { 110 GrSurface* surface = static_cast<GrSurface*>(resource); 111 GrRenderTarget* rt = surface->asRenderTarget(); 112 if (rt && fGpu->caps()->discardRenderTargetSupport()) { 113 rt->discard(); 114 } 115 return surface->asTexture(); 116 } 117 } 118 119 if (!(kNoCreate_ScratchTextureFlag & flags)) { 120 return fGpu->createTexture(*desc, SkBudgeted::kYes, nullptr, 0); 121 } 122 123 return nullptr; 124 } 125 126 GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc, 127 GrWrapOwnership ownership) { 128 ASSERT_SINGLE_OWNER 129 if (this->isAbandoned()) { 130 return nullptr; 131 } 132 return fGpu->wrapBackendTexture(desc, ownership); 133 } 134 135 GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) { 136 ASSERT_SINGLE_OWNER 137 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc, 138 kBorrow_GrWrapOwnership); 139 } 140 141 void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) { 142 ASSERT_SINGLE_OWNER 143 if (this->isAbandoned() || !resource) { 144 return; 145 } 146 resource->resourcePriv().setUniqueKey(key); 147 } 148 149 bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const { 150 ASSERT_SINGLE_OWNER 151 return this->isAbandoned() ? false : fCache->hasUniqueKey(key); 152 } 153 154 GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) { 155 ASSERT_SINGLE_OWNER 156 return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key); 157 } 158 159 GrTexture* GrTextureProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) { 160 ASSERT_SINGLE_OWNER 161 GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key); 162 if (resource) { 163 GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture(); 164 SkASSERT(texture); 165 return texture; 166 } 167 return NULL; 168 } 169