blob: f079c7d9df2d633521e10ad56a836e3971553256 [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"
Robert Phillipse19babf2020-04-06 13:57:30 -040018#include "src/gpu/GrDataUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/GrGpu.h"
20#include "src/gpu/GrGpuBuffer.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040021#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/gpu/GrPath.h"
23#include "src/gpu/GrPathRendering.h"
24#include "src/gpu/GrProxyProvider.h"
25#include "src/gpu/GrRenderTargetPriv.h"
26#include "src/gpu/GrResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/gpu/GrSemaphore.h"
28#include "src/gpu/GrStencilAttachment.h"
29#include "src/gpu/GrTexturePriv.h"
30#include "src/gpu/SkGr.h"
bsalomoned0bcad2015-05-04 10:36:42 -070031
Brian Salomon9f2b86c2019-10-22 10:37:46 -040032const int GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050033
34#define ASSERT_SINGLE_OWNER \
35 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
36
Robert Phillips12c46292019-04-23 07:36:17 -040037GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050038 : fCache(cache)
39 , fGpu(gpu)
40#ifdef SK_DEBUG
41 , fSingleOwner(owner)
42#endif
Robert Phillips4150eea2018-02-07 17:08:21 -050043{
Robert Phillips26c90e02017-03-14 14:39:29 -040044 fCaps = sk_ref_sp(fGpu->caps());
bsalomoned0bcad2015-05-04 10:36:42 -070045}
46
Brian Salomona56a7462020-02-07 14:17:25 -050047sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040048 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -040049 GrColorType colorType,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040050 GrRenderable renderable,
Brian Salomon2af3e702019-08-11 19:10:31 -040051 int renderTargetSampleCnt,
52 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -040053 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -040054 const GrMipLevel texels[],
55 int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050056 ASSERT_SINGLE_OWNER
57
Robert Phillips7f1b4f82017-11-28 07:38:39 -050058 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040059
Brian Osman32342f02017-03-04 08:12:46 -050060 if (this->isAbandoned()) {
61 return nullptr;
62 }
Robert Phillips1119dc32017-04-11 12:54:57 -040063
Brian Salomonbdecacf2018-02-02 20:32:49 -050064 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
Brian Salomona56a7462020-02-07 14:17:25 -050065 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
66 mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050067 return nullptr;
68 }
Brian Salomon8660eb02019-09-20 13:04:13 -040069 // Current rule is that you can provide no level data, just the base, or all the levels.
70 bool hasPixels = mipLevelCount && texels[0].fPixels;
Brian Salomona56a7462020-02-07 14:17:25 -050071 auto scratch = this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt,
72 budgeted, mipMapped, isProtected);
Brian Salomon8660eb02019-09-20 13:04:13 -040073 if (scratch) {
74 if (!hasPixels) {
75 return scratch;
76 }
Brian Salomona56a7462020-02-07 14:17:25 -050077 return this->writePixels(std::move(scratch), colorType, dimensions, texels, mipLevelCount);
Brian Salomona90382f2019-09-17 09:01:56 -040078 }
Brian Salomon1047a492019-07-02 12:25:21 -040079 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -040080 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon8660eb02019-09-20 13:04:13 -040081 GrColorType tempColorType = GrColorType::kUnknown;
82 if (hasPixels) {
Brian Salomona56a7462020-02-07 14:17:25 -050083 tempColorType = this->prepareLevels(format, colorType, dimensions, texels, mipLevelCount,
84 &tmpTexels, &tmpDatas);
Brian Salomon8660eb02019-09-20 13:04:13 -040085 if (tempColorType == GrColorType::kUnknown) {
86 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -040087 }
88 }
Brian Salomona56a7462020-02-07 14:17:25 -050089 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomon8660eb02019-09-20 13:04:13 -040090 isProtected, colorType, tempColorType, tmpTexels.get(),
91 mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -050092}
93
Brian Salomona56a7462020-02-07 14:17:25 -050094sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040095 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040096 GrRenderable renderable,
97 int renderTargetSampleCnt,
98 SkBudgeted budgeted,
Brian Salomon14cb4132019-09-16 13:14:47 -040099 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400100 GrProtected isProtected) {
Brian Salomona56a7462020-02-07 14:17:25 -0500101 sk_sp<GrTexture> tex(this->refScratchTexture(dimensions, format, renderable,
102 renderTargetSampleCnt, mipMapped, isProtected));
Robert Phillips45fdae12017-04-17 12:57:27 -0400103 if (tex && SkBudgeted::kNo == budgeted) {
104 tex->resourcePriv().makeUnbudgeted();
105 }
106
107 return tex;
108}
109
Brian Salomona56a7462020-02-07 14:17:25 -0500110sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400111 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -0400112 GrColorType colorType,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400113 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400114 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500115 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500116 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400117 GrProtected isProtected,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400118 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400119 ASSERT_SINGLE_OWNER
120
Robert Phillips45fdae12017-04-17 12:57:27 -0400121 if (!mipLevel.fPixels) {
122 return nullptr;
123 }
124
Brian Salomona90382f2019-09-17 09:01:56 -0400125 if (SkBackingFit::kApprox == fit) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400126 if (this->isAbandoned()) {
127 return nullptr;
128 }
Brian Salomona56a7462020-02-07 14:17:25 -0500129 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
130 GrMipMapped::kNo)) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400131 return nullptr;
132 }
133
Brian Salomona56a7462020-02-07 14:17:25 -0500134 auto tex = this->createApproxTexture(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon8660eb02019-09-20 13:04:13 -0400135 isProtected);
Brian Salomona90382f2019-09-17 09:01:56 -0400136 if (!tex) {
137 return nullptr;
138 }
Brian Salomona56a7462020-02-07 14:17:25 -0500139 return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
Brian Salomona90382f2019-09-17 09:01:56 -0400140 } else {
Brian Salomona56a7462020-02-07 14:17:25 -0500141 return this->createTexture(dimensions, format, colorType, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400142 budgeted, isProtected, &mipLevel, 1);
Brian Salomona3ffaab2019-07-09 12:26:46 -0400143 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400144}
145
Robert Phillips9f744f72019-12-19 19:14:33 -0500146sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400147 const GrBackendFormat& format,
Robert Phillipse4720c62020-01-14 14:33:24 -0500148 SkBudgeted budgeted,
149 GrMipMapped mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500150 GrProtected isProtected,
Robert Phillipse4720c62020-01-14 14:33:24 -0500151 SkData* data) {
Brian Salomonbb8dde82019-06-27 10:52:13 -0400152 ASSERT_SINGLE_OWNER
153 if (this->isAbandoned()) {
154 return nullptr;
155 }
Robert Phillipse4720c62020-01-14 14:33:24 -0500156 return fGpu->createCompressedTexture(dimensions, format, budgeted, mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500157 isProtected, data->data(), data->size());
Brian Salomonbb8dde82019-06-27 10:52:13 -0400158}
159
Brian Salomona56a7462020-02-07 14:17:25 -0500160sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400161 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400162 GrRenderable renderable,
163 int renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400164 GrMipMapped mipMapped,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400165 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400166 GrProtected isProtected) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400167 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400168 if (this->isAbandoned()) {
169 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500170 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400171
Brian Salomona56a7462020-02-07 14:17:25 -0500172 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
173 mipMapped)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400174 return nullptr;
175 }
176
Greg Danielc3a927f2019-10-16 12:03:50 -0400177 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
178 // textures should be created through the createCompressedTexture function.
179 SkASSERT(!this->caps()->isFormatCompressed(format));
180
Brian Salomona90382f2019-09-17 09:01:56 -0400181 // TODO: Support GrMipMapped::kYes in scratch texture lookup here.
Brian Salomona56a7462020-02-07 14:17:25 -0500182 sk_sp<GrTexture> tex =
183 this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
184 mipMapped, isProtected);
Greg Danielc3a927f2019-10-16 12:03:50 -0400185 if (tex) {
186 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400187 }
188
Brian Salomona56a7462020-02-07 14:17:25 -0500189 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, mipMapped,
190 budgeted, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500191}
192
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400193// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
194// the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400195SkISize GrResourceProvider::MakeApprox(SkISize dimensions) {
196 auto adjust = [](int value) {
197 static const int kMagicTol = 1024;
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400198
Brian Osman788b9162020-02-07 10:36:46 -0500199 value = std::max(kMinScratchTextureSize, value);
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400200
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400201 if (SkIsPow2(value)) {
202 return value;
203 }
204
205 int ceilPow2 = SkNextPow2(value);
206 if (value <= kMagicTol) {
207 return ceilPow2;
208 }
209
210 int floorPow2 = ceilPow2 >> 1;
211 int mid = floorPow2 + (floorPow2 >> 1);
212
213 if (value <= mid) {
214 return mid;
215 }
Brian Salomon322301a2019-10-24 12:50:50 -0400216 return ceilPow2;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400217 };
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400218
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400219 return {adjust(dimensions.width()), adjust(dimensions.height())};
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400220}
221
Brian Salomona56a7462020-02-07 14:17:25 -0500222sk_sp<GrTexture> GrResourceProvider::createApproxTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400223 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400224 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400225 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400226 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500227 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500228
Brian Osman32342f02017-03-04 08:12:46 -0500229 if (this->isAbandoned()) {
230 return nullptr;
231 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400232
Greg Danielc3a927f2019-10-16 12:03:50 -0400233 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
234 // textures should be created through the createCompressedTexture function.
235 SkASSERT(!this->caps()->isFormatCompressed(format));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500236
Brian Salomona56a7462020-02-07 14:17:25 -0500237 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
238 GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400239 return nullptr;
240 }
241
Brian Salomona56a7462020-02-07 14:17:25 -0500242 auto copyDimensions = MakeApprox(dimensions);
Greg Daniel29bf84f2017-09-25 12:25:12 -0400243
Brian Salomona56a7462020-02-07 14:17:25 -0500244 if (auto tex = this->refScratchTexture(copyDimensions, format, renderable,
245 renderTargetSampleCnt, GrMipMapped::kNo, isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400246 return tex;
247 }
248
Brian Salomona56a7462020-02-07 14:17:25 -0500249 return fGpu->createTexture(copyDimensions, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400250 GrMipMapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500251}
252
Brian Salomona56a7462020-02-07 14:17:25 -0500253sk_sp<GrTexture> GrResourceProvider::refScratchTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400254 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400255 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400256 int renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400257 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400258 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500259 ASSERT_SINGLE_OWNER
260 SkASSERT(!this->isAbandoned());
Greg Danielc3a927f2019-10-16 12:03:50 -0400261 SkASSERT(!this->caps()->isFormatCompressed(format));
Brian Salomona56a7462020-02-07 14:17:25 -0500262 SkASSERT(fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
263 GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500264
Brian Salomond17b4a62017-05-23 16:53:47 -0400265 // We could make initial clears work with scratch textures but it is a rare case so we just opt
266 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400267 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500268 GrScratchKey key;
Brian Salomona56a7462020-02-07 14:17:25 -0500269 GrTexturePriv::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
270 renderTargetSampleCnt, mipMapped, isProtected, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400271 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500272 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400273 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500274 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400275 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500276 }
277 }
278
Brian Osman32342f02017-03-04 08:12:46 -0500279 return nullptr;
280}
281
Greg Daniel7ef28f32017-04-20 16:41:55 +0000282sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Greg Daniel2268ad22018-11-15 09:27:38 -0500283 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500284 GrWrapCacheable cacheable,
285 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500286 ASSERT_SINGLE_OWNER
287 if (this->isAbandoned()) {
288 return nullptr;
289 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400290 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400291}
292
Robert Phillipsead321b2019-12-19 10:16:32 -0500293sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
294 GrWrapOwnership ownership,
295 GrWrapCacheable cacheable) {
296 ASSERT_SINGLE_OWNER
297 if (this->isAbandoned()) {
298 return nullptr;
299 }
300
301 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
302}
303
304
Brian Salomond17f6582017-07-19 18:28:58 -0400305sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400306 int sampleCnt,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500307 GrWrapOwnership ownership,
308 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400309 ASSERT_SINGLE_OWNER
310 if (this->isAbandoned()) {
311 return nullptr;
312 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400313 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500314}
315
316sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400317 const GrBackendRenderTarget& backendRT) {
Brian Osman32342f02017-03-04 08:12:46 -0500318 ASSERT_SINGLE_OWNER
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400319 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500320}
321
Greg Danielb46add82019-01-02 14:51:29 -0500322sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
323 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
324 ASSERT_SINGLE_OWNER
325 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
326 vkInfo);
327
328}
329
Brian Osman32342f02017-03-04 08:12:46 -0500330void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
331 GrGpuResource* resource) {
332 ASSERT_SINGLE_OWNER
333 if (this->isAbandoned() || !resource) {
334 return;
335 }
336 resource->resourcePriv().setUniqueKey(key);
337}
338
Brian Salomond28a79d2017-10-16 13:01:07 -0400339sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500340 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400341 return this->isAbandoned() ? nullptr
342 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500343}
344
Brian Salomondbf70722019-02-07 11:31:24 -0500345sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
346 size_t size,
347 const void* data,
348 const GrUniqueKey& key) {
349 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Mike Kleina9609ea2020-02-18 13:33:23 -0600350 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700351 }
Brian Salomondbf70722019-02-07 11:31:24 -0500352 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500353 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500354 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700355 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700356 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500357 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700358 }
359 return nullptr;
360}
361
Brian Salomondbf70722019-02-07 11:31:24 -0500362sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
363 int patternSize,
364 int reps,
365 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500366 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700367 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
368
Brian Salomondbf70722019-02-07 11:31:24 -0500369 sk_sp<GrGpuBuffer> buffer(
370 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700371 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700372 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700373 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400374 uint16_t* data = (uint16_t*) buffer->map();
375 SkAutoTArray<uint16_t> temp;
376 if (!data) {
377 temp.reset(reps * patternSize);
378 data = temp.get();
379 }
bsalomoned0bcad2015-05-04 10:36:42 -0700380 for (int i = 0; i < reps; ++i) {
381 int baseIdx = i * patternSize;
382 uint16_t baseVert = (uint16_t)(i * vertCount);
383 for (int j = 0; j < patternSize; ++j) {
384 data[baseIdx+j] = baseVert + pattern[j];
385 }
386 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400387 if (temp.get()) {
388 if (!buffer->updateData(data, bufferSize)) {
389 return nullptr;
390 }
391 } else {
392 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700393 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500394 if (key) {
395 SkASSERT(key->isValid());
396 this->assignUniqueKeyToResource(*key, buffer.get());
397 }
Mike Kleina9609ea2020-02-18 13:33:23 -0600398 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700399}
400
Robert Phillipsee08d522019-10-28 16:34:44 -0400401///////////////////////////////////////////////////////////////////////////////////////////////////
402static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
403static const int kVertsPerNonAAQuad = 4;
404static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400405
Robert Phillipsee08d522019-10-28 16:34:44 -0400406sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500407 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400408
409 static const uint16_t kNonAAQuadIndexPattern[] = {
410 0, 1, 2, 2, 1, 3
411 };
412
Brian Salomon4dea72a2019-12-18 10:43:10 -0500413 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400414
415 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
416 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700417}
418
Robert Phillipsee08d522019-10-28 16:34:44 -0400419int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
420int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
421int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400422
Robert Phillipsee08d522019-10-28 16:34:44 -0400423///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500424static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400425static const int kVertsPerAAQuad = 8;
426static const int kIndicesPerAAQuad = 30;
427
428sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500429 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400430
431 // clang-format off
432 static const uint16_t kAAQuadIndexPattern[] = {
433 0, 1, 2, 1, 3, 2,
434 0, 4, 1, 4, 5, 1,
435 0, 6, 4, 0, 2, 6,
436 2, 3, 6, 3, 7, 6,
437 1, 5, 3, 3, 5, 7,
438 };
439 // clang-format on
440
Brian Salomon4dea72a2019-12-18 10:43:10 -0500441 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400442
443 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
444 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
445}
446
447int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
448int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
449int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
450
451///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400452sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400453 if (this->isAbandoned()) {
454 return nullptr;
455 }
456
bsalomon706f08f2015-05-22 07:35:58 -0700457 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700458 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700459}
460
Brian Salomondbf70722019-02-07 11:31:24 -0500461sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
462 GrAccessPattern accessPattern,
463 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700464 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700465 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700466 }
cdaltond37fe762016-04-21 07:41:50 -0700467 if (kDynamic_GrAccessPattern != accessPattern) {
468 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
469 }
cdaltond37fe762016-04-21 07:41:50 -0700470 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400471 static const size_t MIN_SIZE = 1 << 12;
Brian Osman788b9162020-02-07 10:36:46 -0500472 size_t allocSize = std::max(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700473
cdaltond37fe762016-04-21 07:41:50 -0700474 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500475 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
476 auto buffer =
477 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400478 key)));
cdaltond37fe762016-04-21 07:41:50 -0700479 if (!buffer) {
480 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
481 if (!buffer) {
482 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700483 }
484 }
cdaltond37fe762016-04-21 07:41:50 -0700485 if (data) {
486 buffer->updateData(data, size);
487 }
488 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800489}
490
Chris Daltonf00b95b2019-11-07 21:14:41 -0700491bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700492 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600493 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700494 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400495 return true;
egdanielec00d942015-09-14 12:56:10 -0700496 }
497
498 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
499 GrUniqueKey sbKey;
500
501 int width = rt->width();
502 int height = rt->height();
503#if 0
504 if (this->caps()->oversizedStencilSupport()) {
505 width = SkNextPow2(width);
506 height = SkNextPow2(height);
507 }
508#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600509 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700510 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400511 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700512 if (!stencil) {
513 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600514 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700515 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400516 if (!stencil) {
517 return false;
egdanielec00d942015-09-14 12:56:10 -0700518 }
Robert Phillips01a91282018-07-26 08:03:04 -0400519 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700520 }
Greg Danielcfa39352018-10-05 12:01:59 -0400521 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700522 }
Chris Dalton215ff332019-07-02 09:38:22 -0600523
524 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700525 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600526 }
527 return false;
egdanielec00d942015-09-14 12:56:10 -0700528}
529
bungeman6bd52842016-10-27 09:30:08 -0700530sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400531 const GrBackendTexture& tex, int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800532 if (this->isAbandoned()) {
533 return nullptr;
534 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400535 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800536}
Greg Danield85f97d2017-03-07 13:37:21 -0500537
Greg Daniel301015c2019-11-18 14:06:46 -0500538std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
539 bool isOwned) {
540 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400541}
542
Greg Daniel301015c2019-11-18 14:06:46 -0500543std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
544 const GrBackendSemaphore& semaphore,
545 SemaphoreWrapType wrapType,
546 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400547 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500548 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
549 wrapType,
550 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500551}
Brian Salomon8660eb02019-09-20 13:04:13 -0400552
553// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
554// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
555static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomona56a7462020-02-07 14:17:25 -0500556 SkISize dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400557 bool rowBytesSupport,
558 GrColorType origColorType,
559 GrColorType allowedColorType,
560 GrMipLevel* outLevel,
561 std::unique_ptr<char[]>* data) {
562 if (!inLevel.fPixels) {
563 outLevel->fPixels = nullptr;
564 outLevel->fRowBytes = 0;
565 return true;
566 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400567 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400568 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
569 if (actualRB < minRB) {
570 return false;
571 }
572 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
573 outLevel->fRowBytes = actualRB;
574 outLevel->fPixels = inLevel.fPixels;
575 return true;
576 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400577 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
578 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400579 outLevel->fPixels = data->get();
580 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400581 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
582 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400583 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
584}
585
586GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
587 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500588 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400589 const GrMipLevel texels[],
590 int mipLevelCount,
591 TempLevels* tempLevels,
592 TempLevelDatas* tempLevelDatas) const {
593 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
594
595 auto allowedColorType =
596 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
597 if (allowedColorType == GrColorType::kUnknown) {
598 return GrColorType::kUnknown;
599 }
600 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
601 tempLevels->reset(mipLevelCount);
602 tempLevelDatas->reset(mipLevelCount);
603 auto size = baseSize;
604 for (int i = 0; i < mipLevelCount; ++i) {
605 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
606 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
607 return GrColorType::kUnknown;
608 }
609 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
610 }
611 return allowedColorType;
612}
613
614sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
615 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500616 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400617 const GrMipLevel texels[],
618 int mipLevelCount) const {
619 SkASSERT(!this->isAbandoned());
620 SkASSERT(texture);
621 SkASSERT(colorType != GrColorType::kUnknown);
622 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
623
624 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
625 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
626 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
627 mipLevelCount, &tmpTexels, &tmpDatas);
628 if (tempColorType == GrColorType::kUnknown) {
629 return nullptr;
630 }
631 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
632 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
633 return texture;
634}