blob: 7d720eb1212dd0455953892c75e550155975fe03 [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"
9#include "GrTexturePriv.h"
10#include "GrResourceCache.h"
11#include "GrGpu.h"
joshualitt6d0872d2016-01-11 08:27:48 -080012#include "../private/GrSingleOwner.h"
13
14#define ASSERT_SINGLE_OWNER \
15 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
bsalomond309e7a2015-04-30 14:18:54 -070016
17enum ScratchTextureFlags {
18 kExact_ScratchTextureFlag = 0x1,
19 kNoPendingIO_ScratchTextureFlag = 0x2,
20 kNoCreate_ScratchTextureFlag = 0x4,
21};
22
joshualitt6d0872d2016-01-11 08:27:48 -080023GrTextureProvider::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
bsalomond309e7a2015-04-30 14:18:54 -070032GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, bool budgeted,
33 const void* srcData, size_t rowBytes) {
joshualitt6d0872d2016-01-11 08:27:48 -080034 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -070035 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -070036 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070037 }
38 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
39 !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
halcanary96fcdcc2015-08-27 07:41:13 -070040 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070041 }
erikchen7fec91c2016-02-05 12:10:55 -080042 if (!GrPixelConfigIsCompressed(desc.fConfig) &&
43 !desc.fTextureStorageAllocator.fAllocateTextureStorage) {
bsalomond309e7a2015-04-30 14:18:54 -070044 static const uint32_t kFlags = kExact_ScratchTextureFlag |
45 kNoCreate_ScratchTextureFlag;
bsalomoneae62002015-07-31 13:59:30 -070046 if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) {
bsalomond309e7a2015-04-30 14:18:54 -070047 if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
48 srcData, rowBytes)) {
49 if (!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
bsalomoneae62002015-07-31 13:59:30 -070060GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) {
joshualitt6d0872d2016-01-11 08:27:48 -080061 ASSERT_SINGLE_OWNER
bsalomoneae62002015-07-31 13:59:30 -070062 return this->internalCreateApproxTexture(desc, 0);
63}
64
65GrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc,
66 uint32_t scratchFlags) {
joshualitt6d0872d2016-01-11 08:27:48 -080067 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -070068 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -070069 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070070 }
71 // Currently we don't recycle compressed textures as scratch.
72 if (GrPixelConfigIsCompressed(desc.fConfig)) {
halcanary96fcdcc2015-08-27 07:41:13 -070073 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -070074 } else {
bsalomoneae62002015-07-31 13:59:30 -070075 return this->refScratchTexture(desc, scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -070076 }
77}
78
bsalomoneae62002015-07-31 13:59:30 -070079GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
brucedawson7b77ac12015-08-05 14:05:17 -070080 uint32_t flags) {
joshualitt6d0872d2016-01-11 08:27:48 -080081 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -070082 SkASSERT(!this->isAbandoned());
83 SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
84
85 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
86
87 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
brucedawson7b77ac12015-08-05 14:05:17 -070088 if (!(kExact_ScratchTextureFlag & flags)) {
bsalomond309e7a2015-04-30 14:18:54 -070089 // bin by pow2 with a reasonable min
bsalomon100b8f82015-10-28 08:37:44 -070090 const int kMinSize = 16;
bsalomond309e7a2015-04-30 14:18:54 -070091 GrSurfaceDesc* wdesc = desc.writable();
bsalomon100b8f82015-10-28 08:37:44 -070092 wdesc->fWidth = SkTMax(kMinSize, GrNextPow2(desc->fWidth));
93 wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight));
bsalomond309e7a2015-04-30 14:18:54 -070094 }
95
96 GrScratchKey key;
97 GrTexturePriv::ComputeScratchKey(*desc, &key);
98 uint32_t scratchFlags = 0;
brucedawson7b77ac12015-08-05 14:05:17 -070099 if (kNoPendingIO_ScratchTextureFlag & flags) {
bsalomond309e7a2015-04-30 14:18:54 -0700100 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 }
robertphillips6e83ac72015-08-13 05:19:14 -0700106 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
107 GrSurface::WorseCaseSize(*desc),
108 scratchFlags);
bsalomond309e7a2015-04-30 14:18:54 -0700109 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
brucedawson7b77ac12015-08-05 14:05:17 -0700119 if (!(kNoCreate_ScratchTextureFlag & flags)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700120 return fGpu->createTexture(*desc, true, nullptr, 0);
bsalomond309e7a2015-04-30 14:18:54 -0700121 }
122
halcanary96fcdcc2015-08-27 07:41:13 -0700123 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700124}
125
bsalomon6dc6f5f2015-06-18 09:12:16 -0700126GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
127 GrWrapOwnership ownership) {
joshualitt6d0872d2016-01-11 08:27:48 -0800128 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700129 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700130 return nullptr;
bsalomond309e7a2015-04-30 14:18:54 -0700131 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700132 return fGpu->wrapBackendTexture(desc, ownership);
bsalomond309e7a2015-04-30 14:18:54 -0700133}
134
135GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
joshualitt6d0872d2016-01-11 08:27:48 -0800136 ASSERT_SINGLE_OWNER
halcanary96fcdcc2015-08-27 07:41:13 -0700137 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc,
joshualitt6d0872d2016-01-11 08:27:48 -0800138 kBorrow_GrWrapOwnership);
bsalomond309e7a2015-04-30 14:18:54 -0700139}
140
141void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
joshualitt6d0872d2016-01-11 08:27:48 -0800142 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700143 if (this->isAbandoned() || !resource) {
144 return;
145 }
146 resource->resourcePriv().setUniqueKey(key);
147}
148
149bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
joshualitt6d0872d2016-01-11 08:27:48 -0800150 ASSERT_SINGLE_OWNER
bsalomond309e7a2015-04-30 14:18:54 -0700151 return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
152}
153
154GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
joshualitt6d0872d2016-01-11 08:27:48 -0800155 ASSERT_SINGLE_OWNER
halcanary96fcdcc2015-08-27 07:41:13 -0700156 return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
bsalomond309e7a2015-04-30 14:18:54 -0700157}
joshualitt6d0872d2016-01-11 08:27:48 -0800158
159GrTexture* 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}