blob: 25835a7a96d1226bf3816f589738f7ecdee64f53 [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 Salomonf2c2ba92019-07-17 09:59:59 -040046sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
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;
Greg Daniel9a48beb2020-01-16 16:57:16 -050064 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
Greg Daniel6fa62e22019-08-07 15:52:37 -040065 renderTargetSampleCnt, 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;
70 auto scratch = this->getExactScratch(desc, format, renderable, renderTargetSampleCnt, budgeted,
71 mipMapped, isProtected);
72 if (scratch) {
73 if (!hasPixels) {
74 return scratch;
75 }
76 return this->writePixels(std::move(scratch), colorType, {desc.fWidth, desc.fHeight}, texels,
77 mipLevelCount);
Brian Salomona90382f2019-09-17 09:01:56 -040078 }
Brian Salomon1047a492019-07-02 12:25:21 -040079 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -040080 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon8660eb02019-09-20 13:04:13 -040081 GrColorType tempColorType = GrColorType::kUnknown;
82 if (hasPixels) {
83 tempColorType = this->prepareLevels(format, colorType, {desc.fWidth, desc.fHeight}, texels,
84 mipLevelCount, &tmpTexels, &tmpDatas);
85 if (tempColorType == GrColorType::kUnknown) {
86 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -040087 }
88 }
Brian Salomon4eb38b72019-08-05 12:58:39 -040089 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomon8660eb02019-09-20 13:04:13 -040090 isProtected, colorType, tempColorType, tmpTexels.get(),
91 mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -050092}
93
Robert Phillips45fdae12017-04-17 12:57:27 -040094sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -040095 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040096 GrRenderable renderable,
97 int renderTargetSampleCnt,
98 SkBudgeted budgeted,
Brian Salomon14cb4132019-09-16 13:14:47 -040099 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400100 GrProtected isProtected) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400101 sk_sp<GrTexture> tex(this->refScratchTexture(desc, format, renderable, renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400102 mipMapped, isProtected));
Robert Phillips45fdae12017-04-17 12:57:27 -0400103 if (tex && SkBudgeted::kNo == budgeted) {
104 tex->resourcePriv().makeUnbudgeted();
105 }
106
107 return tex;
108}
109
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500110sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400111 const GrBackendFormat& format,
Brian Salomona90382f2019-09-17 09:01:56 -0400112 GrColorType colorType,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400113 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400114 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500115 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500116 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400117 GrProtected isProtected,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400118 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400119 ASSERT_SINGLE_OWNER
120
Robert Phillips45fdae12017-04-17 12:57:27 -0400121 if (!mipLevel.fPixels) {
122 return nullptr;
123 }
124
Brian Salomona90382f2019-09-17 09:01:56 -0400125 if (SkBackingFit::kApprox == fit) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400126 if (this->isAbandoned()) {
127 return nullptr;
128 }
Greg Daniel9a48beb2020-01-16 16:57:16 -0500129 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
130 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomon8660eb02019-09-20 13:04:13 -0400131 return nullptr;
132 }
133
134 auto tex = this->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
135 isProtected);
Brian Salomona90382f2019-09-17 09:01:56 -0400136 if (!tex) {
137 return nullptr;
138 }
Brian Salomon8660eb02019-09-20 13:04:13 -0400139 return this->writePixels(std::move(tex), colorType, {desc.fWidth, desc.fHeight}, &mipLevel,
140 1);
Brian Salomona90382f2019-09-17 09:01:56 -0400141 } else {
142 return this->createTexture(desc, format, colorType, renderable, renderTargetSampleCnt,
143 budgeted, isProtected, &mipLevel, 1);
Brian Salomona3ffaab2019-07-09 12:26:46 -0400144 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400145}
146
Robert Phillips9f744f72019-12-19 19:14:33 -0500147sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400148 const GrBackendFormat& format,
Robert Phillipse4720c62020-01-14 14:33:24 -0500149 SkBudgeted budgeted,
150 GrMipMapped mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500151 GrProtected isProtected,
Robert Phillipse4720c62020-01-14 14:33:24 -0500152 SkData* data) {
Brian Salomonbb8dde82019-06-27 10:52:13 -0400153 ASSERT_SINGLE_OWNER
154 if (this->isAbandoned()) {
155 return nullptr;
156 }
Robert Phillipse4720c62020-01-14 14:33:24 -0500157 return fGpu->createCompressedTexture(dimensions, format, budgeted, mipMapped,
Robert Phillips3a833922020-01-21 15:25:58 -0500158 isProtected, data->data(), data->size());
Brian Salomonbb8dde82019-06-27 10:52:13 -0400159}
160
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400161sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400162 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400163 GrRenderable renderable,
164 int renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400165 GrMipMapped mipMapped,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400166 SkBudgeted budgeted,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400167 GrProtected isProtected) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400168 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400169 if (this->isAbandoned()) {
170 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500171 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400172
Greg Daniel9a48beb2020-01-16 16:57:16 -0500173 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
Brian Salomona90382f2019-09-17 09:01:56 -0400174 renderTargetSampleCnt, mipMapped)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400175 return nullptr;
176 }
177
Greg Danielc3a927f2019-10-16 12:03:50 -0400178 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
179 // textures should be created through the createCompressedTexture function.
180 SkASSERT(!this->caps()->isFormatCompressed(format));
181
Brian Salomona90382f2019-09-17 09:01:56 -0400182 // TODO: Support GrMipMapped::kYes in scratch texture lookup here.
Greg Danielc3a927f2019-10-16 12:03:50 -0400183 sk_sp<GrTexture> tex = this->getExactScratch(
184 desc, format, renderable, renderTargetSampleCnt, budgeted, mipMapped, isProtected);
185 if (tex) {
186 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400187 }
188
Brian Salomona90382f2019-09-17 09:01:56 -0400189 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, mipMapped, budgeted,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400190 isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500191}
192
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400193// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
194// the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400195SkISize GrResourceProvider::MakeApprox(SkISize dimensions) {
196 auto adjust = [](int value) {
197 static const int kMagicTol = 1024;
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400198
Brian Osman788b9162020-02-07 10:36:46 -0500199 value = std::max(kMinScratchTextureSize, value);
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400200
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400201 if (SkIsPow2(value)) {
202 return value;
203 }
204
205 int ceilPow2 = SkNextPow2(value);
206 if (value <= kMagicTol) {
207 return ceilPow2;
208 }
209
210 int floorPow2 = ceilPow2 >> 1;
211 int mid = floorPow2 + (floorPow2 >> 1);
212
213 if (value <= mid) {
214 return mid;
215 }
Brian Salomon322301a2019-10-24 12:50:50 -0400216 return ceilPow2;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400217 };
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400218
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400219 return {adjust(dimensions.width()), adjust(dimensions.height())};
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400220}
221
Robert Phillips67d52cf2017-06-05 13:38:13 -0400222sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400223 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400224 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400225 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400226 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500227 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500228
Brian Osman32342f02017-03-04 08:12:46 -0500229 if (this->isAbandoned()) {
230 return nullptr;
231 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400232
Greg Danielc3a927f2019-10-16 12:03:50 -0400233 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
234 // textures should be created through the createCompressedTexture function.
235 SkASSERT(!this->caps()->isFormatCompressed(format));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500236
Greg Daniel9a48beb2020-01-16 16:57:16 -0500237 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
Greg Daniel6fa62e22019-08-07 15:52:37 -0400238 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400239 return nullptr;
240 }
241
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400242 // bin by some multiple or power of 2 with a reasonable min
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400243 GrSurfaceDesc copyDesc(desc);
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400244 auto size = MakeApprox({desc.fWidth, desc.fHeight});
245 copyDesc.fWidth = size.width();
246 copyDesc.fHeight = size.height();
Greg Daniel29bf84f2017-09-25 12:25:12 -0400247
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400248 if (auto tex = this->refScratchTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400249 GrMipMapped::kNo, isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400250 return tex;
251 }
252
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400253 return fGpu->createTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400254 GrMipMapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500255}
256
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400257sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400258 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400259 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400260 int renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400261 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400262 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500263 ASSERT_SINGLE_OWNER
264 SkASSERT(!this->isAbandoned());
Greg Danielc3a927f2019-10-16 12:03:50 -0400265 SkASSERT(!this->caps()->isFormatCompressed(format));
Greg Daniel9a48beb2020-01-16 16:57:16 -0500266 SkASSERT(fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
267 renderTargetSampleCnt, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500268
Brian Salomond17b4a62017-05-23 16:53:47 -0400269 // We could make initial clears work with scratch textures but it is a rare case so we just opt
270 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400271 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500272 GrScratchKey key;
Greg Danield51fa2f2020-01-22 16:53:38 -0500273 GrTexturePriv::ComputeScratchKey(*this->caps(), format, {desc.fWidth, desc.fHeight},
274 renderable, renderTargetSampleCnt, mipMapped, isProtected,
275 &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400276 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500277 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400278 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500279 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400280 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500281 }
282 }
283
Brian Osman32342f02017-03-04 08:12:46 -0500284 return nullptr;
285}
286
Greg Daniel7ef28f32017-04-20 16:41:55 +0000287sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400288 GrColorType colorType,
Greg Daniel2268ad22018-11-15 09:27:38 -0500289 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500290 GrWrapCacheable cacheable,
291 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500292 ASSERT_SINGLE_OWNER
293 if (this->isAbandoned()) {
294 return nullptr;
295 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400296 return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400297}
298
Robert Phillipsead321b2019-12-19 10:16:32 -0500299sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
300 GrWrapOwnership ownership,
301 GrWrapCacheable cacheable) {
302 ASSERT_SINGLE_OWNER
303 if (this->isAbandoned()) {
304 return nullptr;
305 }
306
307 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
308}
309
310
Brian Salomond17f6582017-07-19 18:28:58 -0400311sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400312 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400313 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500314 GrWrapOwnership ownership,
315 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400316 ASSERT_SINGLE_OWNER
317 if (this->isAbandoned()) {
318 return nullptr;
319 }
Robert Phillips0902c982019-07-16 07:47:56 -0400320 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500321}
322
323sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400324 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500325{
326 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400327 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500328}
329
Greg Danielb46add82019-01-02 14:51:29 -0500330sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
331 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
332 ASSERT_SINGLE_OWNER
333 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
334 vkInfo);
335
336}
337
Brian Osman32342f02017-03-04 08:12:46 -0500338void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
339 GrGpuResource* resource) {
340 ASSERT_SINGLE_OWNER
341 if (this->isAbandoned() || !resource) {
342 return;
343 }
344 resource->resourcePriv().setUniqueKey(key);
345}
346
Brian Salomond28a79d2017-10-16 13:01:07 -0400347sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500348 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400349 return this->isAbandoned() ? nullptr
350 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500351}
352
Brian Salomondbf70722019-02-07 11:31:24 -0500353sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
354 size_t size,
355 const void* data,
356 const GrUniqueKey& key) {
357 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400358 return buffer;
Chris Dalton5d2de082017-12-19 10:40:23 -0700359 }
Brian Salomondbf70722019-02-07 11:31:24 -0500360 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500361 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500362 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700363 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700364 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500365 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700366 }
367 return nullptr;
368}
369
Brian Salomondbf70722019-02-07 11:31:24 -0500370sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
371 int patternSize,
372 int reps,
373 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500374 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700375 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
376
Brian Salomondbf70722019-02-07 11:31:24 -0500377 sk_sp<GrGpuBuffer> buffer(
378 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700379 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700380 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700381 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400382 uint16_t* data = (uint16_t*) buffer->map();
383 SkAutoTArray<uint16_t> temp;
384 if (!data) {
385 temp.reset(reps * patternSize);
386 data = temp.get();
387 }
bsalomoned0bcad2015-05-04 10:36:42 -0700388 for (int i = 0; i < reps; ++i) {
389 int baseIdx = i * patternSize;
390 uint16_t baseVert = (uint16_t)(i * vertCount);
391 for (int j = 0; j < patternSize; ++j) {
392 data[baseIdx+j] = baseVert + pattern[j];
393 }
394 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400395 if (temp.get()) {
396 if (!buffer->updateData(data, bufferSize)) {
397 return nullptr;
398 }
399 } else {
400 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700401 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500402 if (key) {
403 SkASSERT(key->isValid());
404 this->assignUniqueKeyToResource(*key, buffer.get());
405 }
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400406 return buffer;
bsalomoned0bcad2015-05-04 10:36:42 -0700407}
408
Robert Phillipsee08d522019-10-28 16:34:44 -0400409///////////////////////////////////////////////////////////////////////////////////////////////////
410static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
411static const int kVertsPerNonAAQuad = 4;
412static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400413
Robert Phillipsee08d522019-10-28 16:34:44 -0400414sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500415 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400416
417 static const uint16_t kNonAAQuadIndexPattern[] = {
418 0, 1, 2, 2, 1, 3
419 };
420
Brian Salomon4dea72a2019-12-18 10:43:10 -0500421 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400422
423 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
424 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700425}
426
Robert Phillipsee08d522019-10-28 16:34:44 -0400427int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
428int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
429int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400430
Robert Phillipsee08d522019-10-28 16:34:44 -0400431///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500432static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400433static const int kVertsPerAAQuad = 8;
434static const int kIndicesPerAAQuad = 30;
435
436sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500437 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400438
439 // clang-format off
440 static const uint16_t kAAQuadIndexPattern[] = {
441 0, 1, 2, 1, 3, 2,
442 0, 4, 1, 4, 5, 1,
443 0, 6, 4, 0, 2, 6,
444 2, 3, 6, 3, 7, 6,
445 1, 5, 3, 3, 5, 7,
446 };
447 // clang-format on
448
Brian Salomon4dea72a2019-12-18 10:43:10 -0500449 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400450
451 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
452 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
453}
454
455int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
456int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
457int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
458
459///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400460sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400461 if (this->isAbandoned()) {
462 return nullptr;
463 }
464
bsalomon706f08f2015-05-22 07:35:58 -0700465 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700466 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700467}
468
Brian Salomondbf70722019-02-07 11:31:24 -0500469sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
470 GrAccessPattern accessPattern,
471 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700472 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700473 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700474 }
cdaltond37fe762016-04-21 07:41:50 -0700475 if (kDynamic_GrAccessPattern != accessPattern) {
476 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
477 }
cdaltond37fe762016-04-21 07:41:50 -0700478 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400479 static const size_t MIN_SIZE = 1 << 12;
Brian Osman788b9162020-02-07 10:36:46 -0500480 size_t allocSize = std::max(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700481
cdaltond37fe762016-04-21 07:41:50 -0700482 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500483 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
484 auto buffer =
485 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400486 key)));
cdaltond37fe762016-04-21 07:41:50 -0700487 if (!buffer) {
488 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
489 if (!buffer) {
490 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700491 }
492 }
cdaltond37fe762016-04-21 07:41:50 -0700493 if (data) {
494 buffer->updateData(data, size);
495 }
496 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800497}
498
Chris Daltonf00b95b2019-11-07 21:14:41 -0700499bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700500 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600501 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700502 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400503 return true;
egdanielec00d942015-09-14 12:56:10 -0700504 }
505
506 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
507 GrUniqueKey sbKey;
508
509 int width = rt->width();
510 int height = rt->height();
511#if 0
512 if (this->caps()->oversizedStencilSupport()) {
513 width = SkNextPow2(width);
514 height = SkNextPow2(height);
515 }
516#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600517 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700518 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400519 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700520 if (!stencil) {
521 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600522 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700523 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400524 if (!stencil) {
525 return false;
egdanielec00d942015-09-14 12:56:10 -0700526 }
Robert Phillips01a91282018-07-26 08:03:04 -0400527 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700528 }
Greg Danielcfa39352018-10-05 12:01:59 -0400529 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700530 }
Chris Dalton215ff332019-07-02 09:38:22 -0600531
532 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700533 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600534 }
535 return false;
egdanielec00d942015-09-14 12:56:10 -0700536}
537
bungeman6bd52842016-10-27 09:30:08 -0700538sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400539 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700540{
ericrkf7b8b8a2016-02-24 14:49:51 -0800541 if (this->isAbandoned()) {
542 return nullptr;
543 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400544 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800545}
Greg Danield85f97d2017-03-07 13:37:21 -0500546
Greg Daniel301015c2019-11-18 14:06:46 -0500547std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
548 bool isOwned) {
549 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400550}
551
Greg Daniel301015c2019-11-18 14:06:46 -0500552std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
553 const GrBackendSemaphore& semaphore,
554 SemaphoreWrapType wrapType,
555 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400556 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500557 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
558 wrapType,
559 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500560}
Brian Salomon8660eb02019-09-20 13:04:13 -0400561
562// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
563// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
564static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400565 const SkISize& dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400566 bool rowBytesSupport,
567 GrColorType origColorType,
568 GrColorType allowedColorType,
569 GrMipLevel* outLevel,
570 std::unique_ptr<char[]>* data) {
571 if (!inLevel.fPixels) {
572 outLevel->fPixels = nullptr;
573 outLevel->fRowBytes = 0;
574 return true;
575 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400576 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400577 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
578 if (actualRB < minRB) {
579 return false;
580 }
581 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
582 outLevel->fRowBytes = actualRB;
583 outLevel->fPixels = inLevel.fPixels;
584 return true;
585 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400586 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
587 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400588 outLevel->fPixels = data->get();
589 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400590 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
591 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400592 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
593}
594
595GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
596 GrColorType colorType,
597 const SkISize& baseSize,
598 const GrMipLevel texels[],
599 int mipLevelCount,
600 TempLevels* tempLevels,
601 TempLevelDatas* tempLevelDatas) const {
602 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
603
604 auto allowedColorType =
605 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
606 if (allowedColorType == GrColorType::kUnknown) {
607 return GrColorType::kUnknown;
608 }
609 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
610 tempLevels->reset(mipLevelCount);
611 tempLevelDatas->reset(mipLevelCount);
612 auto size = baseSize;
613 for (int i = 0; i < mipLevelCount; ++i) {
614 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
615 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
616 return GrColorType::kUnknown;
617 }
618 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
619 }
620 return allowedColorType;
621}
622
623sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
624 GrColorType colorType,
625 const SkISize& baseSize,
626 const GrMipLevel texels[],
627 int mipLevelCount) const {
628 SkASSERT(!this->isAbandoned());
629 SkASSERT(texture);
630 SkASSERT(colorType != GrColorType::kUnknown);
631 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
632
633 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
634 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
635 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
636 mipLevelCount, &tmpTexels, &tmpDatas);
637 if (tempColorType == GrColorType::kUnknown) {
638 return nullptr;
639 }
640 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
641 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
642 return texture;
643}