blob: 8408873700bf7db82eb34277a4711dc91e6e8c10 [file] [log] [blame]
bsalomoned0bcad2015-05-04 10:36:42 -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
Brian Salomon1047a492019-07-02 12:25:21 -04008#include "src/gpu/GrResourceProvider.h"
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrBackendSemaphore.h"
11#include "include/gpu/GrContext.h"
12#include "include/private/GrResourceKey.h"
13#include "include/private/GrSingleOwner.h"
Brian Salomon1047a492019-07-02 12:25:21 -040014#include "src/core/SkConvertPixels.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/core/SkMathPriv.h"
16#include "src/gpu/GrCaps.h"
17#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrGpu.h"
19#include "src/gpu/GrGpuBuffer.h"
20#include "src/gpu/GrPath.h"
21#include "src/gpu/GrPathRendering.h"
22#include "src/gpu/GrProxyProvider.h"
23#include "src/gpu/GrRenderTargetPriv.h"
24#include "src/gpu/GrResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrSemaphore.h"
26#include "src/gpu/GrStencilAttachment.h"
27#include "src/gpu/GrTexturePriv.h"
28#include "src/gpu/SkGr.h"
bsalomoned0bcad2015-05-04 10:36:42 -070029
Robert Phillips1bfece82017-06-01 13:56:52 -040030const uint32_t GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050031
32#define ASSERT_SINGLE_OWNER \
33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
34
Robert Phillips12c46292019-04-23 07:36:17 -040035GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050036 : fCache(cache)
37 , fGpu(gpu)
38#ifdef SK_DEBUG
39 , fSingleOwner(owner)
40#endif
Robert Phillips4150eea2018-02-07 17:08:21 -050041{
Robert Phillips26c90e02017-03-14 14:39:29 -040042 fCaps = sk_ref_sp(fGpu->caps());
bsalomoned0bcad2015-05-04 10:36:42 -070043}
44
Brian Salomona3ffaab2019-07-09 12:26:46 -040045// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
46// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
Brian Salomona90382f2019-09-17 09:01:56 -040047static bool prepare_level(const GrMipLevel& inLevel, int w, int h, bool rowBytesSupport,
48 GrColorType origColorType, GrColorType allowedColorType,
Brian Salomond2a8ae22019-09-10 16:03:59 -040049 GrMipLevel* outLevel, std::unique_ptr<char[]>* data) {
Brian Salomona3ffaab2019-07-09 12:26:46 -040050 if (!inLevel.fPixels) {
Brian Salomond2a8ae22019-09-10 16:03:59 -040051 outLevel->fPixels = nullptr;
52 outLevel->fRowBytes = 0;
Brian Salomona3ffaab2019-07-09 12:26:46 -040053 return true;
54 }
Brian Salomona90382f2019-09-17 09:01:56 -040055 size_t minRB = w * GrColorTypeBytesPerPixel(origColorType);
Brian Salomona3ffaab2019-07-09 12:26:46 -040056 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
57 if (actualRB < minRB) {
58 return false;
59 }
Brian Salomona90382f2019-09-17 09:01:56 -040060 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
Brian Salomona3ffaab2019-07-09 12:26:46 -040061 outLevel->fRowBytes = actualRB;
62 outLevel->fPixels = inLevel.fPixels;
Brian Salomona90382f2019-09-17 09:01:56 -040063 return true;
Brian Salomona3ffaab2019-07-09 12:26:46 -040064 }
Brian Salomona90382f2019-09-17 09:01:56 -040065 auto tempRB = w * GrColorTypeBytesPerPixel(allowedColorType);
66 data->reset(new char[tempRB * h]);
67 outLevel->fPixels = data->get();
68 outLevel->fRowBytes = minRB;
69 GrPixelInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, w, h);
70 GrPixelInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, w, h);
71 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
Brian Salomona3ffaab2019-07-09 12:26:46 -040072}
73
Brian Salomonf2c2ba92019-07-17 09:59:59 -040074sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -040075 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -040076 GrColorType colorType,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040077 GrRenderable renderable,
Brian Salomon2af3e702019-08-11 19:10:31 -040078 int renderTargetSampleCnt,
79 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -040080 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -040081 const GrMipLevel texels[],
82 int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050083 ASSERT_SINGLE_OWNER
84
Robert Phillips7f1b4f82017-11-28 07:38:39 -050085 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040086
Brian Osman32342f02017-03-04 08:12:46 -050087 if (this->isAbandoned()) {
88 return nullptr;
89 }
Robert Phillips1119dc32017-04-11 12:54:57 -040090
Brian Salomonbdecacf2018-02-02 20:32:49 -050091 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
Greg Daniel6fa62e22019-08-07 15:52:37 -040092 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
93 renderTargetSampleCnt, mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050094 return nullptr;
95 }
Brian Salomona90382f2019-09-17 09:01:56 -040096 auto allowedColorType =
97 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
98 if (allowedColorType == GrColorType::kUnknown) {
99 return nullptr;
100 }
Brian Salomona3e29962019-07-16 11:52:08 -0400101 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
Brian Salomon1047a492019-07-02 12:25:21 -0400102 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -0400103 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon1047a492019-07-02 12:25:21 -0400104 if (mipLevelCount > 0 && texels) {
105 tmpTexels.reset(mipLevelCount);
106 tmpDatas.reset(mipLevelCount);
107 int w = desc.fWidth;
108 int h = desc.fHeight;
Brian Salomon1047a492019-07-02 12:25:21 -0400109 for (int i = 0; i < mipLevelCount; ++i) {
Brian Salomona90382f2019-09-17 09:01:56 -0400110 if (!prepare_level(texels[i], w, h, rowBytesSupport, colorType, allowedColorType,
111 &tmpTexels[i], &tmpDatas[i])) {
Brian Salomona3ffaab2019-07-09 12:26:46 -0400112 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -0400113 }
114 w = std::max(w / 2, 1);
115 h = std::max(h / 2, 1);
116 }
117 }
Brian Salomon4eb38b72019-08-05 12:58:39 -0400118 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomona90382f2019-09-17 09:01:56 -0400119 isProtected, colorType, colorType, tmpTexels.get(), mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -0500120}
121
Robert Phillips45fdae12017-04-17 12:57:27 -0400122sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400123 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400124 GrRenderable renderable,
125 int renderTargetSampleCnt,
126 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400127 GrProtected isProtected) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400128 sk_sp<GrTexture> tex(this->refScratchTexture(desc, format, renderable, renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400129 isProtected));
Robert Phillips45fdae12017-04-17 12:57:27 -0400130 if (tex && SkBudgeted::kNo == budgeted) {
131 tex->resourcePriv().makeUnbudgeted();
132 }
133
134 return tex;
135}
136
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500137sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400138 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -0400139 GrColorType colorType,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400140 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400141 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500142 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500143 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400144 GrProtected isProtected,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400145 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400146 ASSERT_SINGLE_OWNER
147
148 if (this->isAbandoned()) {
149 return nullptr;
150 }
151
Robert Phillips45fdae12017-04-17 12:57:27 -0400152 if (!mipLevel.fPixels) {
153 return nullptr;
154 }
155
Greg Daniel6fa62e22019-08-07 15:52:37 -0400156 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
157 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400158 return nullptr;
159 }
160
Robert Phillips45fdae12017-04-17 12:57:27 -0400161 GrContext* context = fGpu->getContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500162 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Robert Phillips45fdae12017-04-17 12:57:27 -0400163
Brian Salomona90382f2019-09-17 09:01:56 -0400164 sk_sp<GrTexture> tex;
165 if (SkBackingFit::kApprox == fit) {
166 tex = this->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
167 isProtected);
168 if (!tex) {
169 return nullptr;
170 }
171 sk_sp<GrTextureProxy> proxy = proxyProvider->createWrapped(
172 tex, colorType, kTopLeft_GrSurfaceOrigin, GrSurfaceProxy::UseAllocator::kYes);
173 if (!proxy) {
174 return nullptr;
175 }
176 // Here we don't really know the alpha type of the data we want to upload. All we really
177 // care about is that it is not converted. So we use the same alpha type for the data
178 // and the surface context.
179 static constexpr auto kAlphaType = kUnpremul_SkAlphaType;
180 auto sContext =
181 context->priv().makeWrappedSurfaceContext(std::move(proxy), colorType, kAlphaType);
182 if (!sContext) {
183 return nullptr;
184 }
185 GrPixelInfo srcInfo(colorType, kAlphaType, nullptr, desc.fWidth, desc.fHeight);
186 SkAssertResult(
187 sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, {0, 0}));
188 return tex;
189 } else {
190 return this->createTexture(desc, format, colorType, renderable, renderTargetSampleCnt,
191 budgeted, isProtected, &mipLevel, 1);
Brian Salomona3ffaab2019-07-09 12:26:46 -0400192 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400193}
194
Brian Salomonbb8dde82019-06-27 10:52:13 -0400195sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400196 const GrBackendFormat& format,
Brian Salomonbb8dde82019-06-27 10:52:13 -0400197 SkImage::CompressionType compression,
198 SkBudgeted budgeted, SkData* data) {
199 ASSERT_SINGLE_OWNER
200 if (this->isAbandoned()) {
201 return nullptr;
202 }
Greg Daniel7bfc9132019-08-14 14:23:53 -0400203 return fGpu->createCompressedTexture(width, height, format, compression, budgeted, data->data(),
Brian Salomonbb8dde82019-06-27 10:52:13 -0400204 data->size());
205}
206
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400207sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400208 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400209 GrRenderable renderable,
210 int renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400211 GrMipMapped mipMapped,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400212 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400213 GrProtected isProtected) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400214 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400215 if (this->isAbandoned()) {
216 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500217 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400218
Greg Daniel6fa62e22019-08-07 15:52:37 -0400219 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
Brian Salomona90382f2019-09-17 09:01:56 -0400220 renderTargetSampleCnt, mipMapped)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400221 return nullptr;
222 }
223
Jim Van Verth1676cb92019-01-15 13:24:45 -0500224 // Compressed textures are read-only so they don't support re-use for scratch.
Brian Salomona90382f2019-09-17 09:01:56 -0400225 // TODO: Support GrMipMapped::kYes in scratch texture lookup here.
226 if (!GrPixelConfigIsCompressed(desc.fConfig) && mipMapped == GrMipMapped::kNo) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400227 sk_sp<GrTexture> tex = this->getExactScratch(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400228 desc, format, renderable, renderTargetSampleCnt, budgeted, isProtected);
Jim Van Verth1676cb92019-01-15 13:24:45 -0500229 if (tex) {
230 return tex;
231 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400232 }
233
Brian Salomona90382f2019-09-17 09:01:56 -0400234 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, mipMapped, budgeted,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400235 isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500236}
237
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400238// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
239// the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
240uint32_t GrResourceProvider::MakeApprox(uint32_t value) {
241 static const int kMagicTol = 1024;
242
243 value = SkTMax(kMinScratchTextureSize, value);
244
245 if (SkIsPow2(value)) {
246 return value;
247 }
248
249 uint32_t ceilPow2 = GrNextPow2(value);
250 if (value <= kMagicTol) {
251 return ceilPow2;
252 }
253
254 uint32_t floorPow2 = ceilPow2 >> 1;
255 uint32_t mid = floorPow2 + (floorPow2 >> 1);
256
257 if (value <= mid) {
258 return mid;
259 }
260
261 return ceilPow2;
262}
263
Robert Phillips67d52cf2017-06-05 13:38:13 -0400264sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400265 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400266 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400267 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400268 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500269 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500270
Brian Osman32342f02017-03-04 08:12:46 -0500271 if (this->isAbandoned()) {
272 return nullptr;
273 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400274
Jim Van Verth1676cb92019-01-15 13:24:45 -0500275 // Currently we don't recycle compressed textures as scratch.
276 if (GrPixelConfigIsCompressed(desc.fConfig)) {
277 return nullptr;
278 }
279
Greg Daniel6fa62e22019-08-07 15:52:37 -0400280 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
281 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400282 return nullptr;
283 }
284
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400285 // bin by some multiple or power of 2 with a reasonable min
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400286 GrSurfaceDesc copyDesc(desc);
287 copyDesc.fWidth = MakeApprox(desc.fWidth);
288 copyDesc.fHeight = MakeApprox(desc.fHeight);
Greg Daniel29bf84f2017-09-25 12:25:12 -0400289
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400290 if (auto tex = this->refScratchTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400291 isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400292 return tex;
293 }
294
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400295 return fGpu->createTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400296 GrMipMapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500297}
298
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400299sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400300 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400301 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400302 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400303 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500304 ASSERT_SINGLE_OWNER
305 SkASSERT(!this->isAbandoned());
Jim Van Verth1676cb92019-01-15 13:24:45 -0500306 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
Greg Daniel6fa62e22019-08-07 15:52:37 -0400307 SkASSERT(fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig,
308 renderable, renderTargetSampleCnt, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500309
Brian Salomond17b4a62017-05-23 16:53:47 -0400310 // We could make initial clears work with scratch textures but it is a rare case so we just opt
311 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400312 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500313 GrScratchKey key;
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400314 GrTexturePriv::ComputeScratchKey(desc, renderable, renderTargetSampleCnt, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400315 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500316 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400317 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500318 GrSurface* surface = static_cast<GrSurface*>(resource);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600319 if (GrRenderTarget* rt = surface->asRenderTarget()) {
320 rt->flagAsResolved(); // Scratch textures always start without dirty MSAA.
321 }
Robert Phillips67d52cf2017-06-05 13:38:13 -0400322 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500323 }
324 }
325
Brian Osman32342f02017-03-04 08:12:46 -0500326 return nullptr;
327}
328
Greg Daniel7ef28f32017-04-20 16:41:55 +0000329sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400330 GrColorType colorType,
Greg Daniel2268ad22018-11-15 09:27:38 -0500331 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500332 GrWrapCacheable cacheable,
333 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500334 ASSERT_SINGLE_OWNER
335 if (this->isAbandoned()) {
336 return nullptr;
337 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400338 return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400339}
340
341sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400342 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400343 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500344 GrWrapOwnership ownership,
345 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400346 ASSERT_SINGLE_OWNER
347 if (this->isAbandoned()) {
348 return nullptr;
349 }
Robert Phillips0902c982019-07-16 07:47:56 -0400350 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500351}
352
353sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400354 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500355{
356 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400357 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500358}
359
Greg Danielb46add82019-01-02 14:51:29 -0500360sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
361 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
362 ASSERT_SINGLE_OWNER
363 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
364 vkInfo);
365
366}
367
Brian Osman32342f02017-03-04 08:12:46 -0500368void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
369 GrGpuResource* resource) {
370 ASSERT_SINGLE_OWNER
371 if (this->isAbandoned() || !resource) {
372 return;
373 }
374 resource->resourcePriv().setUniqueKey(key);
375}
376
Brian Salomond28a79d2017-10-16 13:01:07 -0400377sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500378 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400379 return this->isAbandoned() ? nullptr
380 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500381}
382
Brian Salomondbf70722019-02-07 11:31:24 -0500383sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
384 size_t size,
385 const void* data,
386 const GrUniqueKey& key) {
387 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400388 return buffer;
Chris Dalton5d2de082017-12-19 10:40:23 -0700389 }
Brian Salomondbf70722019-02-07 11:31:24 -0500390 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500391 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500392 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700393 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700394 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500395 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700396 }
397 return nullptr;
398}
399
Brian Salomondbf70722019-02-07 11:31:24 -0500400sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
401 int patternSize,
402 int reps,
403 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500404 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700405 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
406
Brian Salomondbf70722019-02-07 11:31:24 -0500407 sk_sp<GrGpuBuffer> buffer(
408 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700409 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700410 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700411 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400412 uint16_t* data = (uint16_t*) buffer->map();
413 SkAutoTArray<uint16_t> temp;
414 if (!data) {
415 temp.reset(reps * patternSize);
416 data = temp.get();
417 }
bsalomoned0bcad2015-05-04 10:36:42 -0700418 for (int i = 0; i < reps; ++i) {
419 int baseIdx = i * patternSize;
420 uint16_t baseVert = (uint16_t)(i * vertCount);
421 for (int j = 0; j < patternSize; ++j) {
422 data[baseIdx+j] = baseVert + pattern[j];
423 }
424 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400425 if (temp.get()) {
426 if (!buffer->updateData(data, bufferSize)) {
427 return nullptr;
428 }
429 } else {
430 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700431 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500432 if (key) {
433 SkASSERT(key->isValid());
434 this->assignUniqueKeyToResource(*key, buffer.get());
435 }
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400436 return buffer;
bsalomoned0bcad2015-05-04 10:36:42 -0700437}
438
Brian Salomon34169692017-08-28 15:32:01 -0400439static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
440
Brian Salomondbf70722019-02-07 11:31:24 -0500441sk_sp<const GrGpuBuffer> GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700442 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
Brian Salomon57caa662017-10-18 12:21:05 +0000443 static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
Brian Salomona29dd9d2019-02-07 13:27:18 -0500444 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700445}
446
Brian Salomon763abf02018-05-01 18:49:38 +0000447int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
Brian Salomon34169692017-08-28 15:32:01 -0400448
Robert Phillips67d52cf2017-06-05 13:38:13 -0400449sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400450 if (this->isAbandoned()) {
451 return nullptr;
452 }
453
bsalomon706f08f2015-05-22 07:35:58 -0700454 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700455 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700456}
457
Brian Salomondbf70722019-02-07 11:31:24 -0500458sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
459 GrAccessPattern accessPattern,
460 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700461 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700462 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700463 }
cdaltond37fe762016-04-21 07:41:50 -0700464 if (kDynamic_GrAccessPattern != accessPattern) {
465 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
466 }
cdaltond37fe762016-04-21 07:41:50 -0700467 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400468 static const size_t MIN_SIZE = 1 << 12;
469 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700470
cdaltond37fe762016-04-21 07:41:50 -0700471 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500472 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
473 auto buffer =
474 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400475 key)));
cdaltond37fe762016-04-21 07:41:50 -0700476 if (!buffer) {
477 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
478 if (!buffer) {
479 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700480 }
481 }
cdaltond37fe762016-04-21 07:41:50 -0700482 if (data) {
483 buffer->updateData(data, size);
484 }
485 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800486}
487
Chris Daltoneffee202019-07-01 22:28:03 -0600488bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int minStencilSampleCount) {
egdanielec00d942015-09-14 12:56:10 -0700489 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600490 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
491 if (stencil && stencil->numSamples() >= minStencilSampleCount) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400492 return true;
egdanielec00d942015-09-14 12:56:10 -0700493 }
494
495 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
496 GrUniqueKey sbKey;
497
498 int width = rt->width();
499 int height = rt->height();
500#if 0
501 if (this->caps()->oversizedStencilSupport()) {
502 width = SkNextPow2(width);
503 height = SkNextPow2(height);
504 }
505#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600506 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
507 width, height, minStencilSampleCount, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400508 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700509 if (!stencil) {
510 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600511 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
512 rt, width, height, minStencilSampleCount));
Robert Phillips01a91282018-07-26 08:03:04 -0400513 if (!stencil) {
514 return false;
egdanielec00d942015-09-14 12:56:10 -0700515 }
Robert Phillips01a91282018-07-26 08:03:04 -0400516 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700517 }
Greg Danielcfa39352018-10-05 12:01:59 -0400518 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700519 }
Chris Dalton215ff332019-07-02 09:38:22 -0600520
521 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
522 return stencil->numSamples() >= minStencilSampleCount;
523 }
524 return false;
egdanielec00d942015-09-14 12:56:10 -0700525}
526
bungeman6bd52842016-10-27 09:30:08 -0700527sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400528 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700529{
ericrkf7b8b8a2016-02-24 14:49:51 -0800530 if (this->isAbandoned()) {
531 return nullptr;
532 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400533 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800534}
Greg Danield85f97d2017-03-07 13:37:21 -0500535
Greg Daniela5cb7812017-06-16 09:45:32 -0400536sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
537 return fGpu->makeSemaphore(isOwned);
538}
539
540sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
Greg Daniel17b7c052018-01-09 13:55:33 -0500541 SemaphoreWrapType wrapType,
Greg Daniela5cb7812017-06-16 09:45:32 -0400542 GrWrapOwnership ownership) {
543 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500544 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
545 wrapType,
546 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500547}