blob: 00494da5a1194a088de10a5b44f66cd3e65b5b53 [file] [log] [blame]
bsalomond309e7a2015-04-30 14:18:54 -07001/*
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"
robertphillips28a838e2016-06-23 14:07:00 -07009
10#include "GrCaps.h"
bsalomond309e7a2015-04-30 14:18:54 -070011#include "GrTexturePriv.h"
12#include "GrResourceCache.h"
13#include "GrGpu.h"
joshualitt6d0872d2016-01-11 08:27:48 -080014#include "../private/GrSingleOwner.h"
halcanary4dbbd042016-06-07 17:21:10 -070015#include "SkMathPriv.h"
cblume55f2d2d2016-02-26 13:20:48 -080016#include "SkTArray.h"
joshualitt6d0872d2016-01-11 08:27:48 -080017
18#define ASSERT_SINGLE_OWNER \
19 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
bsalomond309e7a2015-04-30 14:18:54 -070020
21enum ScratchTextureFlags {
22 kExact_ScratchTextureFlag = 0x1,
23 kNoPendingIO_ScratchTextureFlag = 0x2,
24 kNoCreate_ScratchTextureFlag = 0x4,
25};
26
joshualitt6d0872d2016-01-11 08:27:48 -080027GrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner)
28 : fCache(cache)
29 , fGpu(gpu)
30#ifdef SK_DEBUG
31 , fSingleOwner(singleOwner)
32#endif
33 {
34}
35
cblume55f2d2d2016-02-26 13:20:48 -080036GrTexture* GrTextureProvider::createMipMappedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
37 const GrMipLevel* texels, int mipLevelCount) {
joshualitt6d0872d2016-01-11 08:27:48 -080038 ASSERT_SINGLE_OWNER
cblume55f2d2d2016-02-26 13:20:48 -080039
bsalomond309e7a2015-04-30 14:18:54 -070040 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -070041 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070042 }
bsalomone699d0c2016-03-09 06:25:15 -080043 if (mipLevelCount && !texels) {
44 return nullptr;
45 }
46 for (int i = 0; i < mipLevelCount; ++i) {
47 if (!texels[i].fPixels) {
48 return nullptr;
49 }
50 }
51
bsalomond309e7a2015-04-30 14:18:54 -070052 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
53 !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
halcanary96fcdcc2015-08-27 07:41:13 -070054 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070055 }
bsalomon7e68ab72016-04-13 14:29:25 -070056 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
cblume55f2d2d2016-02-26 13:20:48 -080057 if (mipLevelCount < 2) {
cblume55f2d2d2016-02-26 13:20:48 -080058 static const uint32_t kFlags = kExact_ScratchTextureFlag |
59 kNoCreate_ScratchTextureFlag;
60 if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) {
bsalomon7467ab82016-03-09 09:52:45 -080061 if (!mipLevelCount ||
62 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
63 texels[0].fPixels, texels[0].fRowBytes)) {
cblume55f2d2d2016-02-26 13:20:48 -080064 if (SkBudgeted::kNo == budgeted) {
65 texture->resourcePriv().makeUnbudgeted();
66 }
67 return texture;
bsalomond309e7a2015-04-30 14:18:54 -070068 }
cblume55f2d2d2016-02-26 13:20:48 -080069 texture->unref();
bsalomond309e7a2015-04-30 14:18:54 -070070 }
bsalomond309e7a2015-04-30 14:18:54 -070071 }
72 }
cblume55f2d2d2016-02-26 13:20:48 -080073
74 SkTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
75 for (int i = 0; i < mipLevelCount; ++i) {
76 texelsShallowCopy.push_back(texels[i]);
77 }
78 return fGpu->createTexture(desc, budgeted, texelsShallowCopy);
79}
80
81GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
82 const void* srcData, size_t rowBytes) {
bsalomone699d0c2016-03-09 06:25:15 -080083 GrMipLevel tempTexels;
84 GrMipLevel* texels = nullptr;
85 int levelCount = 0;
86 if (srcData) {
87 tempTexels.fPixels = srcData;
88 tempTexels.fRowBytes = rowBytes;
89 texels = &tempTexels;
90 levelCount = 1;
91 }
92 return this->createMipMappedTexture(desc, budgeted, texels, levelCount);
bsalomond309e7a2015-04-30 14:18:54 -070093}
94
bsalomoneae62002015-07-31 13:59:30 -070095GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) {
joshualitt6d0872d2016-01-11 08:27:48 -080096 ASSERT_SINGLE_OWNER
bsalomoneae62002015-07-31 13:59:30 -070097 return this->internalCreateApproxTexture(desc, 0);
98}
99
100GrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc,
101 uint32_t scratchFlags) {
joshualitt6d0872d2016-01-11 08:27:48 -0800102 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700103 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700104 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700105 }
106 // Currently we don't recycle compressed textures as scratch.
107 if (GrPixelConfigIsCompressed(desc.fConfig)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700108 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700109 } else {
bsalomoneae62002015-07-31 13:59:30 -0700110 return this->refScratchTexture(desc, scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -0700111 }
112}
113
bsalomoneae62002015-07-31 13:59:30 -0700114GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
brucedawson7b77ac12015-08-05 14:05:17 -0700115 uint32_t flags) {
joshualitt6d0872d2016-01-11 08:27:48 -0800116 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700117 SkASSERT(!this->isAbandoned());
118 SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
119
120 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
121
122 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
brucedawson7b77ac12015-08-05 14:05:17 -0700123 if (!(kExact_ScratchTextureFlag & flags)) {
bsalomond309e7a2015-04-30 14:18:54 -0700124 // bin by pow2 with a reasonable min
bsalomon100b8f82015-10-28 08:37:44 -0700125 const int kMinSize = 16;
bsalomond309e7a2015-04-30 14:18:54 -0700126 GrSurfaceDesc* wdesc = desc.writable();
bsalomon100b8f82015-10-28 08:37:44 -0700127 wdesc->fWidth = SkTMax(kMinSize, GrNextPow2(desc->fWidth));
128 wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight));
bsalomond309e7a2015-04-30 14:18:54 -0700129 }
130
131 GrScratchKey key;
132 GrTexturePriv::ComputeScratchKey(*desc, &key);
133 uint32_t scratchFlags = 0;
brucedawson7b77ac12015-08-05 14:05:17 -0700134 if (kNoPendingIO_ScratchTextureFlag & flags) {
bsalomond309e7a2015-04-30 14:18:54 -0700135 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
136 } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
137 // If it is not a render target then it will most likely be populated by
138 // writePixels() which will trigger a flush if the texture has pending IO.
139 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
140 }
robertphillips6e83ac72015-08-13 05:19:14 -0700141 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
142 GrSurface::WorseCaseSize(*desc),
143 scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -0700144 if (resource) {
145 GrSurface* surface = static_cast<GrSurface*>(resource);
146 GrRenderTarget* rt = surface->asRenderTarget();
147 if (rt && fGpu->caps()->discardRenderTargetSupport()) {
148 rt->discard();
149 }
150 return surface->asTexture();
151 }
152 }
153
brucedawson7b77ac12015-08-05 14:05:17 -0700154 if (!(kNoCreate_ScratchTextureFlag & flags)) {
bsalomone699d0c2016-03-09 06:25:15 -0800155 return fGpu->createTexture(*desc, SkBudgeted::kYes);
bsalomond309e7a2015-04-30 14:18:54 -0700156 }
157
halcanary96fcdcc2015-08-27 07:41:13 -0700158 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700159}
160
bsalomon6dc6f5f2015-06-18 09:12:16 -0700161GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
162 GrWrapOwnership ownership) {
joshualitt6d0872d2016-01-11 08:27:48 -0800163 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700164 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700165 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700166 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700167 return fGpu->wrapBackendTexture(desc, ownership);
bsalomond309e7a2015-04-30 14:18:54 -0700168}
169
170GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
joshualitt6d0872d2016-01-11 08:27:48 -0800171 ASSERT_SINGLE_OWNER
halcanary96fcdcc2015-08-27 07:41:13 -0700172 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc,
joshualitt6d0872d2016-01-11 08:27:48 -0800173 kBorrow_GrWrapOwnership);
bsalomond309e7a2015-04-30 14:18:54 -0700174}
175
176void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
joshualitt6d0872d2016-01-11 08:27:48 -0800177 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700178 if (this->isAbandoned() || !resource) {
179 return;
180 }
181 resource->resourcePriv().setUniqueKey(key);
182}
183
184bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
joshualitt6d0872d2016-01-11 08:27:48 -0800185 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700186 return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
187}
188
189GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
joshualitt6d0872d2016-01-11 08:27:48 -0800190 ASSERT_SINGLE_OWNER
halcanary96fcdcc2015-08-27 07:41:13 -0700191 return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
bsalomond309e7a2015-04-30 14:18:54 -0700192}
joshualitt6d0872d2016-01-11 08:27:48 -0800193
194GrTexture* GrTextureProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
195 ASSERT_SINGLE_OWNER
196 GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
197 if (resource) {
198 GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
199 SkASSERT(texture);
200 return texture;
201 }
202 return NULL;
203}