blob: 93ccc62048bf6c025da440b98ab10e62c9228955 [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 Daniel6fa62e22019-08-07 15:52:37 -040064 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
65 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 }
129 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig,
130 renderable, renderTargetSampleCnt, GrMipMapped::kNo)) {
131 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
Brian Salomonbb8dde82019-06-27 10:52:13 -0400147sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400148 const GrBackendFormat& format,
Brian Salomonbb8dde82019-06-27 10:52:13 -0400149 SkImage::CompressionType compression,
150 SkBudgeted budgeted, SkData* data) {
151 ASSERT_SINGLE_OWNER
152 if (this->isAbandoned()) {
153 return nullptr;
154 }
Greg Daniel7bfc9132019-08-14 14:23:53 -0400155 return fGpu->createCompressedTexture(width, height, format, compression, budgeted, data->data(),
Brian Salomonbb8dde82019-06-27 10:52:13 -0400156 data->size());
157}
158
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400159sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
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
Greg Daniel6fa62e22019-08-07 15:52:37 -0400171 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
Brian Salomona90382f2019-09-17 09:01:56 -0400172 renderTargetSampleCnt, 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.
Greg Danielc3a927f2019-10-16 12:03:50 -0400181 sk_sp<GrTexture> tex = this->getExactScratch(
182 desc, format, renderable, renderTargetSampleCnt, budgeted, mipMapped, isProtected);
183 if (tex) {
184 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400185 }
186
Brian Salomona90382f2019-09-17 09:01:56 -0400187 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, mipMapped, budgeted,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400188 isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500189}
190
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400191// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
192// 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 -0400193SkISize GrResourceProvider::MakeApprox(SkISize dimensions) {
194 auto adjust = [](int value) {
195 static const int kMagicTol = 1024;
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400196
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400197 value = SkTMax(kMinScratchTextureSize, value);
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400198
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400199 if (SkIsPow2(value)) {
200 return value;
201 }
202
203 int ceilPow2 = SkNextPow2(value);
204 if (value <= kMagicTol) {
205 return ceilPow2;
206 }
207
208 int floorPow2 = ceilPow2 >> 1;
209 int mid = floorPow2 + (floorPow2 >> 1);
210
211 if (value <= mid) {
212 return mid;
213 }
Brian Salomon322301a2019-10-24 12:50:50 -0400214 return ceilPow2;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400215 };
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400216
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400217 return {adjust(dimensions.width()), adjust(dimensions.height())};
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400218}
219
Robert Phillips67d52cf2017-06-05 13:38:13 -0400220sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400221 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400222 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400223 int renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400224 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500225 ASSERT_SINGLE_OWNER
Brian Osman32342f02017-03-04 08:12:46 -0500226
Brian Osman32342f02017-03-04 08:12:46 -0500227 if (this->isAbandoned()) {
228 return nullptr;
229 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400230
Greg Danielc3a927f2019-10-16 12:03:50 -0400231 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
232 // textures should be created through the createCompressedTexture function.
233 SkASSERT(!this->caps()->isFormatCompressed(format));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500234
Greg Daniel6fa62e22019-08-07 15:52:37 -0400235 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
236 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400237 return nullptr;
238 }
239
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400240 // bin by some multiple or power of 2 with a reasonable min
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400241 GrSurfaceDesc copyDesc(desc);
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400242 auto size = MakeApprox({desc.fWidth, desc.fHeight});
243 copyDesc.fWidth = size.width();
244 copyDesc.fHeight = size.height();
Greg Daniel29bf84f2017-09-25 12:25:12 -0400245
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400246 if (auto tex = this->refScratchTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400247 GrMipMapped::kNo, isProtected)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400248 return tex;
249 }
250
Michael Ludwigbd2f0702019-09-13 15:29:41 -0400251 return fGpu->createTexture(copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400252 GrMipMapped::kNo, SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500253}
254
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400255sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400256 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400257 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400258 int renderTargetSampleCnt,
Brian Salomon14cb4132019-09-16 13:14:47 -0400259 GrMipMapped mipMapped,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400260 GrProtected isProtected) {
Brian Osman32342f02017-03-04 08:12:46 -0500261 ASSERT_SINGLE_OWNER
262 SkASSERT(!this->isAbandoned());
Greg Danielc3a927f2019-10-16 12:03:50 -0400263 SkASSERT(!this->caps()->isFormatCompressed(format));
Greg Daniel6fa62e22019-08-07 15:52:37 -0400264 SkASSERT(fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig,
265 renderable, renderTargetSampleCnt, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500266
Brian Salomond17b4a62017-05-23 16:53:47 -0400267 // We could make initial clears work with scratch textures but it is a rare case so we just opt
268 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400269 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500270 GrScratchKey key;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400271 GrTexturePriv::ComputeScratchKey(desc.fConfig, {desc.fWidth, desc.fHeight}, renderable,
Brian Salomon14cb4132019-09-16 13:14:47 -0400272 renderTargetSampleCnt, mipMapped, isProtected, &key);
Robert Phillipsaee18c92019-09-06 11:48:27 -0400273 GrGpuResource* resource = fCache->findAndRefScratchResource(key);
Brian Osman32342f02017-03-04 08:12:46 -0500274 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400275 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500276 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400277 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500278 }
279 }
280
Brian Osman32342f02017-03-04 08:12:46 -0500281 return nullptr;
282}
283
Greg Daniel7ef28f32017-04-20 16:41:55 +0000284sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400285 GrColorType colorType,
Greg Daniel2268ad22018-11-15 09:27:38 -0500286 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500287 GrWrapCacheable cacheable,
288 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500289 ASSERT_SINGLE_OWNER
290 if (this->isAbandoned()) {
291 return nullptr;
292 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400293 return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400294}
295
Robert Phillipsead321b2019-12-19 10:16:32 -0500296sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
297 GrWrapOwnership ownership,
298 GrWrapCacheable cacheable) {
299 ASSERT_SINGLE_OWNER
300 if (this->isAbandoned()) {
301 return nullptr;
302 }
303
304 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
305}
306
307
Brian Salomond17f6582017-07-19 18:28:58 -0400308sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400309 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400310 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500311 GrWrapOwnership ownership,
312 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400313 ASSERT_SINGLE_OWNER
314 if (this->isAbandoned()) {
315 return nullptr;
316 }
Robert Phillips0902c982019-07-16 07:47:56 -0400317 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500318}
319
320sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400321 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500322{
323 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400324 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500325}
326
Greg Danielb46add82019-01-02 14:51:29 -0500327sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
328 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
329 ASSERT_SINGLE_OWNER
330 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
331 vkInfo);
332
333}
334
Brian Osman32342f02017-03-04 08:12:46 -0500335void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
336 GrGpuResource* resource) {
337 ASSERT_SINGLE_OWNER
338 if (this->isAbandoned() || !resource) {
339 return;
340 }
341 resource->resourcePriv().setUniqueKey(key);
342}
343
Brian Salomond28a79d2017-10-16 13:01:07 -0400344sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500345 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400346 return this->isAbandoned() ? nullptr
347 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500348}
349
Brian Salomondbf70722019-02-07 11:31:24 -0500350sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
351 size_t size,
352 const void* data,
353 const GrUniqueKey& key) {
354 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400355 return buffer;
Chris Dalton5d2de082017-12-19 10:40:23 -0700356 }
Brian Salomondbf70722019-02-07 11:31:24 -0500357 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500358 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500359 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700360 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700361 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500362 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700363 }
364 return nullptr;
365}
366
Brian Salomondbf70722019-02-07 11:31:24 -0500367sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
368 int patternSize,
369 int reps,
370 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500371 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700372 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
373
Brian Salomondbf70722019-02-07 11:31:24 -0500374 sk_sp<GrGpuBuffer> buffer(
375 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700376 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700377 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700378 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400379 uint16_t* data = (uint16_t*) buffer->map();
380 SkAutoTArray<uint16_t> temp;
381 if (!data) {
382 temp.reset(reps * patternSize);
383 data = temp.get();
384 }
bsalomoned0bcad2015-05-04 10:36:42 -0700385 for (int i = 0; i < reps; ++i) {
386 int baseIdx = i * patternSize;
387 uint16_t baseVert = (uint16_t)(i * vertCount);
388 for (int j = 0; j < patternSize; ++j) {
389 data[baseIdx+j] = baseVert + pattern[j];
390 }
391 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400392 if (temp.get()) {
393 if (!buffer->updateData(data, bufferSize)) {
394 return nullptr;
395 }
396 } else {
397 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700398 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500399 if (key) {
400 SkASSERT(key->isValid());
401 this->assignUniqueKeyToResource(*key, buffer.get());
402 }
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400403 return buffer;
bsalomoned0bcad2015-05-04 10:36:42 -0700404}
405
Robert Phillipsee08d522019-10-28 16:34:44 -0400406///////////////////////////////////////////////////////////////////////////////////////////////////
407static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
408static const int kVertsPerNonAAQuad = 4;
409static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400410
Robert Phillipsee08d522019-10-28 16:34:44 -0400411sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500412 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400413
414 static const uint16_t kNonAAQuadIndexPattern[] = {
415 0, 1, 2, 2, 1, 3
416 };
417
Brian Salomon4dea72a2019-12-18 10:43:10 -0500418 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400419
420 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
421 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700422}
423
Robert Phillipsee08d522019-10-28 16:34:44 -0400424int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
425int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
426int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400427
Robert Phillipsee08d522019-10-28 16:34:44 -0400428///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500429static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400430static const int kVertsPerAAQuad = 8;
431static const int kIndicesPerAAQuad = 30;
432
433sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500434 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400435
436 // clang-format off
437 static const uint16_t kAAQuadIndexPattern[] = {
438 0, 1, 2, 1, 3, 2,
439 0, 4, 1, 4, 5, 1,
440 0, 6, 4, 0, 2, 6,
441 2, 3, 6, 3, 7, 6,
442 1, 5, 3, 3, 5, 7,
443 };
444 // clang-format on
445
Brian Salomon4dea72a2019-12-18 10:43:10 -0500446 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400447
448 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
449 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
450}
451
452int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
453int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
454int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
455
456///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400457sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400458 if (this->isAbandoned()) {
459 return nullptr;
460 }
461
bsalomon706f08f2015-05-22 07:35:58 -0700462 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700463 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700464}
465
Brian Salomondbf70722019-02-07 11:31:24 -0500466sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
467 GrAccessPattern accessPattern,
468 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700469 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700470 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700471 }
cdaltond37fe762016-04-21 07:41:50 -0700472 if (kDynamic_GrAccessPattern != accessPattern) {
473 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
474 }
cdaltond37fe762016-04-21 07:41:50 -0700475 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400476 static const size_t MIN_SIZE = 1 << 12;
477 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700478
cdaltond37fe762016-04-21 07:41:50 -0700479 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500480 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
481 auto buffer =
482 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400483 key)));
cdaltond37fe762016-04-21 07:41:50 -0700484 if (!buffer) {
485 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
486 if (!buffer) {
487 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700488 }
489 }
cdaltond37fe762016-04-21 07:41:50 -0700490 if (data) {
491 buffer->updateData(data, size);
492 }
493 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800494}
495
Chris Daltonf00b95b2019-11-07 21:14:41 -0700496bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700497 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600498 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700499 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400500 return true;
egdanielec00d942015-09-14 12:56:10 -0700501 }
502
503 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
504 GrUniqueKey sbKey;
505
506 int width = rt->width();
507 int height = rt->height();
508#if 0
509 if (this->caps()->oversizedStencilSupport()) {
510 width = SkNextPow2(width);
511 height = SkNextPow2(height);
512 }
513#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600514 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700515 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400516 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700517 if (!stencil) {
518 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600519 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700520 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400521 if (!stencil) {
522 return false;
egdanielec00d942015-09-14 12:56:10 -0700523 }
Robert Phillips01a91282018-07-26 08:03:04 -0400524 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700525 }
Greg Danielcfa39352018-10-05 12:01:59 -0400526 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700527 }
Chris Dalton215ff332019-07-02 09:38:22 -0600528
529 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700530 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600531 }
532 return false;
egdanielec00d942015-09-14 12:56:10 -0700533}
534
bungeman6bd52842016-10-27 09:30:08 -0700535sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400536 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700537{
ericrkf7b8b8a2016-02-24 14:49:51 -0800538 if (this->isAbandoned()) {
539 return nullptr;
540 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400541 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800542}
Greg Danield85f97d2017-03-07 13:37:21 -0500543
Greg Daniel301015c2019-11-18 14:06:46 -0500544std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
545 bool isOwned) {
546 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400547}
548
Greg Daniel301015c2019-11-18 14:06:46 -0500549std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
550 const GrBackendSemaphore& semaphore,
551 SemaphoreWrapType wrapType,
552 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400553 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500554 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
555 wrapType,
556 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500557}
Brian Salomon8660eb02019-09-20 13:04:13 -0400558
559// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
560// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
561static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400562 const SkISize& dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400563 bool rowBytesSupport,
564 GrColorType origColorType,
565 GrColorType allowedColorType,
566 GrMipLevel* outLevel,
567 std::unique_ptr<char[]>* data) {
568 if (!inLevel.fPixels) {
569 outLevel->fPixels = nullptr;
570 outLevel->fRowBytes = 0;
571 return true;
572 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400573 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400574 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
575 if (actualRB < minRB) {
576 return false;
577 }
578 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
579 outLevel->fRowBytes = actualRB;
580 outLevel->fPixels = inLevel.fPixels;
581 return true;
582 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400583 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
584 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400585 outLevel->fPixels = data->get();
586 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400587 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
588 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400589 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
590}
591
592GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
593 GrColorType colorType,
594 const SkISize& baseSize,
595 const GrMipLevel texels[],
596 int mipLevelCount,
597 TempLevels* tempLevels,
598 TempLevelDatas* tempLevelDatas) const {
599 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
600
601 auto allowedColorType =
602 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
603 if (allowedColorType == GrColorType::kUnknown) {
604 return GrColorType::kUnknown;
605 }
606 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
607 tempLevels->reset(mipLevelCount);
608 tempLevelDatas->reset(mipLevelCount);
609 auto size = baseSize;
610 for (int i = 0; i < mipLevelCount; ++i) {
611 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
612 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
613 return GrColorType::kUnknown;
614 }
615 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
616 }
617 return allowedColorType;
618}
619
620sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
621 GrColorType colorType,
622 const SkISize& baseSize,
623 const GrMipLevel texels[],
624 int mipLevelCount) const {
625 SkASSERT(!this->isAbandoned());
626 SkASSERT(texture);
627 SkASSERT(colorType != GrColorType::kUnknown);
628 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
629
630 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
631 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
632 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
633 mipLevelCount, &tmpTexels, &tmpDatas);
634 if (tempColorType == GrColorType::kUnknown) {
635 return nullptr;
636 }
637 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
638 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
639 return texture;
640}