blob: f239f0aeac69182f1eb5d31b512d0c5b277f52fe [file] [log] [blame]
bsalomoned0bcad2015-05-04 10:36:42 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Brian Salomon1047a492019-07-02 12:25:21 -04008#include "src/gpu/GrResourceProvider.h"
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrBackendSemaphore.h"
11#include "include/gpu/GrContext.h"
12#include "include/private/GrResourceKey.h"
13#include "include/private/GrSingleOwner.h"
Brian Salomon1047a492019-07-02 12:25:21 -040014#include "src/core/SkConvertPixels.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/core/SkMathPriv.h"
16#include "src/gpu/GrCaps.h"
17#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrGpu.h"
19#include "src/gpu/GrGpuBuffer.h"
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"
24#include "src/gpu/GrRenderTargetPriv.h"
25#include "src/gpu/GrResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrSemaphore.h"
27#include "src/gpu/GrStencilAttachment.h"
28#include "src/gpu/GrTexturePriv.h"
29#include "src/gpu/SkGr.h"
bsalomoned0bcad2015-05-04 10:36:42 -070030
Brian Salomon9f2b86c2019-10-22 10:37:46 -040031const int GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050032
33#define ASSERT_SINGLE_OWNER \
34 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
35
Robert Phillips12c46292019-04-23 07:36:17 -040036GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050037 : fCache(cache)
38 , fGpu(gpu)
39#ifdef SK_DEBUG
40 , fSingleOwner(owner)
41#endif
Robert Phillips4150eea2018-02-07 17:08:21 -050042{
Robert Phillips26c90e02017-03-14 14:39:29 -040043 fCaps = sk_ref_sp(fGpu->caps());
bsalomoned0bcad2015-05-04 10:36:42 -070044}
45
Brian Salomona56a7462020-02-07 14:17:25 -050046sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040047 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -040048 GrColorType colorType,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040049 GrRenderable renderable,
Brian Salomon2af3e702019-08-11 19:10:31 -040050 int renderTargetSampleCnt,
51 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -040052 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -040053 const GrMipLevel texels[],
54 int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050055 ASSERT_SINGLE_OWNER
56
Robert Phillips7f1b4f82017-11-28 07:38:39 -050057 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040058
Brian Osman32342f02017-03-04 08:12:46 -050059 if (this->isAbandoned()) {
60 return nullptr;
61 }
Robert Phillips1119dc32017-04-11 12:54:57 -040062
Brian Salomonbdecacf2018-02-02 20:32:49 -050063 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
Brian Salomona56a7462020-02-07 14:17:25 -050064 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
65 mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050066 return nullptr;
67 }
Brian Salomon8660eb02019-09-20 13:04:13 -040068 // Current rule is that you can provide no level data, just the base, or all the levels.
69 bool hasPixels = mipLevelCount && texels[0].fPixels;
Brian Salomona56a7462020-02-07 14:17:25 -050070 auto scratch = this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt,
71 budgeted, mipMapped, isProtected);
Brian Salomon8660eb02019-09-20 13:04:13 -040072 if (scratch) {
73 if (!hasPixels) {
74 return scratch;
75 }
Brian Salomona56a7462020-02-07 14:17:25 -050076 return this->writePixels(std::move(scratch), colorType, dimensions, texels, mipLevelCount);
Brian Salomona90382f2019-09-17 09:01:56 -040077 }
Brian Salomon1047a492019-07-02 12:25:21 -040078 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -040079 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon8660eb02019-09-20 13:04:13 -040080 GrColorType tempColorType = GrColorType::kUnknown;
81 if (hasPixels) {
Brian Salomona56a7462020-02-07 14:17:25 -050082 tempColorType = this->prepareLevels(format, colorType, dimensions, texels, mipLevelCount,
83 &tmpTexels, &tmpDatas);
Brian Salomon8660eb02019-09-20 13:04:13 -040084 if (tempColorType == GrColorType::kUnknown) {
85 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -040086 }
87 }
Brian Salomona56a7462020-02-07 14:17:25 -050088 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomon8660eb02019-09-20 13:04:13 -040089 isProtected, colorType, tempColorType, tmpTexels.get(),
90 mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -050091}
92
Brian Salomona56a7462020-02-07 14:17:25 -050093sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -040094 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040095 GrRenderable renderable,
96 int renderTargetSampleCnt,
97 SkBudgeted budgeted,
Brian Salomon14cb4132019-09-16 13:14:47 -040098 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -040099 GrProtected isProtected) {
Brian Salomona56a7462020-02-07 14:17:25 -0500100 sk_sp<GrTexture> tex(this->refScratchTexture(dimensions, format, renderable,
101 renderTargetSampleCnt, mipMapped, isProtected));
Robert Phillips45fdae12017-04-17 12:57:27 -0400102 if (tex && SkBudgeted::kNo == budgeted) {
103 tex->resourcePriv().makeUnbudgeted();
104 }
105
106 return tex;
107}
108
Brian Salomona56a7462020-02-07 14:17:25 -0500109sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400110 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -0400111 GrColorType colorType,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400112 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400113 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500114 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500115 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400116 GrProtected isProtected,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400117 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400118 ASSERT_SINGLE_OWNER
119
Robert Phillips45fdae12017-04-17 12:57:27 -0400120 if (!mipLevel.fPixels) {
121 return nullptr;
122 }
123
Brian Salomona90382f2019-09-17 09:01:56 -0400124 if (SkBackingFit::kApprox == fit) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400125 if (this->isAbandoned()) {
126 return nullptr;
127 }
Brian Salomona56a7462020-02-07 14:17:25 -0500128 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
129 GrMipMapped::kNo)) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400130 return nullptr;
131 }
132
Brian Salomona56a7462020-02-07 14:17:25 -0500133 auto tex = this->createApproxTexture(dimensions, format, renderable, renderTargetSampleCnt,
Brian Salomon8660eb02019-09-20 13:04:13 -0400134 isProtected);
Brian Salomona90382f2019-09-17 09:01:56 -0400135 if (!tex) {
136 return nullptr;
137 }
Brian Salomona56a7462020-02-07 14:17:25 -0500138 return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
Brian Salomona90382f2019-09-17 09:01:56 -0400139 } else {
Brian Salomona56a7462020-02-07 14:17:25 -0500140 return this->createTexture(dimensions, format, colorType, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400141 budgeted, isProtected, &mipLevel, 1);
Brian Salomona3ffaab2019-07-09 12:26:46 -0400142 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400143}
144
Robert Phillips9f744f72019-12-19 19:14:33 -0500145sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400146 const GrBackendFormat& format,
Robert Phillipse4720c62020-01-14 14:33:24 -0500147 SkBudgeted budgeted,
148 GrMipMapped mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500149 GrProtected isProtected,
Robert Phillipse4720c62020-01-14 14:33:24 -0500150 SkData* data) {
Brian Salomonbb8dde82019-06-27 10:52:13 -0400151 ASSERT_SINGLE_OWNER
152 if (this->isAbandoned()) {
153 return nullptr;
154 }
Robert Phillipse4720c62020-01-14 14:33:24 -0500155 return fGpu->createCompressedTexture(dimensions, format, budgeted, mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500156 isProtected, data->data(), data->size());
Brian Salomonbb8dde82019-06-27 10:52:13 -0400157}
158
Brian Salomona56a7462020-02-07 14:17:25 -0500159sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400160 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400161 GrRenderable renderable,
162 int renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400163 GrMipMapped mipMapped,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400164 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400165 GrProtected isProtected) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400166 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400167 if (this->isAbandoned()) {
168 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500169 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400170
Brian Salomona56a7462020-02-07 14:17:25 -0500171 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
172 mipMapped)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400173 return nullptr;
174 }
175
Greg Danielc3a927f2019-10-16 12:03:50 -0400176 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
177 // textures should be created through the createCompressedTexture function.
178 SkASSERT(!this->caps()->isFormatCompressed(format));
179
Brian Salomona90382f2019-09-17 09:01:56 -0400180 // TODO: Support GrMipMapped::kYes in scratch texture lookup here.
Brian Salomona56a7462020-02-07 14:17:25 -0500181 sk_sp<GrTexture> tex =
182 this->getExactScratch(dimensions, format, renderable, renderTargetSampleCnt, budgeted,
183 mipMapped, isProtected);
Greg Danielc3a927f2019-10-16 12:03:50 -0400184 if (tex) {
185 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400186 }
187
Brian Salomona56a7462020-02-07 14:17:25 -0500188 return fGpu->createTexture(dimensions, format, renderable, renderTargetSampleCnt, mipMapped,
189 budgeted, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500190}
191
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400192// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
193// 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 -0400194SkISize GrResourceProvider::MakeApprox(SkISize dimensions) {
195 auto adjust = [](int value) {
196 static const int kMagicTol = 1024;
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400197
Brian Osman788b9162020-02-07 10:36:46 -0500198 value = std::max(kMinScratchTextureSize, value);
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400199
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400200 if (SkIsPow2(value)) {
201 return value;
202 }
203
204 int ceilPow2 = SkNextPow2(value);
205 if (value <= kMagicTol) {
206 return ceilPow2;
207 }
208
209 int floorPow2 = ceilPow2 >> 1;
210 int mid = floorPow2 + (floorPow2 >> 1);
211
212 if (value <= mid) {
213 return mid;
214 }
Brian Salomon322301a2019-10-24 12:50:50 -0400215 return ceilPow2;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400216 };
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400217
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400218 return {adjust(dimensions.width()), adjust(dimensions.height())};
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400219}
220
Brian Salomona56a7462020-02-07 14:17:25 -0500221sk_sp<GrTexture> GrResourceProvider::createApproxTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400222 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400223 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400224 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400225 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500226 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500227
Brian Osman32342f02017-03-04 08:12:46 -0500228 if (this->isAbandoned()) {
229 return nullptr;
230 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400231
Greg Danielc3a927f2019-10-16 12:03:50 -0400232 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
233 // textures should be created through the createCompressedTexture function.
234 SkASSERT(!this->caps()->isFormatCompressed(format));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500235
Brian Salomona56a7462020-02-07 14:17:25 -0500236 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
237 GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400238 return nullptr;
239 }
240
Brian Salomona56a7462020-02-07 14:17:25 -0500241 auto copyDimensions = MakeApprox(dimensions);
Greg Daniel29bf84f2017-09-25 12:25:12 -0400242
Brian Salomona56a7462020-02-07 14:17:25 -0500243 if (auto tex = this->refScratchTexture(copyDimensions, format, renderable,
244 renderTargetSampleCnt, GrMipMapped::kNo, isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400245 return tex;
246 }
247
Brian Salomona56a7462020-02-07 14:17:25 -0500248 return fGpu->createTexture(copyDimensions, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400249 GrMipMapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500250}
251
Brian Salomona56a7462020-02-07 14:17:25 -0500252sk_sp<GrTexture> GrResourceProvider::refScratchTexture(SkISize dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400253 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400254 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400255 int renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400256 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400257 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500258 ASSERT_SINGLE_OWNER
259 SkASSERT(!this->isAbandoned());
Greg Danielc3a927f2019-10-16 12:03:50 -0400260 SkASSERT(!this->caps()->isFormatCompressed(format));
Brian Salomona56a7462020-02-07 14:17:25 -0500261 SkASSERT(fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
262 GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500263
Brian Salomond17b4a62017-05-23 16:53:47 -0400264 // We could make initial clears work with scratch textures but it is a rare case so we just opt
265 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400266 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500267 GrScratchKey key;
Brian Salomona56a7462020-02-07 14:17:25 -0500268 GrTexturePriv::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
269 renderTargetSampleCnt, mipMapped, isProtected, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400270 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500271 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400272 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500273 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400274 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500275 }
276 }
277
Brian Osman32342f02017-03-04 08:12:46 -0500278 return nullptr;
279}
280
Greg Daniel7ef28f32017-04-20 16:41:55 +0000281sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400282 GrColorType colorType,
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 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400290 return fGpu->wrapBackendTexture(tex, colorType, 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,
Robert Phillips0902c982019-07-16 07:47:56 -0400307 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500308 GrWrapOwnership ownership,
309 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400310 ASSERT_SINGLE_OWNER
311 if (this->isAbandoned()) {
312 return nullptr;
313 }
Robert Phillips0902c982019-07-16 07:47:56 -0400314 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500315}
316
317sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400318 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500319{
320 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400321 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500322}
323
Greg Danielb46add82019-01-02 14:51:29 -0500324sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
325 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
326 ASSERT_SINGLE_OWNER
327 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
328 vkInfo);
329
330}
331
Brian Osman32342f02017-03-04 08:12:46 -0500332void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
333 GrGpuResource* resource) {
334 ASSERT_SINGLE_OWNER
335 if (this->isAbandoned() || !resource) {
336 return;
337 }
338 resource->resourcePriv().setUniqueKey(key);
339}
340
Brian Salomond28a79d2017-10-16 13:01:07 -0400341sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500342 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400343 return this->isAbandoned() ? nullptr
344 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500345}
346
Brian Salomondbf70722019-02-07 11:31:24 -0500347sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
348 size_t size,
349 const void* data,
350 const GrUniqueKey& key) {
351 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Mike Kleina9609ea2020-02-18 13:33:23 -0600352 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700353 }
Brian Salomondbf70722019-02-07 11:31:24 -0500354 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500355 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500356 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700357 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700358 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500359 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700360 }
361 return nullptr;
362}
363
Brian Salomondbf70722019-02-07 11:31:24 -0500364sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
365 int patternSize,
366 int reps,
367 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500368 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700369 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
370
Brian Salomondbf70722019-02-07 11:31:24 -0500371 sk_sp<GrGpuBuffer> buffer(
372 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700373 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700374 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700375 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400376 uint16_t* data = (uint16_t*) buffer->map();
377 SkAutoTArray<uint16_t> temp;
378 if (!data) {
379 temp.reset(reps * patternSize);
380 data = temp.get();
381 }
bsalomoned0bcad2015-05-04 10:36:42 -0700382 for (int i = 0; i < reps; ++i) {
383 int baseIdx = i * patternSize;
384 uint16_t baseVert = (uint16_t)(i * vertCount);
385 for (int j = 0; j < patternSize; ++j) {
386 data[baseIdx+j] = baseVert + pattern[j];
387 }
388 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400389 if (temp.get()) {
390 if (!buffer->updateData(data, bufferSize)) {
391 return nullptr;
392 }
393 } else {
394 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700395 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500396 if (key) {
397 SkASSERT(key->isValid());
398 this->assignUniqueKeyToResource(*key, buffer.get());
399 }
Mike Kleina9609ea2020-02-18 13:33:23 -0600400 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700401}
402
Robert Phillipsee08d522019-10-28 16:34:44 -0400403///////////////////////////////////////////////////////////////////////////////////////////////////
404static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
405static const int kVertsPerNonAAQuad = 4;
406static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400407
Robert Phillipsee08d522019-10-28 16:34:44 -0400408sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500409 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400410
411 static const uint16_t kNonAAQuadIndexPattern[] = {
412 0, 1, 2, 2, 1, 3
413 };
414
Brian Salomon4dea72a2019-12-18 10:43:10 -0500415 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400416
417 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
418 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700419}
420
Robert Phillipsee08d522019-10-28 16:34:44 -0400421int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
422int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
423int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400424
Robert Phillipsee08d522019-10-28 16:34:44 -0400425///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500426static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400427static const int kVertsPerAAQuad = 8;
428static const int kIndicesPerAAQuad = 30;
429
430sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500431 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400432
433 // clang-format off
434 static const uint16_t kAAQuadIndexPattern[] = {
435 0, 1, 2, 1, 3, 2,
436 0, 4, 1, 4, 5, 1,
437 0, 6, 4, 0, 2, 6,
438 2, 3, 6, 3, 7, 6,
439 1, 5, 3, 3, 5, 7,
440 };
441 // clang-format on
442
Brian Salomon4dea72a2019-12-18 10:43:10 -0500443 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400444
445 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
446 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
447}
448
449int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
450int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
451int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
452
453///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400454sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400455 if (this->isAbandoned()) {
456 return nullptr;
457 }
458
bsalomon706f08f2015-05-22 07:35:58 -0700459 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700460 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700461}
462
Brian Salomondbf70722019-02-07 11:31:24 -0500463sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
464 GrAccessPattern accessPattern,
465 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700466 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700467 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700468 }
cdaltond37fe762016-04-21 07:41:50 -0700469 if (kDynamic_GrAccessPattern != accessPattern) {
470 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
471 }
cdaltond37fe762016-04-21 07:41:50 -0700472 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400473 static const size_t MIN_SIZE = 1 << 12;
Brian Osman788b9162020-02-07 10:36:46 -0500474 size_t allocSize = std::max(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700475
cdaltond37fe762016-04-21 07:41:50 -0700476 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500477 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
478 auto buffer =
479 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400480 key)));
cdaltond37fe762016-04-21 07:41:50 -0700481 if (!buffer) {
482 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
483 if (!buffer) {
484 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700485 }
486 }
cdaltond37fe762016-04-21 07:41:50 -0700487 if (data) {
488 buffer->updateData(data, size);
489 }
490 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800491}
492
Chris Daltonf00b95b2019-11-07 21:14:41 -0700493bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700494 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600495 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700496 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400497 return true;
egdanielec00d942015-09-14 12:56:10 -0700498 }
499
500 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
501 GrUniqueKey sbKey;
502
503 int width = rt->width();
504 int height = rt->height();
505#if 0
506 if (this->caps()->oversizedStencilSupport()) {
507 width = SkNextPow2(width);
508 height = SkNextPow2(height);
509 }
510#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600511 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700512 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400513 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700514 if (!stencil) {
515 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600516 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700517 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400518 if (!stencil) {
519 return false;
egdanielec00d942015-09-14 12:56:10 -0700520 }
Robert Phillips01a91282018-07-26 08:03:04 -0400521 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700522 }
Greg Danielcfa39352018-10-05 12:01:59 -0400523 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700524 }
Chris Dalton215ff332019-07-02 09:38:22 -0600525
526 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700527 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600528 }
529 return false;
egdanielec00d942015-09-14 12:56:10 -0700530}
531
bungeman6bd52842016-10-27 09:30:08 -0700532sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400533 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700534{
ericrkf7b8b8a2016-02-24 14:49:51 -0800535 if (this->isAbandoned()) {
536 return nullptr;
537 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400538 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800539}
Greg Danield85f97d2017-03-07 13:37:21 -0500540
Greg Daniel301015c2019-11-18 14:06:46 -0500541std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
542 bool isOwned) {
543 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400544}
545
Greg Daniel301015c2019-11-18 14:06:46 -0500546std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
547 const GrBackendSemaphore& semaphore,
548 SemaphoreWrapType wrapType,
549 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400550 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500551 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
552 wrapType,
553 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500554}
Brian Salomon8660eb02019-09-20 13:04:13 -0400555
556// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
557// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
558static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomona56a7462020-02-07 14:17:25 -0500559 SkISize dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400560 bool rowBytesSupport,
561 GrColorType origColorType,
562 GrColorType allowedColorType,
563 GrMipLevel* outLevel,
564 std::unique_ptr<char[]>* data) {
565 if (!inLevel.fPixels) {
566 outLevel->fPixels = nullptr;
567 outLevel->fRowBytes = 0;
568 return true;
569 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400570 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400571 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
572 if (actualRB < minRB) {
573 return false;
574 }
575 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
576 outLevel->fRowBytes = actualRB;
577 outLevel->fPixels = inLevel.fPixels;
578 return true;
579 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400580 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
581 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400582 outLevel->fPixels = data->get();
583 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400584 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
585 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400586 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
587}
588
589GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
590 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500591 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400592 const GrMipLevel texels[],
593 int mipLevelCount,
594 TempLevels* tempLevels,
595 TempLevelDatas* tempLevelDatas) const {
596 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
597
598 auto allowedColorType =
599 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
600 if (allowedColorType == GrColorType::kUnknown) {
601 return GrColorType::kUnknown;
602 }
603 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
604 tempLevels->reset(mipLevelCount);
605 tempLevelDatas->reset(mipLevelCount);
606 auto size = baseSize;
607 for (int i = 0; i < mipLevelCount; ++i) {
608 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
609 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
610 return GrColorType::kUnknown;
611 }
612 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
613 }
614 return allowedColorType;
615}
616
617sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
618 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500619 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400620 const GrMipLevel texels[],
621 int mipLevelCount) const {
622 SkASSERT(!this->isAbandoned());
623 SkASSERT(texture);
624 SkASSERT(colorType != GrColorType::kUnknown);
625 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
626
627 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
628 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
629 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
630 mipLevelCount, &tmpTexels, &tmpDatas);
631 if (tempColorType == GrColorType::kUnknown) {
632 return nullptr;
633 }
634 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
635 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
636 return texture;
637}