blob: 64e9e5aa18ebaf03676d2b5be57ca09817650f6a [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/GrResourceKey.h"
12#include "include/private/GrSingleOwner.h"
Brian Salomon1047a492019-07-02 12:25:21 -040013#include "src/core/SkConvertPixels.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkMathPriv.h"
15#include "src/gpu/GrCaps.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040016#include "src/gpu/GrDataUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/gpu/GrGpu.h"
18#include "src/gpu/GrGpuBuffer.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040019#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#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
Brian Salomon9f2b86c2019-10-22 10:37:46 -040030const int GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050031
Adlai Holler33dbd652020-06-01 12:35:42 -040032#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner)
Brian Osman32342f02017-03-04 08:12:46 -050033
Robert Phillips12c46292019-04-23 07:36:17 -040034GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050035 : fCache(cache)
36 , fGpu(gpu)
37#ifdef SK_DEBUG
38 , fSingleOwner(owner)
39#endif
Robert Phillips4150eea2018-02-07 17:08:21 -050040{
Robert Phillips26c90e02017-03-14 14:39:29 -040041 fCaps = sk_ref_sp(fGpu->caps());
bsalomoned0bcad2015-05-04 10:36:42 -070042}
43
Brian Salomona56a7462020-02-07 14:17:25 -050044sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040045 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -040046 GrColorType colorType,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040047 GrRenderable renderable,
Brian Salomon2af3e702019-08-11 19:10:31 -040048 int renderTargetSampleCnt,
49 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -040050 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -040051 const GrMipLevel texels[],
52 int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050053 ASSERT_SINGLE_OWNER
54
Robert Phillips7f1b4f82017-11-28 07:38:39 -050055 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040056
Brian Osman32342f02017-03-04 08:12:46 -050057 if (this->isAbandoned()) {
58 return nullptr;
59 }
Robert Phillips1119dc32017-04-11 12:54:57 -040060
Brian Salomon7e67dca2020-07-21 09:27:25 -040061 GrMipmapped mipMapped = mipLevelCount > 1 ? GrMipmapped::kYes : GrMipmapped::kNo;
Brian Salomona56a7462020-02-07 14:17:25 -050062 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
63 mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050064 return nullptr;
65 }
Brian Salomon8660eb02019-09-20 13:04:13 -040066 // Current rule is that you can provide no level data, just the base, or all the levels.
67 bool hasPixels = mipLevelCount && texels[0].fPixels;
Brian Salomona56a7462020-02-07 14:17:25 -050068 auto scratch = this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt,
69 budgeted, mipMapped, isProtected);
Brian Salomon8660eb02019-09-20 13:04:13 -040070 if (scratch) {
71 if (!hasPixels) {
72 return scratch;
73 }
Brian Salomona56a7462020-02-07 14:17:25 -050074 return this->writePixels(std::move(scratch), colorType, dimensions, texels, mipLevelCount);
Brian Salomona90382f2019-09-17 09:01:56 -040075 }
Brian Salomon1047a492019-07-02 12:25:21 -040076 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -040077 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon8660eb02019-09-20 13:04:13 -040078 GrColorType tempColorType = GrColorType::kUnknown;
79 if (hasPixels) {
Brian Salomona56a7462020-02-07 14:17:25 -050080 tempColorType = this->prepareLevels(format, colorType, dimensions, texels, mipLevelCount,
81 &tmpTexels, &tmpDatas);
Brian Salomon8660eb02019-09-20 13:04:13 -040082 if (tempColorType == GrColorType::kUnknown) {
83 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -040084 }
85 }
Brian Salomona56a7462020-02-07 14:17:25 -050086 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomon8660eb02019-09-20 13:04:13 -040087 isProtected, colorType, tempColorType, tmpTexels.get(),
88 mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -050089}
90
Brian Salomona56a7462020-02-07 14:17:25 -050091sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040092 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040093 GrRenderable renderable,
94 int renderTargetSampleCnt,
95 SkBudgeted budgeted,
Brian Salomon7e67dca2020-07-21 09:27:25 -040096 GrMipmapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -040097 GrProtected isProtected) {
Brian Salomona56a7462020-02-07 14:17:25 -050098 sk_sp<GrTexture> tex(this->refScratchTexture(dimensions, format, renderable,
99 renderTargetSampleCnt, mipMapped, isProtected));
Robert Phillips45fdae12017-04-17 12:57:27 -0400100 if (tex && SkBudgeted::kNo == budgeted) {
101 tex->resourcePriv().makeUnbudgeted();
102 }
103
104 return tex;
105}
106
Brian Salomona56a7462020-02-07 14:17:25 -0500107sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400108 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -0400109 GrColorType colorType,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400110 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400111 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500112 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500113 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400114 GrProtected isProtected,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400115 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400116 ASSERT_SINGLE_OWNER
117
Robert Phillips45fdae12017-04-17 12:57:27 -0400118 if (!mipLevel.fPixels) {
119 return nullptr;
120 }
121
Brian Salomona90382f2019-09-17 09:01:56 -0400122 if (SkBackingFit::kApprox == fit) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400123 if (this->isAbandoned()) {
124 return nullptr;
125 }
Brian Salomona56a7462020-02-07 14:17:25 -0500126 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400127 GrMipmapped::kNo)) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400128 return nullptr;
129 }
130
Brian Salomona56a7462020-02-07 14:17:25 -0500131 auto tex = this->createApproxTexture(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon8660eb02019-09-20 13:04:13 -0400132 isProtected);
Brian Salomona90382f2019-09-17 09:01:56 -0400133 if (!tex) {
134 return nullptr;
135 }
Brian Salomona56a7462020-02-07 14:17:25 -0500136 return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
Brian Salomona90382f2019-09-17 09:01:56 -0400137 } else {
Brian Salomona56a7462020-02-07 14:17:25 -0500138 return this->createTexture(dimensions, format, colorType, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400139 budgeted, isProtected, &mipLevel, 1);
Brian Salomona3ffaab2019-07-09 12:26:46 -0400140 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400141}
142
Robert Phillips9f744f72019-12-19 19:14:33 -0500143sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400144 const GrBackendFormat& format,
Robert Phillipse4720c62020-01-14 14:33:24 -0500145 SkBudgeted budgeted,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400146 GrMipmapped mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500147 GrProtected isProtected,
Robert Phillipse4720c62020-01-14 14:33:24 -0500148 SkData* data) {
Brian Salomonbb8dde82019-06-27 10:52:13 -0400149 ASSERT_SINGLE_OWNER
150 if (this->isAbandoned()) {
151 return nullptr;
152 }
Robert Phillipse4720c62020-01-14 14:33:24 -0500153 return fGpu->createCompressedTexture(dimensions, format, budgeted, mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500154 isProtected, data->data(), data->size());
Brian Salomonbb8dde82019-06-27 10:52:13 -0400155}
156
Brian Salomona56a7462020-02-07 14:17:25 -0500157sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400158 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400159 GrRenderable renderable,
160 int renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400161 GrMipmapped mipMapped,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400162 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400163 GrProtected isProtected) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400164 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400165 if (this->isAbandoned()) {
166 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500167 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400168
Brian Salomona56a7462020-02-07 14:17:25 -0500169 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
170 mipMapped)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400171 return nullptr;
172 }
173
Greg Danielc3a927f2019-10-16 12:03:50 -0400174 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
175 // textures should be created through the createCompressedTexture function.
176 SkASSERT(!this->caps()->isFormatCompressed(format));
177
Brian Salomon7e67dca2020-07-21 09:27:25 -0400178 // TODO: Support GrMipmapped::kYes in scratch texture lookup here.
Brian Salomona56a7462020-02-07 14:17:25 -0500179 sk_sp<GrTexture> tex =
180 this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
181 mipMapped, isProtected);
Greg Danielc3a927f2019-10-16 12:03:50 -0400182 if (tex) {
183 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400184 }
185
Brian Salomona56a7462020-02-07 14:17:25 -0500186 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, mipMapped,
187 budgeted, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500188}
189
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400190// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
191// 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 -0400192SkISize GrResourceProvider::MakeApprox(SkISize dimensions) {
193 auto adjust = [](int value) {
194 static const int kMagicTol = 1024;
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400195
Brian Osman788b9162020-02-07 10:36:46 -0500196 value = std::max(kMinScratchTextureSize, value);
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400197
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400198 if (SkIsPow2(value)) {
199 return value;
200 }
201
202 int ceilPow2 = SkNextPow2(value);
203 if (value <= kMagicTol) {
204 return ceilPow2;
205 }
206
207 int floorPow2 = ceilPow2 >> 1;
208 int mid = floorPow2 + (floorPow2 >> 1);
209
210 if (value <= mid) {
211 return mid;
212 }
Brian Salomon322301a2019-10-24 12:50:50 -0400213 return ceilPow2;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400214 };
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400215
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400216 return {adjust(dimensions.width()), adjust(dimensions.height())};
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400217}
218
Brian Salomona56a7462020-02-07 14:17:25 -0500219sk_sp<GrTexture> GrResourceProvider::createApproxTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400220 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400221 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400222 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400223 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500224 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500225
Brian Osman32342f02017-03-04 08:12:46 -0500226 if (this->isAbandoned()) {
227 return nullptr;
228 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400229
Greg Danielc3a927f2019-10-16 12:03:50 -0400230 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
231 // textures should be created through the createCompressedTexture function.
232 SkASSERT(!this->caps()->isFormatCompressed(format));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500233
Brian Salomona56a7462020-02-07 14:17:25 -0500234 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400235 GrMipmapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400236 return nullptr;
237 }
238
Brian Salomona56a7462020-02-07 14:17:25 -0500239 auto copyDimensions = MakeApprox(dimensions);
Greg Daniel29bf84f2017-09-25 12:25:12 -0400240
Brian Salomona56a7462020-02-07 14:17:25 -0500241 if (auto tex = this->refScratchTexture(copyDimensions, format, renderable,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400242 renderTargetSampleCnt, GrMipmapped::kNo, isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400243 return tex;
244 }
245
Brian Salomona56a7462020-02-07 14:17:25 -0500246 return fGpu->createTexture(copyDimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400247 GrMipmapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500248}
249
Brian Salomona56a7462020-02-07 14:17:25 -0500250sk_sp<GrTexture> GrResourceProvider::refScratchTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400251 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400252 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400253 int renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400254 GrMipmapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400255 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500256 ASSERT_SINGLE_OWNER
257 SkASSERT(!this->isAbandoned());
Greg Danielc3a927f2019-10-16 12:03:50 -0400258 SkASSERT(!this->caps()->isFormatCompressed(format));
Brian Salomona56a7462020-02-07 14:17:25 -0500259 SkASSERT(fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400260 GrMipmapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500261
Brian Salomond17b4a62017-05-23 16:53:47 -0400262 // We could make initial clears work with scratch textures but it is a rare case so we just opt
263 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400264 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500265 GrScratchKey key;
Brian Salomona56a7462020-02-07 14:17:25 -0500266 GrTexturePriv::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
267 renderTargetSampleCnt, mipMapped, isProtected, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400268 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500269 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400270 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500271 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400272 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500273 }
274 }
275
Brian Osman32342f02017-03-04 08:12:46 -0500276 return nullptr;
277}
278
Greg Daniel7ef28f32017-04-20 16:41:55 +0000279sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Greg Daniel2268ad22018-11-15 09:27:38 -0500280 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500281 GrWrapCacheable cacheable,
282 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500283 ASSERT_SINGLE_OWNER
284 if (this->isAbandoned()) {
285 return nullptr;
286 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400287 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400288}
289
Robert Phillipsead321b2019-12-19 10:16:32 -0500290sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
291 GrWrapOwnership ownership,
292 GrWrapCacheable cacheable) {
293 ASSERT_SINGLE_OWNER
294 if (this->isAbandoned()) {
295 return nullptr;
296 }
297
298 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
299}
300
301
Brian Salomond17f6582017-07-19 18:28:58 -0400302sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400303 int sampleCnt,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500304 GrWrapOwnership ownership,
305 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400306 ASSERT_SINGLE_OWNER
307 if (this->isAbandoned()) {
308 return nullptr;
309 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400310 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500311}
312
313sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400314 const GrBackendRenderTarget& backendRT) {
Brian Osman32342f02017-03-04 08:12:46 -0500315 ASSERT_SINGLE_OWNER
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400316 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500317}
318
Greg Danielb46add82019-01-02 14:51:29 -0500319sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
320 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
321 ASSERT_SINGLE_OWNER
322 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
323 vkInfo);
324
325}
326
Brian Osman32342f02017-03-04 08:12:46 -0500327void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
328 GrGpuResource* resource) {
329 ASSERT_SINGLE_OWNER
330 if (this->isAbandoned() || !resource) {
331 return;
332 }
333 resource->resourcePriv().setUniqueKey(key);
334}
335
Brian Salomond28a79d2017-10-16 13:01:07 -0400336sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500337 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400338 return this->isAbandoned() ? nullptr
339 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500340}
341
Brian Salomondbf70722019-02-07 11:31:24 -0500342sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
343 size_t size,
344 const void* data,
345 const GrUniqueKey& key) {
346 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Mike Kleina9609ea2020-02-18 13:33:23 -0600347 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700348 }
Brian Salomondbf70722019-02-07 11:31:24 -0500349 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500350 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500351 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700352 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700353 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500354 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700355 }
356 return nullptr;
357}
358
Brian Salomondbf70722019-02-07 11:31:24 -0500359sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
360 int patternSize,
361 int reps,
362 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500363 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700364 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
365
Brian Salomondbf70722019-02-07 11:31:24 -0500366 sk_sp<GrGpuBuffer> buffer(
367 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700368 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700369 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700370 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400371 uint16_t* data = (uint16_t*) buffer->map();
372 SkAutoTArray<uint16_t> temp;
373 if (!data) {
374 temp.reset(reps * patternSize);
375 data = temp.get();
376 }
bsalomoned0bcad2015-05-04 10:36:42 -0700377 for (int i = 0; i < reps; ++i) {
378 int baseIdx = i * patternSize;
379 uint16_t baseVert = (uint16_t)(i * vertCount);
380 for (int j = 0; j < patternSize; ++j) {
381 data[baseIdx+j] = baseVert + pattern[j];
382 }
383 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400384 if (temp.get()) {
385 if (!buffer->updateData(data, bufferSize)) {
386 return nullptr;
387 }
388 } else {
389 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700390 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500391 if (key) {
392 SkASSERT(key->isValid());
393 this->assignUniqueKeyToResource(*key, buffer.get());
394 }
Mike Kleina9609ea2020-02-18 13:33:23 -0600395 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700396}
397
Robert Phillipsee08d522019-10-28 16:34:44 -0400398///////////////////////////////////////////////////////////////////////////////////////////////////
399static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
400static const int kVertsPerNonAAQuad = 4;
401static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400402
Robert Phillipsee08d522019-10-28 16:34:44 -0400403sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500404 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400405
406 static const uint16_t kNonAAQuadIndexPattern[] = {
407 0, 1, 2, 2, 1, 3
408 };
409
Brian Salomon4dea72a2019-12-18 10:43:10 -0500410 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400411
412 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
413 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700414}
415
Robert Phillipsee08d522019-10-28 16:34:44 -0400416int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
417int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
418int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400419
Robert Phillipsee08d522019-10-28 16:34:44 -0400420///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500421static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400422static const int kVertsPerAAQuad = 8;
423static const int kIndicesPerAAQuad = 30;
424
425sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500426 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400427
428 // clang-format off
429 static const uint16_t kAAQuadIndexPattern[] = {
430 0, 1, 2, 1, 3, 2,
431 0, 4, 1, 4, 5, 1,
432 0, 6, 4, 0, 2, 6,
433 2, 3, 6, 3, 7, 6,
434 1, 5, 3, 3, 5, 7,
435 };
436 // clang-format on
437
Brian Salomon4dea72a2019-12-18 10:43:10 -0500438 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400439
440 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
441 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
442}
443
444int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
445int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
446int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
447
448///////////////////////////////////////////////////////////////////////////////////////////////////
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;
Brian Osman788b9162020-02-07 10:36:46 -0500469 size_t allocSize = std::max(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 Daltonf00b95b2019-11-07 21:14:41 -0700488bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700489 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600490 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700491 if (stencil && stencil->numSamples() == numStencilSamples) {
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(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700507 width, height, numStencilSamples, &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(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700512 rt, width, height, numStencilSamples));
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()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700522 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600523 }
524 return false;
egdanielec00d942015-09-14 12:56:10 -0700525}
526
bungeman6bd52842016-10-27 09:30:08 -0700527sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400528 const GrBackendTexture& tex, int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800529 if (this->isAbandoned()) {
530 return nullptr;
531 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400532 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800533}
Greg Danield85f97d2017-03-07 13:37:21 -0500534
Greg Daniel301015c2019-11-18 14:06:46 -0500535std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
536 bool isOwned) {
537 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400538}
539
Greg Daniel301015c2019-11-18 14:06:46 -0500540std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
541 const GrBackendSemaphore& semaphore,
542 SemaphoreWrapType wrapType,
543 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400544 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500545 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
546 wrapType,
547 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500548}
Brian Salomon8660eb02019-09-20 13:04:13 -0400549
550// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
551// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
552static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomona56a7462020-02-07 14:17:25 -0500553 SkISize dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400554 bool rowBytesSupport,
555 GrColorType origColorType,
556 GrColorType allowedColorType,
557 GrMipLevel* outLevel,
558 std::unique_ptr<char[]>* data) {
559 if (!inLevel.fPixels) {
560 outLevel->fPixels = nullptr;
561 outLevel->fRowBytes = 0;
562 return true;
563 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400564 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400565 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
566 if (actualRB < minRB) {
567 return false;
568 }
569 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
570 outLevel->fRowBytes = actualRB;
571 outLevel->fPixels = inLevel.fPixels;
572 return true;
573 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400574 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
575 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400576 outLevel->fPixels = data->get();
577 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400578 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
579 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400580 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
581}
582
583GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
584 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500585 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400586 const GrMipLevel texels[],
587 int mipLevelCount,
588 TempLevels* tempLevels,
589 TempLevelDatas* tempLevelDatas) const {
590 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
591
592 auto allowedColorType =
593 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
594 if (allowedColorType == GrColorType::kUnknown) {
595 return GrColorType::kUnknown;
596 }
597 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
598 tempLevels->reset(mipLevelCount);
599 tempLevelDatas->reset(mipLevelCount);
600 auto size = baseSize;
601 for (int i = 0; i < mipLevelCount; ++i) {
602 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
603 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
604 return GrColorType::kUnknown;
605 }
606 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
607 }
608 return allowedColorType;
609}
610
611sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
612 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500613 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400614 const GrMipLevel texels[],
615 int mipLevelCount) const {
616 SkASSERT(!this->isAbandoned());
617 SkASSERT(texture);
618 SkASSERT(colorType != GrColorType::kUnknown);
619 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
620
621 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
622 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
623 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
624 mipLevelCount, &tmpTexels, &tmpDatas);
625 if (tempColorType == GrColorType::kUnknown) {
626 return nullptr;
627 }
628 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
629 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
630 return texture;
631}