blob: ce3cf90e8cddfc4ad2f2c9d5512b09716e19dd4d [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"
Greg Danielc0d69152020-10-08 14:59:00 -040015#include "src/gpu/GrAttachment.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrCaps.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040017#include "src/gpu/GrDataUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrGpu.h"
19#include "src/gpu/GrGpuBuffer.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040020#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrPath.h"
22#include "src/gpu/GrPathRendering.h"
23#include "src/gpu/GrProxyProvider.h"
Brian Salomonf7f54332020-07-28 09:23:35 -040024#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrSemaphore.h"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040027#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#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 Salomon4cfae3b2020-07-23 10:33:24 -0400266 GrTexture::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 }
Jim Van Verth939cc7a2020-08-14 18:00:36 -0400467 // bin by pow2+midpoint with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400468 static const size_t MIN_SIZE = 1 << 12;
Jim Van Verth939cc7a2020-08-14 18:00:36 -0400469 size_t allocSize = std::max(size, MIN_SIZE);
470 size_t ceilPow2 = GrNextSizePow2(allocSize);
471 size_t floorPow2 = ceilPow2 >> 1;
472 size_t mid = floorPow2 + (floorPow2 >> 1);
473 allocSize = (allocSize <= mid) ? mid : ceilPow2;
robertphillips1b8e1b52015-06-24 06:54:10 -0700474
cdaltond37fe762016-04-21 07:41:50 -0700475 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500476 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
477 auto buffer =
478 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400479 key)));
cdaltond37fe762016-04-21 07:41:50 -0700480 if (!buffer) {
481 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
482 if (!buffer) {
483 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700484 }
485 }
cdaltond37fe762016-04-21 07:41:50 -0700486 if (data) {
487 buffer->updateData(data, size);
488 }
489 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800490}
491
Chris Daltonf00b95b2019-11-07 21:14:41 -0700492bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700493 SkASSERT(rt);
Greg Danielc0d69152020-10-08 14:59:00 -0400494 GrAttachment* stencil = rt->getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700495 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400496 return true;
egdanielec00d942015-09-14 12:56:10 -0700497 }
498
499 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
500 GrUniqueKey sbKey;
501
egdanielec00d942015-09-14 12:56:10 -0700502#if 0
503 if (this->caps()->oversizedStencilSupport()) {
504 width = SkNextPow2(width);
505 height = SkNextPow2(height);
506 }
507#endif
Greg Danielb8949bd2020-10-12 15:21:02 -0400508 GrBackendFormat stencilFormat =
509 this->gpu()->getPreferredStencilFormat(rt->backendFormat());
510 if (!stencilFormat.isValid()) {
511 return false;
512 }
513 GrProtected isProtected = rt->isProtected() ? GrProtected::kYes : GrProtected::kNo;
Greg Danielc0d69152020-10-08 14:59:00 -0400514 GrAttachment::ComputeSharedAttachmentUniqueKey(
Greg Danielb8949bd2020-10-12 15:21:02 -0400515 *this->caps(), stencilFormat, rt->dimensions(), GrAttachment::UsageFlags::kStencil,
516 numStencilSamples, isProtected, &sbKey);
Greg Danielc0d69152020-10-08 14:59:00 -0400517 auto stencil = this->findByUniqueKey<GrAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700518 if (!stencil) {
519 // Need to try and create a new stencil
Greg Danielc0d69152020-10-08 14:59:00 -0400520 stencil = this->gpu()->makeStencilAttachmentForRenderTarget(rt, rt->dimensions(),
521 numStencilSamples);
Robert Phillips01a91282018-07-26 08:03:04 -0400522 if (!stencil) {
523 return false;
egdanielec00d942015-09-14 12:56:10 -0700524 }
Robert Phillips01a91282018-07-26 08:03:04 -0400525 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700526 }
Brian Salomonf7f54332020-07-28 09:23:35 -0400527 rt->attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700528 }
Chris Dalton215ff332019-07-02 09:38:22 -0600529
Greg Danielc0d69152020-10-08 14:59:00 -0400530 if (GrAttachment* stencil = rt->getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700531 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600532 }
533 return false;
egdanielec00d942015-09-14 12:56:10 -0700534}
535
Greg Daniel5d0330e2020-10-12 16:05:21 -0400536sk_sp<GrAttachment> GrResourceProvider::makeMSAAAttachment(SkISize dimensions,
537 const GrBackendFormat& format,
538 int sampleCnt,
539 GrProtected isProtected) {
540 ASSERT_SINGLE_OWNER
541
542 SkASSERT(sampleCnt > 1);
543
544 if (this->isAbandoned()) {
545 return nullptr;
546 }
547
548 if (!fCaps->validateSurfaceParams(dimensions, format, GrRenderable::kYes, sampleCnt,
549 GrMipMapped::kNo)) {
550 return nullptr;
551 }
552
553 auto scratch = this->refScratchMSAAAttachment(dimensions, format, sampleCnt, isProtected);
554 if (scratch) {
555 return scratch;
556 }
557
558 return fGpu->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected);
559}
560
561sk_sp<GrAttachment> GrResourceProvider::refScratchMSAAAttachment(SkISize dimensions,
562 const GrBackendFormat& format,
563 int sampleCnt,
564 GrProtected isProtected) {
565 ASSERT_SINGLE_OWNER
566 SkASSERT(!this->isAbandoned());
567 SkASSERT(!this->caps()->isFormatCompressed(format));
568 SkASSERT(fCaps->validateSurfaceParams(dimensions, format, GrRenderable::kYes, sampleCnt,
569 GrMipmapped::kNo));
570
571 GrScratchKey key;
572 GrAttachment::ComputeScratchKey(*this->caps(), format, dimensions,
573 GrAttachment::UsageFlags::kMSAA, sampleCnt, isProtected, &key);
574 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
575 if (resource) {
576 fGpu->stats()->incNumScratchMSAAAttachmentsReused();
577 GrAttachment* attachment = static_cast<GrAttachment*>(resource);
578 return sk_sp<GrAttachment>(attachment);
579 }
580
581 return nullptr;
582}
583
Greg Daniel301015c2019-11-18 14:06:46 -0500584std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
585 bool isOwned) {
586 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400587}
588
Greg Daniel301015c2019-11-18 14:06:46 -0500589std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
590 const GrBackendSemaphore& semaphore,
591 SemaphoreWrapType wrapType,
592 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400593 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500594 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
595 wrapType,
596 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500597}
Brian Salomon8660eb02019-09-20 13:04:13 -0400598
599// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
600// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
601static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomona56a7462020-02-07 14:17:25 -0500602 SkISize dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400603 bool rowBytesSupport,
604 GrColorType origColorType,
605 GrColorType allowedColorType,
606 GrMipLevel* outLevel,
607 std::unique_ptr<char[]>* data) {
608 if (!inLevel.fPixels) {
609 outLevel->fPixels = nullptr;
610 outLevel->fRowBytes = 0;
611 return true;
612 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400613 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400614 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
615 if (actualRB < minRB) {
616 return false;
617 }
618 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
619 outLevel->fRowBytes = actualRB;
620 outLevel->fPixels = inLevel.fPixels;
621 return true;
622 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400623 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
624 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400625 outLevel->fPixels = data->get();
626 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400627 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
628 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400629 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
630}
631
632GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
633 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500634 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400635 const GrMipLevel texels[],
636 int mipLevelCount,
637 TempLevels* tempLevels,
638 TempLevelDatas* tempLevelDatas) const {
639 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
640
641 auto allowedColorType =
642 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
643 if (allowedColorType == GrColorType::kUnknown) {
644 return GrColorType::kUnknown;
645 }
646 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
647 tempLevels->reset(mipLevelCount);
648 tempLevelDatas->reset(mipLevelCount);
649 auto size = baseSize;
650 for (int i = 0; i < mipLevelCount; ++i) {
651 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
652 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
653 return GrColorType::kUnknown;
654 }
655 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
656 }
657 return allowedColorType;
658}
659
660sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
661 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500662 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400663 const GrMipLevel texels[],
664 int mipLevelCount) const {
665 SkASSERT(!this->isAbandoned());
666 SkASSERT(texture);
667 SkASSERT(colorType != GrColorType::kUnknown);
668 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
669
670 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
671 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
672 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
673 mipLevelCount, &tmpTexels, &tmpDatas);
674 if (tempColorType == GrColorType::kUnknown) {
675 return nullptr;
676 }
677 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
678 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
679 return texture;
680}