blob: 31b502abe88176b1fe6e01801227ecfb192c3eb7 [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
Robert Phillipsee08d522019-10-28 16:34:44 -0400394///////////////////////////////////////////////////////////////////////////////////////////////////
395static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
396static const int kVertsPerNonAAQuad = 4;
397static const int kIndicesPerNonAAQuad = 6;
Brian Salomon34169692017-08-28 15:32:01 -0400398
Robert Phillipsee08d522019-10-28 16:34:44 -0400399sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500400 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400401
402 static const uint16_t kNonAAQuadIndexPattern[] = {
403 0, 1, 2, 2, 1, 3
404 };
405
Brian Salomon4dea72a2019-12-18 10:43:10 -0500406 static_assert(SK_ARRAY_COUNT(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400407
408 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
409 kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700410}
411
Robert Phillipsee08d522019-10-28 16:34:44 -0400412int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
413int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
414int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
Brian Salomon34169692017-08-28 15:32:01 -0400415
Robert Phillipsee08d522019-10-28 16:34:44 -0400416///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips8bc157e2019-11-15 12:04:48 -0500417static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
Robert Phillipsee08d522019-10-28 16:34:44 -0400418static const int kVertsPerAAQuad = 8;
419static const int kIndicesPerAAQuad = 30;
420
421sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500422 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
Robert Phillipsee08d522019-10-28 16:34:44 -0400423
424 // clang-format off
425 static const uint16_t kAAQuadIndexPattern[] = {
426 0, 1, 2, 1, 3, 2,
427 0, 4, 1, 4, 5, 1,
428 0, 6, 4, 0, 2, 6,
429 2, 3, 6, 3, 7, 6,
430 1, 5, 3, 3, 5, 7,
431 };
432 // clang-format on
433
Brian Salomon4dea72a2019-12-18 10:43:10 -0500434 static_assert(SK_ARRAY_COUNT(kAAQuadIndexPattern) == kIndicesPerAAQuad);
Robert Phillipsee08d522019-10-28 16:34:44 -0400435
436 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
437 kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
438}
439
440int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
441int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
442int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
443
444///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips67d52cf2017-06-05 13:38:13 -0400445sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400446 if (this->isAbandoned()) {
447 return nullptr;
448 }
449
bsalomon706f08f2015-05-22 07:35:58 -0700450 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700451 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700452}
453
Brian Salomondbf70722019-02-07 11:31:24 -0500454sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
455 GrAccessPattern accessPattern,
456 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700457 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700458 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700459 }
cdaltond37fe762016-04-21 07:41:50 -0700460 if (kDynamic_GrAccessPattern != accessPattern) {
461 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
462 }
cdaltond37fe762016-04-21 07:41:50 -0700463 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400464 static const size_t MIN_SIZE = 1 << 12;
465 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700466
cdaltond37fe762016-04-21 07:41:50 -0700467 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500468 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
469 auto buffer =
470 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
Robert Phillipsaee18c92019-09-06 11:48:27 -0400471 key)));
cdaltond37fe762016-04-21 07:41:50 -0700472 if (!buffer) {
473 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
474 if (!buffer) {
475 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700476 }
477 }
cdaltond37fe762016-04-21 07:41:50 -0700478 if (data) {
479 buffer->updateData(data, size);
480 }
481 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800482}
483
Chris Daltonf00b95b2019-11-07 21:14:41 -0700484bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int numStencilSamples) {
egdanielec00d942015-09-14 12:56:10 -0700485 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600486 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
Chris Daltonf00b95b2019-11-07 21:14:41 -0700487 if (stencil && stencil->numSamples() == numStencilSamples) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400488 return true;
egdanielec00d942015-09-14 12:56:10 -0700489 }
490
491 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
492 GrUniqueKey sbKey;
493
494 int width = rt->width();
495 int height = rt->height();
496#if 0
497 if (this->caps()->oversizedStencilSupport()) {
498 width = SkNextPow2(width);
499 height = SkNextPow2(height);
500 }
501#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600502 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700503 width, height, numStencilSamples, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400504 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700505 if (!stencil) {
506 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600507 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
Chris Daltonf00b95b2019-11-07 21:14:41 -0700508 rt, width, height, numStencilSamples));
Robert Phillips01a91282018-07-26 08:03:04 -0400509 if (!stencil) {
510 return false;
egdanielec00d942015-09-14 12:56:10 -0700511 }
Robert Phillips01a91282018-07-26 08:03:04 -0400512 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700513 }
Greg Danielcfa39352018-10-05 12:01:59 -0400514 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700515 }
Chris Dalton215ff332019-07-02 09:38:22 -0600516
517 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
Chris Daltonf00b95b2019-11-07 21:14:41 -0700518 return stencil->numSamples() == numStencilSamples;
Chris Dalton215ff332019-07-02 09:38:22 -0600519 }
520 return false;
egdanielec00d942015-09-14 12:56:10 -0700521}
522
bungeman6bd52842016-10-27 09:30:08 -0700523sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400524 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700525{
ericrkf7b8b8a2016-02-24 14:49:51 -0800526 if (this->isAbandoned()) {
527 return nullptr;
528 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400529 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800530}
Greg Danield85f97d2017-03-07 13:37:21 -0500531
Greg Daniel301015c2019-11-18 14:06:46 -0500532std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(
533 bool isOwned) {
534 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
Greg Daniela5cb7812017-06-16 09:45:32 -0400535}
536
Greg Daniel301015c2019-11-18 14:06:46 -0500537std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
538 const GrBackendSemaphore& semaphore,
539 SemaphoreWrapType wrapType,
540 GrWrapOwnership ownership) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400541 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500542 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
543 wrapType,
544 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500545}
Brian Salomon8660eb02019-09-20 13:04:13 -0400546
547// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
548// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
549static bool prepare_level(const GrMipLevel& inLevel,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400550 const SkISize& dimensions,
Brian Salomon8660eb02019-09-20 13:04:13 -0400551 bool rowBytesSupport,
552 GrColorType origColorType,
553 GrColorType allowedColorType,
554 GrMipLevel* outLevel,
555 std::unique_ptr<char[]>* data) {
556 if (!inLevel.fPixels) {
557 outLevel->fPixels = nullptr;
558 outLevel->fRowBytes = 0;
559 return true;
560 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400561 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
Brian Salomon8660eb02019-09-20 13:04:13 -0400562 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
563 if (actualRB < minRB) {
564 return false;
565 }
566 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
567 outLevel->fRowBytes = actualRB;
568 outLevel->fPixels = inLevel.fPixels;
569 return true;
570 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400571 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
572 data->reset(new char[tempRB * dimensions.fHeight]);
Brian Salomon8660eb02019-09-20 13:04:13 -0400573 outLevel->fPixels = data->get();
574 outLevel->fRowBytes = tempRB;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400575 GrImageInfo srcInfo(origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
576 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
Brian Salomon8660eb02019-09-20 13:04:13 -0400577 return GrConvertPixels(dstInfo, data->get(), tempRB, srcInfo, inLevel.fPixels, actualRB);
578}
579
580GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
581 GrColorType colorType,
582 const SkISize& baseSize,
583 const GrMipLevel texels[],
584 int mipLevelCount,
585 TempLevels* tempLevels,
586 TempLevelDatas* tempLevelDatas) const {
587 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
588
589 auto allowedColorType =
590 this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
591 if (allowedColorType == GrColorType::kUnknown) {
592 return GrColorType::kUnknown;
593 }
594 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
595 tempLevels->reset(mipLevelCount);
596 tempLevelDatas->reset(mipLevelCount);
597 auto size = baseSize;
598 for (int i = 0; i < mipLevelCount; ++i) {
599 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
600 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
601 return GrColorType::kUnknown;
602 }
603 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
604 }
605 return allowedColorType;
606}
607
608sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
609 GrColorType colorType,
610 const SkISize& baseSize,
611 const GrMipLevel texels[],
612 int mipLevelCount) const {
613 SkASSERT(!this->isAbandoned());
614 SkASSERT(texture);
615 SkASSERT(colorType != GrColorType::kUnknown);
616 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
617
618 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
619 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
620 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
621 mipLevelCount, &tmpTexels, &tmpDatas);
622 if (tempColorType == GrColorType::kUnknown) {
623 return nullptr;
624 }
625 SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
626 colorType, tempColorType, tmpTexels.get(), mipLevelCount));
627 return texture;
628}