blob: 3790f27fcc94cb34e7b8468b7475d418dbc39fc3 [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"
Brian Osmane8e54582016-11-28 10:06:27 -050017#include "SkTLazy.h"
joshualitt6d0872d2016-01-11 08:27:48 -080018
Robert Phillips784b7bf2016-12-09 13:35:02 -050019const int GrTextureProvider::kMinScratchTextureSize = 16;
20
joshualitt6d0872d2016-01-11 08:27:48 -080021#define ASSERT_SINGLE_OWNER \
22 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
bsalomond309e7a2015-04-30 14:18:54 -070023
joshualitt6d0872d2016-01-11 08:27:48 -080024GrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner)
25 : fCache(cache)
26 , fGpu(gpu)
27#ifdef SK_DEBUG
28 , fSingleOwner(singleOwner)
29#endif
30 {
31}
32
cblume55f2d2d2016-02-26 13:20:48 -080033GrTexture* GrTextureProvider::createMipMappedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Robert Phillipsc787e492017-02-28 11:26:32 -050034 const GrMipLevel* texels, int mipLevelCount,
35 uint32_t flags) {
joshualitt6d0872d2016-01-11 08:27:48 -080036 ASSERT_SINGLE_OWNER
cblume55f2d2d2016-02-26 13:20:48 -080037
bsalomond309e7a2015-04-30 14:18:54 -070038 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -070039 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070040 }
bsalomone699d0c2016-03-09 06:25:15 -080041 if (mipLevelCount && !texels) {
42 return nullptr;
43 }
44 for (int i = 0; i < mipLevelCount; ++i) {
45 if (!texels[i].fPixels) {
46 return nullptr;
47 }
48 }
Brian Salomonbf7b6202016-11-11 16:08:03 -050049 if (mipLevelCount > 1 && GrPixelConfigIsSint(desc.fConfig)) {
50 return nullptr;
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) {
Robert Phillipsc787e492017-02-28 11:26:32 -050058 flags |= kExact_ScratchTextureFlag | kNoCreate_ScratchTextureFlag;
59 if (GrTexture* texture = this->refScratchTexture(desc, flags)) {
bsalomon7467ab82016-03-09 09:52:45 -080060 if (!mipLevelCount ||
61 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
62 texels[0].fPixels, texels[0].fRowBytes)) {
cblume55f2d2d2016-02-26 13:20:48 -080063 if (SkBudgeted::kNo == budgeted) {
64 texture->resourcePriv().makeUnbudgeted();
65 }
66 return texture;
bsalomond309e7a2015-04-30 14:18:54 -070067 }
cblume55f2d2d2016-02-26 13:20:48 -080068 texture->unref();
bsalomond309e7a2015-04-30 14:18:54 -070069 }
bsalomond309e7a2015-04-30 14:18:54 -070070 }
71 }
cblume55f2d2d2016-02-26 13:20:48 -080072
73 SkTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
74 for (int i = 0; i < mipLevelCount; ++i) {
75 texelsShallowCopy.push_back(texels[i]);
76 }
77 return fGpu->createTexture(desc, budgeted, texelsShallowCopy);
78}
79
80GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Robert Phillipsc787e492017-02-28 11:26:32 -050081 const void* srcData, size_t rowBytes, uint32_t flags) {
bsalomone699d0c2016-03-09 06:25:15 -080082 GrMipLevel tempTexels;
83 GrMipLevel* texels = nullptr;
84 int levelCount = 0;
85 if (srcData) {
Brian Salomonbf7b6202016-11-11 16:08:03 -050086 tempTexels.fPixels = srcData;
87 tempTexels.fRowBytes = rowBytes;
88 texels = &tempTexels;
89 levelCount = 1;
bsalomone699d0c2016-03-09 06:25:15 -080090 }
Robert Phillipsc787e492017-02-28 11:26:32 -050091 return this->createMipMappedTexture(desc, budgeted, texels, levelCount, flags);
bsalomond309e7a2015-04-30 14:18:54 -070092}
93
Robert Phillipsc787e492017-02-28 11:26:32 -050094GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) {
joshualitt6d0872d2016-01-11 08:27:48 -080095 ASSERT_SINGLE_OWNER
Robert Phillipsc787e492017-02-28 11:26:32 -050096 return this->internalCreateApproxTexture(desc, flags);
bsalomoneae62002015-07-31 13:59:30 -070097}
98
99GrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc,
100 uint32_t scratchFlags) {
joshualitt6d0872d2016-01-11 08:27:48 -0800101 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700102 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700103 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700104 }
105 // Currently we don't recycle compressed textures as scratch.
106 if (GrPixelConfigIsCompressed(desc.fConfig)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700107 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700108 } else {
bsalomoneae62002015-07-31 13:59:30 -0700109 return this->refScratchTexture(desc, scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -0700110 }
111}
112
bsalomoneae62002015-07-31 13:59:30 -0700113GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
brucedawson7b77ac12015-08-05 14:05:17 -0700114 uint32_t flags) {
joshualitt6d0872d2016-01-11 08:27:48 -0800115 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700116 SkASSERT(!this->isAbandoned());
117 SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
118
119 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
120
121 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
brucedawson7b77ac12015-08-05 14:05:17 -0700122 if (!(kExact_ScratchTextureFlag & flags)) {
bsalomond309e7a2015-04-30 14:18:54 -0700123 // bin by pow2 with a reasonable min
bsalomond309e7a2015-04-30 14:18:54 -0700124 GrSurfaceDesc* wdesc = desc.writable();
Robert Phillips784b7bf2016-12-09 13:35:02 -0500125 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fWidth));
126 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fHeight));
bsalomond309e7a2015-04-30 14:18:54 -0700127 }
128
129 GrScratchKey key;
130 GrTexturePriv::ComputeScratchKey(*desc, &key);
131 uint32_t scratchFlags = 0;
brucedawson7b77ac12015-08-05 14:05:17 -0700132 if (kNoPendingIO_ScratchTextureFlag & flags) {
bsalomond309e7a2015-04-30 14:18:54 -0700133 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
134 } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
135 // If it is not a render target then it will most likely be populated by
136 // writePixels() which will trigger a flush if the texture has pending IO.
137 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
138 }
robertphillips6e83ac72015-08-13 05:19:14 -0700139 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
robertphillipsf1c6cd72016-08-18 07:11:13 -0700140 GrSurface::WorstCaseSize(*desc),
robertphillips6e83ac72015-08-13 05:19:14 -0700141 scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -0700142 if (resource) {
143 GrSurface* surface = static_cast<GrSurface*>(resource);
144 GrRenderTarget* rt = surface->asRenderTarget();
145 if (rt && fGpu->caps()->discardRenderTargetSupport()) {
146 rt->discard();
147 }
148 return surface->asTexture();
149 }
150 }
151
brucedawson7b77ac12015-08-05 14:05:17 -0700152 if (!(kNoCreate_ScratchTextureFlag & flags)) {
bsalomone699d0c2016-03-09 06:25:15 -0800153 return fGpu->createTexture(*desc, SkBudgeted::kYes);
bsalomond309e7a2015-04-30 14:18:54 -0700154 }
155
halcanary96fcdcc2015-08-27 07:41:13 -0700156 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700157}
158
bungeman6bd52842016-10-27 09:30:08 -0700159sk_sp<GrTexture> GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
160 GrWrapOwnership ownership) {
joshualitt6d0872d2016-01-11 08:27:48 -0800161 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700162 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700163 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700164 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700165 return fGpu->wrapBackendTexture(desc, ownership);
bsalomond309e7a2015-04-30 14:18:54 -0700166}
167
bungeman6bd52842016-10-27 09:30:08 -0700168sk_sp<GrRenderTarget> GrTextureProvider::wrapBackendRenderTarget(
169 const GrBackendRenderTargetDesc& desc)
170{
joshualitt6d0872d2016-01-11 08:27:48 -0800171 ASSERT_SINGLE_OWNER
bungeman6bd52842016-10-27 09:30:08 -0700172 return this->isAbandoned() ? nullptr
173 : fGpu->wrapBackendRenderTarget(desc, 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}