• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GrTextureProvider(GrGpu * gpu,GrResourceCache * cache,GrSingleOwner * singleOwner)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 
createTexture(const GrSurfaceDesc & desc,SkBudgeted budgeted,const void * srcData,size_t rowBytes)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 
createApproxTexture(const GrSurfaceDesc & desc)60 GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) {
61     ASSERT_SINGLE_OWNER
62     return this->internalCreateApproxTexture(desc, 0);
63 }
64 
internalCreateApproxTexture(const GrSurfaceDesc & desc,uint32_t scratchFlags)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 
refScratchTexture(const GrSurfaceDesc & inDesc,uint32_t flags)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 
wrapBackendTexture(const GrBackendTextureDesc & desc,GrWrapOwnership ownership)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 
wrapBackendRenderTarget(const GrBackendRenderTargetDesc & desc)135 GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
136     ASSERT_SINGLE_OWNER
137     return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc,
138                                                                          kBorrow_GrWrapOwnership);
139 }
140 
assignUniqueKeyToResource(const GrUniqueKey & key,GrGpuResource * resource)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 
existsResourceWithUniqueKey(const GrUniqueKey & key) const149 bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
150     ASSERT_SINGLE_OWNER
151     return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
152 }
153 
findAndRefResourceByUniqueKey(const GrUniqueKey & key)154 GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
155     ASSERT_SINGLE_OWNER
156     return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
157 }
158 
findAndRefTextureByUniqueKey(const GrUniqueKey & key)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