blob: 498c171694777dde6347c2fcbc5f9c11aee2d99e [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,
Greg Daniel2268ad22018-11-15 09:27:38 -0500282 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500283 GrWrapCacheable cacheable,
284 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500285 ASSERT_SINGLE_OWNER
286 if (this->isAbandoned()) {
287 return nullptr;
288 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400289 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400290}
291
Robert Phillipsead321b2019-12-19 10:16:32 -0500292sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
293 GrWrapOwnership ownership,
294 GrWrapCacheable cacheable) {
295 ASSERT_SINGLE_OWNER
296 if (this->isAbandoned()) {
297 return nullptr;
298 }
299
300 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
301}
302
303
Brian Salomond17f6582017-07-19 18:28:58 -0400304sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400305 int sampleCnt,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500306 GrWrapOwnership ownership,
307 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400308 ASSERT_SINGLE_OWNER
309 if (this->isAbandoned()) {
310 return nullptr;
311 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400312 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500313}
314
315sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400316 const GrBackendRenderTarget& backendRT) {
Brian Osman32342f02017-03-04 08:12:46 -0500317 ASSERT_SINGLE_OWNER
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400318 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500319}
320
Greg Danielb46add82019-01-02 14:51:29 -0500321sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
322 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
323 ASSERT_SINGLE_OWNER
324 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
325 vkInfo);
326
327}
328
Brian Osman32342f02017-03-04 08:12:46 -0500329void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
330 GrGpuResource* resource) {
331 ASSERT_SINGLE_OWNER
332 if (this->isAbandoned() || !resource) {
333 return;
334 }
335 resource->resourcePriv().setUniqueKey(key);
336}
337
Brian Salomond28a79d2017-10-16 13:01:07 -0400338sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500339 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400340 return this->isAbandoned() ? nullptr
341 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500342}
343
Brian Salomondbf70722019-02-07 11:31:24 -0500344sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
345 size_t size,
346 const void* data,
347 const GrUniqueKey& key) {
348 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Mike Kleina9609ea2020-02-18 13:33:23 -0600349 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700350 }
Brian Salomondbf70722019-02-07 11:31:24 -0500351 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500352 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500353 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700354 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700355 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500356 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700357 }
358 return nullptr;
359}
360
Brian Salomondbf70722019-02-07 11:31:24 -0500361sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
362 int patternSize,
363 int reps,
364 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500365 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700366 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
367
Brian Salomondbf70722019-02-07 11:31:24 -0500368 sk_sp<GrGpuBuffer> buffer(
369 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700370 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700371 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700372 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400373 uint16_t* data = (uint16_t*) buffer->map();
374 SkAutoTArray<uint16_t> temp;
375 if (!data) {
376 temp.reset(reps * patternSize);
377 data = temp.get();
378 }
bsalomoned0bcad2015-05-04 10:36:42 -0700379 for (int i = 0; i < reps; ++i) {
380 int baseIdx = i * patternSize;
381 uint16_t baseVert = (uint16_t)(i * vertCount);
382 for (int j = 0; j < patternSize; ++j) {
383 data[baseIdx+j] = baseVert + pattern[j];
384 }
385 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400386 if (temp.get()) {
387 if (!buffer->updateData(data, bufferSize)) {
388 return nullptr;
389 }
390 } else {
391 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700392 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500393 if (key) {
394 SkASSERT(key->isValid());
395 this->assignUniqueKeyToResource(*key, buffer.get());
396 }
Mike Kleina9609ea2020-02-18 13:33:23 -0600397 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700398}
399
Robert Phillipsee08d522019-10-28 16:34:44 -0400400///////////////////////////////////////////////////////////////////////////////////////////////////
401static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
402static const int kVertsPerNonAAQuad = 4;
403static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400404
Robert Phillipsee08d522019-10-28 16:34:44 -0400405sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500406 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400407
408 static const uint16_t kNonAAQuadIndexPattern[] = {
409 0, 1, 2, 2, 1, 3
410 };
411
Brian Salomon4dea72a2019-12-18 10:43:10 -0500412 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400413
414 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
415 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700416}
417
Robert Phillipsee08d522019-10-28 16:34:44 -0400418int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
419int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
420int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400421
Robert Phillipsee08d522019-10-28 16:34:44 -0400422///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500423static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400424static const int kVertsPerAAQuad = 8;
425static const int kIndicesPerAAQuad = 30;
426
427sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500428 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400429
430 // clang-format off
431 static const uint16_t kAAQuadIndexPattern[] = {
432 0, 1, 2, 1, 3, 2,
433 0, 4, 1, 4, 5, 1,
434 0, 6, 4, 0, 2, 6,
435 2, 3, 6, 3, 7, 6,
436 1, 5, 3, 3, 5, 7,
437 };
438 // clang-format on
439
Brian Salomon4dea72a2019-12-18 10:43:10 -0500440 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400441
442 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
443 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
444}
445
446int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
447int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
448int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
449
450///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400451sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400452 if (this->isAbandoned()) {
453 return nullptr;
454 }
455
bsalomon706f08f2015-05-22 07:35:58 -0700456 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700457 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700458}
459
Brian Salomondbf70722019-02-07 11:31:24 -0500460sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
461 GrAccessPattern accessPattern,
462 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700463 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700464 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700465 }
cdaltond37fe762016-04-21 07:41:50 -0700466 if (kDynamic_GrAccessPattern != accessPattern) {
467 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
468 }
cdaltond37fe762016-04-21 07:41:50 -0700469 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400470 static const size_t MIN_SIZE = 1 << 12;
Brian Osman788b9162020-02-07 10:36:46 -0500471 size_t allocSize = std::max(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700472
cdaltond37fe762016-04-21 07:41:50 -0700473 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500474 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
475 auto buffer =
476 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400477 key)));
cdaltond37fe762016-04-21 07:41:50 -0700478 if (!buffer) {
479 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
480 if (!buffer) {
481 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700482 }
483 }
cdaltond37fe762016-04-21 07:41:50 -0700484 if (data) {
485 buffer->updateData(data, size);
486 }
487 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800488}
489
Chris Daltonf00b95b2019-11-07 21:14:41 -0700490bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700491 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600492 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700493 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400494 return true;
egdanielec00d942015-09-14 12:56:10 -0700495 }
496
497 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
498 GrUniqueKey sbKey;
499
500 int width = rt->width();
501 int height = rt->height();
502#if 0
503 if (this->caps()->oversizedStencilSupport()) {
504 width = SkNextPow2(width);
505 height = SkNextPow2(height);
506 }
507#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600508 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700509 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400510 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700511 if (!stencil) {
512 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600513 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700514 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400515 if (!stencil) {
516 return false;
egdanielec00d942015-09-14 12:56:10 -0700517 }
Robert Phillips01a91282018-07-26 08:03:04 -0400518 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700519 }
Greg Danielcfa39352018-10-05 12:01:59 -0400520 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700521 }
Chris Dalton215ff332019-07-02 09:38:22 -0600522
523 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700524 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600525 }
526 return false;
egdanielec00d942015-09-14 12:56:10 -0700527}
528
bungeman6bd52842016-10-27 09:30:08 -0700529sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400530 const GrBackendTexture& tex, int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800531 if (this->isAbandoned()) {
532 return nullptr;
533 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400534 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800535}
Greg Danield85f97d2017-03-07 13:37:21 -0500536
Greg Daniel301015c2019-11-18 14:06:46 -0500537std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
538 bool isOwned) {
539 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400540}
541
Greg Daniel301015c2019-11-18 14:06:46 -0500542std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
543 const GrBackendSemaphore& semaphore,
544 SemaphoreWrapType wrapType,
545 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400546 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500547 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
548 wrapType,
549 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500550}
Brian Salomon8660eb02019-09-20 13:04:13 -0400551
552// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
553// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
554static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomona56a7462020-02-07 14:17:25 -0500555 SkISize dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400556 bool rowBytesSupport,
557 GrColorType origColorType,
558 GrColorType allowedColorType,
559 GrMipLevel* outLevel,
560 std::unique_ptr<char[]>* data) {
561 if (!inLevel.fPixels) {
562 outLevel->fPixels = nullptr;
563 outLevel->fRowBytes = 0;
564 return true;
565 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400566 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400567 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
568 if (actualRB < minRB) {
569 return false;
570 }
571 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
572 outLevel->fRowBytes = actualRB;
573 outLevel->fPixels = inLevel.fPixels;
574 return true;
575 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400576 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
577 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400578 outLevel->fPixels = data->get();
579 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400580 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
581 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400582 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
583}
584
585GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
586 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500587 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400588 const GrMipLevel texels[],
589 int mipLevelCount,
590 TempLevels* tempLevels,
591 TempLevelDatas* tempLevelDatas) const {
592 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
593
594 auto allowedColorType =
595 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
596 if (allowedColorType == GrColorType::kUnknown) {
597 return GrColorType::kUnknown;
598 }
599 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
600 tempLevels->reset(mipLevelCount);
601 tempLevelDatas->reset(mipLevelCount);
602 auto size = baseSize;
603 for (int i = 0; i < mipLevelCount; ++i) {
604 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
605 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
606 return GrColorType::kUnknown;
607 }
608 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
609 }
610 return allowedColorType;
611}
612
613sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
614 GrColorType colorType,
Brian Salomona56a7462020-02-07 14:17:25 -0500615 SkISize baseSize,
Brian Salomon8660eb02019-09-20 13:04:13 -0400616 const GrMipLevel texels[],
617 int mipLevelCount) const {
618 SkASSERT(!this->isAbandoned());
619 SkASSERT(texture);
620 SkASSERT(colorType != GrColorType::kUnknown);
621 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
622
623 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
624 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
625 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
626 mipLevelCount, &tmpTexels, &tmpDatas);
627 if (tempColorType == GrColorType::kUnknown) {
628 return nullptr;
629 }
630 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
631 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
632 return texture;
633}