blob: 3747638cf9244aef07243f98d034a9dd513e23dc [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
296sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400297 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400298 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500299 GrWrapOwnership ownership,
300 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400301 ASSERT_SINGLE_OWNER
302 if (this->isAbandoned()) {
303 return nullptr;
304 }
Robert Phillips0902c982019-07-16 07:47:56 -0400305 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500306}
307
308sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400309 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500310{
311 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400312 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500313}
314
Greg Danielb46add82019-01-02 14:51:29 -0500315sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
316 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
317 ASSERT_SINGLE_OWNER
318 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
319 vkInfo);
320
321}
322
Brian Osman32342f02017-03-04 08:12:46 -0500323void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
324 GrGpuResource* resource) {
325 ASSERT_SINGLE_OWNER
326 if (this->isAbandoned() || !resource) {
327 return;
328 }
329 resource->resourcePriv().setUniqueKey(key);
330}
331
Brian Salomond28a79d2017-10-16 13:01:07 -0400332sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500333 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400334 return this->isAbandoned() ? nullptr
335 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500336}
337
Brian Salomondbf70722019-02-07 11:31:24 -0500338sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
339 size_t size,
340 const void* data,
341 const GrUniqueKey& key) {
342 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400343 return buffer;
Chris Dalton5d2de082017-12-19 10:40:23 -0700344 }
Brian Salomondbf70722019-02-07 11:31:24 -0500345 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500346 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500347 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700348 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
Chris Dalton5d2de082017-12-19 10:40:23 -0700349 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500350 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700351 }
352 return nullptr;
353}
354
Brian Salomondbf70722019-02-07 11:31:24 -0500355sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
356 int patternSize,
357 int reps,
358 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500359 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700360 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
361
Brian Salomondbf70722019-02-07 11:31:24 -0500362 sk_sp<GrGpuBuffer> buffer(
363 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700364 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700365 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700366 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400367 uint16_t* data = (uint16_t*) buffer->map();
368 SkAutoTArray<uint16_t> temp;
369 if (!data) {
370 temp.reset(reps * patternSize);
371 data = temp.get();
372 }
bsalomoned0bcad2015-05-04 10:36:42 -0700373 for (int i = 0; i < reps; ++i) {
374 int baseIdx = i * patternSize;
375 uint16_t baseVert = (uint16_t)(i * vertCount);
376 for (int j = 0; j < patternSize; ++j) {
377 data[baseIdx+j] = baseVert + pattern[j];
378 }
379 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400380 if (temp.get()) {
381 if (!buffer->updateData(data, bufferSize)) {
382 return nullptr;
383 }
384 } else {
385 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700386 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500387 if (key) {
388 SkASSERT(key->isValid());
389 this->assignUniqueKeyToResource(*key, buffer.get());
390 }
Brian Salomon9c73e3d2019-08-15 10:55:49 -0400391 return buffer;
bsalomoned0bcad2015-05-04 10:36:42 -0700392}
393
Brian Salomon34169692017-08-28 15:32:01 -0400394static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
395
Brian Salomondbf70722019-02-07 11:31:24 -0500396sk_sp<const GrGpuBuffer> GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700397 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
Brian Salomon57caa662017-10-18 12:21:05 +0000398 static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
Brian Salomona29dd9d2019-02-07 13:27:18 -0500399 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700400}
401
Brian Salomon763abf02018-05-01 18:49:38 +0000402int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
Brian Salomon34169692017-08-28 15:32:01 -0400403
Robert Phillips67d52cf2017-06-05 13:38:13 -0400404sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400405 if (this->isAbandoned()) {
406 return nullptr;
407 }
408
bsalomon706f08f2015-05-22 07:35:58 -0700409 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700410 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700411}
412
Brian Salomondbf70722019-02-07 11:31:24 -0500413sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
414 GrAccessPattern accessPattern,
415 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700416 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700417 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700418 }
cdaltond37fe762016-04-21 07:41:50 -0700419 if (kDynamic_GrAccessPattern != accessPattern) {
420 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
421 }
cdaltond37fe762016-04-21 07:41:50 -0700422 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400423 static const size_t MIN_SIZE = 1 << 12;
424 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700425
cdaltond37fe762016-04-21 07:41:50 -0700426 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500427 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
428 auto buffer =
429 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400430 key)));
cdaltond37fe762016-04-21 07:41:50 -0700431 if (!buffer) {
432 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
433 if (!buffer) {
434 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700435 }
436 }
cdaltond37fe762016-04-21 07:41:50 -0700437 if (data) {
438 buffer->updateData(data, size);
439 }
440 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800441}
442
Chris Daltoneffee202019-07-01 22:28:03 -0600443bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int minStencilSampleCount) {
egdanielec00d942015-09-14 12:56:10 -0700444 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600445 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
446 if (stencil && stencil->numSamples() >= minStencilSampleCount) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400447 return true;
egdanielec00d942015-09-14 12:56:10 -0700448 }
449
450 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
451 GrUniqueKey sbKey;
452
453 int width = rt->width();
454 int height = rt->height();
455#if 0
456 if (this->caps()->oversizedStencilSupport()) {
457 width = SkNextPow2(width);
458 height = SkNextPow2(height);
459 }
460#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600461 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
462 width, height, minStencilSampleCount, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400463 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700464 if (!stencil) {
465 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600466 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
467 rt, width, height, minStencilSampleCount));
Robert Phillips01a91282018-07-26 08:03:04 -0400468 if (!stencil) {
469 return false;
egdanielec00d942015-09-14 12:56:10 -0700470 }
Robert Phillips01a91282018-07-26 08:03:04 -0400471 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700472 }
Greg Danielcfa39352018-10-05 12:01:59 -0400473 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700474 }
Chris Dalton215ff332019-07-02 09:38:22 -0600475
476 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
477 return stencil->numSamples() >= minStencilSampleCount;
478 }
479 return false;
egdanielec00d942015-09-14 12:56:10 -0700480}
481
bungeman6bd52842016-10-27 09:30:08 -0700482sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400483 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700484{
ericrkf7b8b8a2016-02-24 14:49:51 -0800485 if (this->isAbandoned()) {
486 return nullptr;
487 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400488 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800489}
Greg Danield85f97d2017-03-07 13:37:21 -0500490
Greg Daniela5cb7812017-06-16 09:45:32 -0400491sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
492 return fGpu->makeSemaphore(isOwned);
493}
494
495sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
Greg Daniel17b7c052018-01-09 13:55:33 -0500496 SemaphoreWrapType wrapType,
Greg Daniela5cb7812017-06-16 09:45:32 -0400497 GrWrapOwnership ownership) {
498 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500499 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
500 wrapType,
501 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500502}
Brian Salomon8660eb02019-09-20 13:04:13 -0400503
504// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
505// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
506static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400507 const SkISize& dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400508 bool rowBytesSupport,
509 GrColorType origColorType,
510 GrColorType allowedColorType,
511 GrMipLevel* outLevel,
512 std::unique_ptr<char[]>* data) {
513 if (!inLevel.fPixels) {
514 outLevel->fPixels = nullptr;
515 outLevel->fRowBytes = 0;
516 return true;
517 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400518 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400519 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
520 if (actualRB < minRB) {
521 return false;
522 }
523 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
524 outLevel->fRowBytes = actualRB;
525 outLevel->fPixels = inLevel.fPixels;
526 return true;
527 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400528 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
529 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400530 outLevel->fPixels = data->get();
531 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400532 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
533 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400534 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
535}
536
537GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
538 GrColorType colorType,
539 const SkISize& baseSize,
540 const GrMipLevel texels[],
541 int mipLevelCount,
542 TempLevels* tempLevels,
543 TempLevelDatas* tempLevelDatas) const {
544 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
545
546 auto allowedColorType =
547 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
548 if (allowedColorType == GrColorType::kUnknown) {
549 return GrColorType::kUnknown;
550 }
551 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
552 tempLevels->reset(mipLevelCount);
553 tempLevelDatas->reset(mipLevelCount);
554 auto size = baseSize;
555 for (int i = 0; i < mipLevelCount; ++i) {
556 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
557 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
558 return GrColorType::kUnknown;
559 }
560 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
561 }
562 return allowedColorType;
563}
564
565sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
566 GrColorType colorType,
567 const SkISize& baseSize,
568 const GrMipLevel texels[],
569 int mipLevelCount) const {
570 SkASSERT(!this->isAbandoned());
571 SkASSERT(texture);
572 SkASSERT(colorType != GrColorType::kUnknown);
573 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
574
575 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
576 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
577 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
578 mipLevelCount, &tmpTexels, &tmpDatas);
579 if (tempColorType == GrColorType::kUnknown) {
580 return nullptr;
581 }
582 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
583 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
584 return texture;
585}