blob: 4969e972bd1eded2483372fe552d69ae7731f9e5 [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 Salomon9f2b86c2019-10-22 10:37:46 -0400199 value = SkTMax(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;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400273 GrTexturePriv::ComputeScratchKey(desc.fConfig, {desc.fWidth, desc.fHeight}, renderable,
Brian Salomon14cb4132019-09-16 13:14:47 -0400274 renderTargetSampleCnt, mipMapped, isProtected, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400275 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500276 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400277 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500278 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400279 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500280 }
281 }
282
Brian Osman32342f02017-03-04 08:12:46 -0500283 return nullptr;
284}
285
Greg Daniel7ef28f32017-04-20 16:41:55 +0000286sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400287 GrColorType colorType,
Greg Daniel2268ad22018-11-15 09:27:38 -0500288 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500289 GrWrapCacheable cacheable,
290 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500291 ASSERT_SINGLE_OWNER
292 if (this->isAbandoned()) {
293 return nullptr;
294 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400295 return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400296}
297
Robert Phillipsead321b2019-12-19 10:16:32 -0500298sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
299 GrWrapOwnership ownership,
300 GrWrapCacheable cacheable) {
301 ASSERT_SINGLE_OWNER
302 if (this->isAbandoned()) {
303 return nullptr;
304 }
305
306 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
307}
308
309
Brian Salomond17f6582017-07-19 18:28:58 -0400310sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400311 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400312 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500313 GrWrapOwnership ownership,
314 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400315 ASSERT_SINGLE_OWNER
316 if (this->isAbandoned()) {
317 return nullptr;
318 }
Robert Phillips0902c982019-07-16 07:47:56 -0400319 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500320}
321
322sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400323 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500324{
325 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400326 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500327}
328
Greg Danielb46add82019-01-02 14:51:29 -0500329sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
330 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
331 ASSERT_SINGLE_OWNER
332 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
333 vkInfo);
334
335}
336
Brian Osman32342f02017-03-04 08:12:46 -0500337void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
338 GrGpuResource* resource) {
339 ASSERT_SINGLE_OWNER
340 if (this->isAbandoned() || !resource) {
341 return;
342 }
343 resource->resourcePriv().setUniqueKey(key);
344}
345
Brian Salomond28a79d2017-10-16 13:01:07 -0400346sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500347 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400348 return this->isAbandoned() ? nullptr
349 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500350}
351
Brian Salomondbf70722019-02-07 11:31:24 -0500352sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
353 size_t size,
354 const void* data,
355 const GrUniqueKey& key) {
356 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400357 return buffer;
Chris Dalton5d2de082017-12-19 10:40:23 -0700358 }
Brian Salomondbf70722019-02-07 11:31:24 -0500359 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500360 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500361 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700362 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700363 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500364 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700365 }
366 return nullptr;
367}
368
Brian Salomondbf70722019-02-07 11:31:24 -0500369sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
370 int patternSize,
371 int reps,
372 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500373 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700374 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
375
Brian Salomondbf70722019-02-07 11:31:24 -0500376 sk_sp<GrGpuBuffer> buffer(
377 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700378 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700379 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700380 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400381 uint16_t* data = (uint16_t*) buffer->map();
382 SkAutoTArray<uint16_t> temp;
383 if (!data) {
384 temp.reset(reps * patternSize);
385 data = temp.get();
386 }
bsalomoned0bcad2015-05-04 10:36:42 -0700387 for (int i = 0; i < reps; ++i) {
388 int baseIdx = i * patternSize;
389 uint16_t baseVert = (uint16_t)(i * vertCount);
390 for (int j = 0; j < patternSize; ++j) {
391 data[baseIdx+j] = baseVert + pattern[j];
392 }
393 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400394 if (temp.get()) {
395 if (!buffer->updateData(data, bufferSize)) {
396 return nullptr;
397 }
398 } else {
399 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700400 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500401 if (key) {
402 SkASSERT(key->isValid());
403 this->assignUniqueKeyToResource(*key, buffer.get());
404 }
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400405 return buffer;
bsalomoned0bcad2015-05-04 10:36:42 -0700406}
407
Robert Phillipsee08d522019-10-28 16:34:44 -0400408///////////////////////////////////////////////////////////////////////////////////////////////////
409static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
410static const int kVertsPerNonAAQuad = 4;
411static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400412
Robert Phillipsee08d522019-10-28 16:34:44 -0400413sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500414 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400415
416 static const uint16_t kNonAAQuadIndexPattern[] = {
417 0, 1, 2, 2, 1, 3
418 };
419
Brian Salomon4dea72a2019-12-18 10:43:10 -0500420 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400421
422 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
423 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700424}
425
Robert Phillipsee08d522019-10-28 16:34:44 -0400426int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
427int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
428int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400429
Robert Phillipsee08d522019-10-28 16:34:44 -0400430///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500431static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400432static const int kVertsPerAAQuad = 8;
433static const int kIndicesPerAAQuad = 30;
434
435sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500436 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400437
438 // clang-format off
439 static const uint16_t kAAQuadIndexPattern[] = {
440 0, 1, 2, 1, 3, 2,
441 0, 4, 1, 4, 5, 1,
442 0, 6, 4, 0, 2, 6,
443 2, 3, 6, 3, 7, 6,
444 1, 5, 3, 3, 5, 7,
445 };
446 // clang-format on
447
Brian Salomon4dea72a2019-12-18 10:43:10 -0500448 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400449
450 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
451 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
452}
453
454int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
455int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
456int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
457
458///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400459sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400460 if (this->isAbandoned()) {
461 return nullptr;
462 }
463
bsalomon706f08f2015-05-22 07:35:58 -0700464 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700465 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700466}
467
Brian Salomondbf70722019-02-07 11:31:24 -0500468sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
469 GrAccessPattern accessPattern,
470 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700471 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700472 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700473 }
cdaltond37fe762016-04-21 07:41:50 -0700474 if (kDynamic_GrAccessPattern != accessPattern) {
475 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
476 }
cdaltond37fe762016-04-21 07:41:50 -0700477 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400478 static const size_t MIN_SIZE = 1 << 12;
479 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700480
cdaltond37fe762016-04-21 07:41:50 -0700481 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500482 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
483 auto buffer =
484 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400485 key)));
cdaltond37fe762016-04-21 07:41:50 -0700486 if (!buffer) {
487 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
488 if (!buffer) {
489 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700490 }
491 }
cdaltond37fe762016-04-21 07:41:50 -0700492 if (data) {
493 buffer->updateData(data, size);
494 }
495 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800496}
497
Chris Daltonf00b95b2019-11-07 21:14:41 -0700498bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700499 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600500 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700501 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400502 return true;
egdanielec00d942015-09-14 12:56:10 -0700503 }
504
505 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
506 GrUniqueKey sbKey;
507
508 int width = rt->width();
509 int height = rt->height();
510#if 0
511 if (this->caps()->oversizedStencilSupport()) {
512 width = SkNextPow2(width);
513 height = SkNextPow2(height);
514 }
515#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600516 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700517 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400518 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700519 if (!stencil) {
520 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600521 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700522 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400523 if (!stencil) {
524 return false;
egdanielec00d942015-09-14 12:56:10 -0700525 }
Robert Phillips01a91282018-07-26 08:03:04 -0400526 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700527 }
Greg Danielcfa39352018-10-05 12:01:59 -0400528 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700529 }
Chris Dalton215ff332019-07-02 09:38:22 -0600530
531 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700532 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600533 }
534 return false;
egdanielec00d942015-09-14 12:56:10 -0700535}
536
bungeman6bd52842016-10-27 09:30:08 -0700537sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400538 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700539{
ericrkf7b8b8a2016-02-24 14:49:51 -0800540 if (this->isAbandoned()) {
541 return nullptr;
542 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400543 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800544}
Greg Danield85f97d2017-03-07 13:37:21 -0500545
Greg Daniel301015c2019-11-18 14:06:46 -0500546std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
547 bool isOwned) {
548 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400549}
550
Greg Daniel301015c2019-11-18 14:06:46 -0500551std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
552 const GrBackendSemaphore& semaphore,
553 SemaphoreWrapType wrapType,
554 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400555 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500556 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
557 wrapType,
558 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500559}
Brian Salomon8660eb02019-09-20 13:04:13 -0400560
561// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
562// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
563static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400564 const SkISize& dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400565 bool rowBytesSupport,
566 GrColorType origColorType,
567 GrColorType allowedColorType,
568 GrMipLevel* outLevel,
569 std::unique_ptr<char[]>* data) {
570 if (!inLevel.fPixels) {
571 outLevel->fPixels = nullptr;
572 outLevel->fRowBytes = 0;
573 return true;
574 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400575 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400576 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
577 if (actualRB < minRB) {
578 return false;
579 }
580 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
581 outLevel->fRowBytes = actualRB;
582 outLevel->fPixels = inLevel.fPixels;
583 return true;
584 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400585 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
586 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400587 outLevel->fPixels = data->get();
588 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400589 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
590 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400591 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
592}
593
594GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
595 GrColorType colorType,
596 const SkISize& baseSize,
597 const GrMipLevel texels[],
598 int mipLevelCount,
599 TempLevels* tempLevels,
600 TempLevelDatas* tempLevelDatas) const {
601 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
602
603 auto allowedColorType =
604 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
605 if (allowedColorType == GrColorType::kUnknown) {
606 return GrColorType::kUnknown;
607 }
608 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
609 tempLevels->reset(mipLevelCount);
610 tempLevelDatas->reset(mipLevelCount);
611 auto size = baseSize;
612 for (int i = 0; i < mipLevelCount; ++i) {
613 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
614 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
615 return GrColorType::kUnknown;
616 }
617 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
618 }
619 return allowedColorType;
620}
621
622sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
623 GrColorType colorType,
624 const SkISize& baseSize,
625 const GrMipLevel texels[],
626 int mipLevelCount) const {
627 SkASSERT(!this->isAbandoned());
628 SkASSERT(texture);
629 SkASSERT(colorType != GrColorType::kUnknown);
630 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
631
632 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
633 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
634 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
635 mipLevelCount, &tmpTexels, &tmpDatas);
636 if (tempColorType == GrColorType::kUnknown) {
637 return nullptr;
638 }
639 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
640 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
641 return texture;
642}