blob: 0541037e6ae4c18535dac4d4fda08300155262f8 [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"
20#include "src/gpu/GrPath.h"
21#include "src/gpu/GrPathRendering.h"
22#include "src/gpu/GrProxyProvider.h"
23#include "src/gpu/GrRenderTargetPriv.h"
24#include "src/gpu/GrResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrSemaphore.h"
26#include "src/gpu/GrStencilAttachment.h"
27#include "src/gpu/GrTexturePriv.h"
28#include "src/gpu/SkGr.h"
bsalomoned0bcad2015-05-04 10:36:42 -070029
Robert Phillips1bfece82017-06-01 13:56:52 -040030const uint32_t GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050031
32#define ASSERT_SINGLE_OWNER \
33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
34
Robert Phillips12c46292019-04-23 07:36:17 -040035GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050036 : fCache(cache)
37 , fGpu(gpu)
38#ifdef SK_DEBUG
39 , fSingleOwner(owner)
40#endif
Robert Phillips4150eea2018-02-07 17:08:21 -050041{
Robert Phillips26c90e02017-03-14 14:39:29 -040042 fCaps = sk_ref_sp(fGpu->caps());
bsalomoned0bcad2015-05-04 10:36:42 -070043}
44
Brian Salomona3ffaab2019-07-09 12:26:46 -040045// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
46// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
47static bool prepare_level(const GrMipLevel& inLevel, size_t bpp, int w, int h, bool rowBytesSupport,
Brian Salomona3e29962019-07-16 11:52:08 -040048 bool mustInitializeAllLevels, GrMipLevel* outLevel,
49 std::unique_ptr<char[]>* data) {
50 size_t minRB = w * bpp;
Brian Salomona3ffaab2019-07-09 12:26:46 -040051 if (!inLevel.fPixels) {
Brian Salomona3e29962019-07-16 11:52:08 -040052 if (mustInitializeAllLevels) {
53 data->reset(new char[minRB * h]());
54 outLevel->fPixels = data->get();
55 outLevel->fRowBytes = minRB;
56 } else {
57 outLevel->fPixels = nullptr;
58 outLevel->fRowBytes = 0;
59 }
Brian Salomona3ffaab2019-07-09 12:26:46 -040060 return true;
61 }
Brian Salomona3ffaab2019-07-09 12:26:46 -040062 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
63 if (actualRB < minRB) {
64 return false;
65 }
66 if (actualRB == minRB || rowBytesSupport) {
67 outLevel->fRowBytes = actualRB;
68 outLevel->fPixels = inLevel.fPixels;
69 } else {
70 data->reset(new char[minRB * h]);
71 outLevel->fPixels = data->get();
72 outLevel->fRowBytes = minRB;
73 SkRectMemcpy(data->get(), outLevel->fRowBytes, inLevel.fPixels, inLevel.fRowBytes, minRB,
74 h);
75 }
76 return true;
77}
78
Brian Salomonf2c2ba92019-07-17 09:59:59 -040079sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -040080 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040081 GrRenderable renderable,
Brian Salomon2af3e702019-08-11 19:10:31 -040082 int renderTargetSampleCnt,
83 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -040084 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -040085 const GrMipLevel texels[],
86 int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050087 ASSERT_SINGLE_OWNER
88
Robert Phillips7f1b4f82017-11-28 07:38:39 -050089 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040090
Brian Osman32342f02017-03-04 08:12:46 -050091 if (this->isAbandoned()) {
92 return nullptr;
93 }
Robert Phillips1119dc32017-04-11 12:54:57 -040094
Brian Salomonbdecacf2018-02-02 20:32:49 -050095 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
Greg Daniel6fa62e22019-08-07 15:52:37 -040096 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
97 renderTargetSampleCnt, mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050098 return nullptr;
99 }
Brian Salomona3e29962019-07-16 11:52:08 -0400100 bool mustInitializeAllLevels = this->caps()->createTextureMustSpecifyAllLevels();
101 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
Brian Salomon1047a492019-07-02 12:25:21 -0400102 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -0400103 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon1047a492019-07-02 12:25:21 -0400104 if (mipLevelCount > 0 && texels) {
105 tmpTexels.reset(mipLevelCount);
106 tmpDatas.reset(mipLevelCount);
107 int w = desc.fWidth;
108 int h = desc.fHeight;
109 size_t bpp = GrBytesPerPixel(desc.fConfig);
110 for (int i = 0; i < mipLevelCount; ++i) {
Brian Salomona3e29962019-07-16 11:52:08 -0400111 if (!prepare_level(texels[i], bpp, w, h, rowBytesSupport, mustInitializeAllLevels,
Brian Salomona3ffaab2019-07-09 12:26:46 -0400112 &tmpTexels[i], &tmpDatas[i])) {
113 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -0400114 }
115 w = std::max(w / 2, 1);
116 h = std::max(h / 2, 1);
117 }
118 }
Brian Salomon4eb38b72019-08-05 12:58:39 -0400119 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
120 isProtected, tmpTexels.get(), mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -0500121}
122
Robert Phillips45fdae12017-04-17 12:57:27 -0400123sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400124 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400125 GrRenderable renderable,
126 int renderTargetSampleCnt,
127 SkBudgeted budgeted,
128 GrProtected isProtected,
129 Flags flags) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400130 sk_sp<GrTexture> tex(this->refScratchTexture(desc, format, renderable, renderTargetSampleCnt,
131 isProtected, flags));
Robert Phillips45fdae12017-04-17 12:57:27 -0400132 if (tex && SkBudgeted::kNo == budgeted) {
133 tex->resourcePriv().makeUnbudgeted();
134 }
135
136 return tex;
137}
138
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500139sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400140 const GrBackendFormat& format,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400141 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400142 int renderTargetSampleCnt,
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500143 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500144 SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -0400145 GrProtected isProtected,
Brian Salomon2af3e702019-08-11 19:10:31 -0400146 GrColorType srcColorType,
Chris Daltond004e0b2018-09-27 09:28:03 -0600147 const GrMipLevel& mipLevel,
148 Flags flags) {
Robert Phillips774831a2017-04-20 10:19:33 -0400149 ASSERT_SINGLE_OWNER
150
151 if (this->isAbandoned()) {
152 return nullptr;
153 }
154
Robert Phillips45fdae12017-04-17 12:57:27 -0400155 if (!mipLevel.fPixels) {
156 return nullptr;
157 }
158
Greg Daniel6fa62e22019-08-07 15:52:37 -0400159 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
160 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400161 return nullptr;
162 }
163
Robert Phillips45fdae12017-04-17 12:57:27 -0400164 GrContext* context = fGpu->getContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500165 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Robert Phillips45fdae12017-04-17 12:57:27 -0400166
Brian Salomona3e29962019-07-16 11:52:08 -0400167 bool mustInitialize = this->caps()->createTextureMustSpecifyAllLevels();
168 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
169
Brian Salomona3ffaab2019-07-09 12:26:46 -0400170 size_t bpp = GrBytesPerPixel(desc.fConfig);
171 std::unique_ptr<char[]> tmpData;
172 GrMipLevel tmpLevel;
Brian Salomona3e29962019-07-16 11:52:08 -0400173 if (!prepare_level(mipLevel, bpp, desc.fWidth, desc.fHeight, rowBytesSupport, mustInitialize,
174 &tmpLevel, &tmpData)) {
Brian Salomona3ffaab2019-07-09 12:26:46 -0400175 return nullptr;
176 }
177
Brian Salomone8a766b2019-07-19 14:24:36 -0400178 sk_sp<GrTexture> tex =
179 (SkBackingFit::kApprox == fit)
Brian Salomon4eb38b72019-08-05 12:58:39 -0400180 ? this->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400181 isProtected, flags)
Brian Salomon4eb38b72019-08-05 12:58:39 -0400182 : this->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400183 isProtected, flags);
Brian Salomona495d6d2019-07-13 17:48:58 -0400184 if (!tex) {
185 return nullptr;
Robert Phillips45fdae12017-04-17 12:57:27 -0400186 }
Brian Salomona495d6d2019-07-13 17:48:58 -0400187
Brian Salomon2af3e702019-08-11 19:10:31 -0400188 sk_sp<GrTextureProxy> proxy =
189 proxyProvider->createWrapped(tex, srcColorType, kTopLeft_GrSurfaceOrigin);
Brian Salomona495d6d2019-07-13 17:48:58 -0400190 if (!proxy) {
191 return nullptr;
192 }
193 // Here we don't really know the alpha type of the data we want to upload. All we really
194 // care about is that it is not converted. So we use the same alpha type for the data
195 // and the surface context.
Brian Salomon2af3e702019-08-11 19:10:31 -0400196 static constexpr auto kAlphaType = kUnpremul_SkAlphaType;
Brian Salomona495d6d2019-07-13 17:48:58 -0400197 sk_sp<GrSurfaceContext> sContext =
Brian Salomon2af3e702019-08-11 19:10:31 -0400198 context->priv().makeWrappedSurfaceContext(std::move(proxy), srcColorType, kAlphaType);
Brian Salomona495d6d2019-07-13 17:48:58 -0400199 if (!sContext) {
200 return nullptr;
201 }
Brian Salomon2af3e702019-08-11 19:10:31 -0400202 GrPixelInfo srcInfo(srcColorType, kAlphaType, nullptr, desc.fWidth, desc.fHeight);
Brian Salomona495d6d2019-07-13 17:48:58 -0400203 SkAssertResult(sContext->writePixels(srcInfo, tmpLevel.fPixels, tmpLevel.fRowBytes, {0, 0}));
204 return tex;
Robert Phillips45fdae12017-04-17 12:57:27 -0400205}
206
Brian Salomonbb8dde82019-06-27 10:52:13 -0400207sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
Greg Daniel7bfc9132019-08-14 14:23:53 -0400208 const GrBackendFormat& format,
Brian Salomonbb8dde82019-06-27 10:52:13 -0400209 SkImage::CompressionType compression,
210 SkBudgeted budgeted, SkData* data) {
211 ASSERT_SINGLE_OWNER
212 if (this->isAbandoned()) {
213 return nullptr;
214 }
Greg Daniel7bfc9132019-08-14 14:23:53 -0400215 return fGpu->createCompressedTexture(width, height, format, compression, budgeted, data->data(),
Brian Salomonbb8dde82019-06-27 10:52:13 -0400216 data->size());
217}
218
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400219sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400220 const GrBackendFormat& format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400221 GrRenderable renderable,
222 int renderTargetSampleCnt,
223 SkBudgeted budgeted,
224 GrProtected isProtected,
225 Flags flags) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400226 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400227 if (this->isAbandoned()) {
228 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500229 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400230
Greg Daniel6fa62e22019-08-07 15:52:37 -0400231 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
232 renderTargetSampleCnt, GrMipMapped::kNo)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400233 return nullptr;
234 }
235
Jim Van Verth1676cb92019-01-15 13:24:45 -0500236 // Compressed textures are read-only so they don't support re-use for scratch.
237 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400238 sk_sp<GrTexture> tex = this->getExactScratch(
239 desc, format, renderable, renderTargetSampleCnt, budgeted, isProtected, flags);
Jim Van Verth1676cb92019-01-15 13:24:45 -0500240 if (tex) {
241 return tex;
242 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400243 }
244
Brian Salomona3e29962019-07-16 11:52:08 -0400245 if (fCaps->createTextureMustSpecifyAllLevels()) {
Brian Salomonc7dced52019-07-18 15:02:01 +0000246 size_t rowBytes = GrBytesPerPixel(desc.fConfig) * desc.fWidth;
247 size_t size = rowBytes * desc.fHeight;
248 std::unique_ptr<char[]> zeros(new char[size]());
249 GrMipLevel level;
250 level.fRowBytes = rowBytes;
Brian Salomona3e29962019-07-16 11:52:08 -0400251 level.fPixels = zeros.get();
Brian Salomon4eb38b72019-08-05 12:58:39 -0400252 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
253 isProtected, &level, 1);
Brian Salomona3e29962019-07-16 11:52:08 -0400254 }
255
Brian Salomon4eb38b72019-08-05 12:58:39 -0400256 return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
257 isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500258}
259
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400260// Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
261// the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
262uint32_t GrResourceProvider::MakeApprox(uint32_t value) {
263 static const int kMagicTol = 1024;
264
265 value = SkTMax(kMinScratchTextureSize, value);
266
267 if (SkIsPow2(value)) {
268 return value;
269 }
270
271 uint32_t ceilPow2 = GrNextPow2(value);
272 if (value <= kMagicTol) {
273 return ceilPow2;
274 }
275
276 uint32_t floorPow2 = ceilPow2 >> 1;
277 uint32_t mid = floorPow2 + (floorPow2 >> 1);
278
279 if (value <= mid) {
280 return mid;
281 }
282
283 return ceilPow2;
284}
285
Robert Phillips67d52cf2017-06-05 13:38:13 -0400286sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400287 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400288 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400289 int renderTargetSampleCnt,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400290 GrProtected isProtected,
291 Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500292 ASSERT_SINGLE_OWNER
Chris Daltond004e0b2018-09-27 09:28:03 -0600293 SkASSERT(Flags::kNone == flags || Flags::kNoPendingIO == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500294
Brian Osman32342f02017-03-04 08:12:46 -0500295 if (this->isAbandoned()) {
296 return nullptr;
297 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400298
Jim Van Verth1676cb92019-01-15 13:24:45 -0500299 // Currently we don't recycle compressed textures as scratch.
300 if (GrPixelConfigIsCompressed(desc.fConfig)) {
301 return nullptr;
302 }
303
Greg Daniel6fa62e22019-08-07 15:52:37 -0400304 if (!fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
305 renderTargetSampleCnt, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400306 return nullptr;
307 }
308
Brian Salomon4eb38b72019-08-05 12:58:39 -0400309 if (auto tex = this->refScratchTexture(desc, format, renderable, renderTargetSampleCnt,
310 isProtected, flags)) {
Greg Daniel6b60b6e2017-09-26 16:37:12 -0400311 return tex;
312 }
313
Greg Daniel29bf84f2017-09-25 12:25:12 -0400314 SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
315
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400316 // bin by some multiple or power of 2 with a reasonable min
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400317 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400318 GrSurfaceDesc* wdesc = copyDesc.writable();
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400319 wdesc->fWidth = MakeApprox(wdesc->fWidth);
320 wdesc->fHeight = MakeApprox(wdesc->fHeight);
Greg Daniel29bf84f2017-09-25 12:25:12 -0400321 }
322
Brian Salomon4eb38b72019-08-05 12:58:39 -0400323 if (auto tex = this->refScratchTexture(*copyDesc, format, renderable, renderTargetSampleCnt,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400324 isProtected, flags)) {
Greg Daniel29bf84f2017-09-25 12:25:12 -0400325 return tex;
326 }
327
Brian Salomona3e29962019-07-16 11:52:08 -0400328 if (this->caps()->createTextureMustSpecifyAllLevels()) {
Brian Salomonc7dced52019-07-18 15:02:01 +0000329 size_t rowBytes = GrBytesPerPixel(copyDesc->fConfig) * copyDesc->fWidth;
330 size_t size = rowBytes * copyDesc->fHeight;
331 std::unique_ptr<char[]> zeros(new char[size]());
332 GrMipLevel level;
333 level.fRowBytes = rowBytes;
Brian Salomona3e29962019-07-16 11:52:08 -0400334 level.fPixels = zeros.get();
Brian Salomon4eb38b72019-08-05 12:58:39 -0400335 return fGpu->createTexture(*copyDesc, format, renderable, renderTargetSampleCnt,
336 SkBudgeted::kYes, isProtected, &level, 1);
Brian Salomona3e29962019-07-16 11:52:08 -0400337 }
Brian Salomon4eb38b72019-08-05 12:58:39 -0400338 return fGpu->createTexture(*copyDesc, format, renderable, renderTargetSampleCnt,
339 SkBudgeted::kYes, isProtected);
Brian Osman32342f02017-03-04 08:12:46 -0500340}
341
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400342sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400343 const GrBackendFormat& format,
Brian Salomone8a766b2019-07-19 14:24:36 -0400344 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400345 int renderTargetSampleCnt,
346 GrProtected isProtected,
347 Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500348 ASSERT_SINGLE_OWNER
349 SkASSERT(!this->isAbandoned());
Jim Van Verth1676cb92019-01-15 13:24:45 -0500350 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
Greg Daniel6fa62e22019-08-07 15:52:37 -0400351 SkASSERT(fCaps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig,
352 renderable, renderTargetSampleCnt, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500353
Brian Salomond17b4a62017-05-23 16:53:47 -0400354 // We could make initial clears work with scratch textures but it is a rare case so we just opt
355 // to fall back to making a new texture.
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400356 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
Brian Osman32342f02017-03-04 08:12:46 -0500357 GrScratchKey key;
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400358 GrTexturePriv::ComputeScratchKey(desc, renderable, renderTargetSampleCnt, &key);
Chris Daltond004e0b2018-09-27 09:28:03 -0600359 auto scratchFlags = GrResourceCache::ScratchFlags::kNone;
360 if (Flags::kNoPendingIO & flags) {
361 scratchFlags |= GrResourceCache::ScratchFlags::kRequireNoPendingIO;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400362 } else if (renderable == GrRenderable::kNo) {
Brian Osman32342f02017-03-04 08:12:46 -0500363 // If it is not a render target then it will most likely be populated by
364 // writePixels() which will trigger a flush if the texture has pending IO.
Chris Daltond004e0b2018-09-27 09:28:03 -0600365 scratchFlags |= GrResourceCache::ScratchFlags::kPreferNoPendingIO;
Brian Osman32342f02017-03-04 08:12:46 -0500366 }
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400367 GrGpuResource* resource = fCache->findAndRefScratchResource(
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400368 key, GrSurface::WorstCaseSize(desc, renderable, renderTargetSampleCnt),
369 scratchFlags);
Brian Osman32342f02017-03-04 08:12:46 -0500370 if (resource) {
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400371 fGpu->stats()->incNumScratchTexturesReused();
Brian Osman32342f02017-03-04 08:12:46 -0500372 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400373 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500374 }
375 }
376
Brian Osman32342f02017-03-04 08:12:46 -0500377 return nullptr;
378}
379
Greg Daniel7ef28f32017-04-20 16:41:55 +0000380sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400381 GrColorType colorType,
Greg Daniel2268ad22018-11-15 09:27:38 -0500382 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500383 GrWrapCacheable cacheable,
384 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500385 ASSERT_SINGLE_OWNER
386 if (this->isAbandoned()) {
387 return nullptr;
388 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400389 return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400390}
391
392sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400393 int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400394 GrColorType colorType,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500395 GrWrapOwnership ownership,
396 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400397 ASSERT_SINGLE_OWNER
398 if (this->isAbandoned()) {
399 return nullptr;
400 }
Robert Phillips0902c982019-07-16 07:47:56 -0400401 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500402}
403
404sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400405 const GrBackendRenderTarget& backendRT, GrColorType colorType)
Brian Osman32342f02017-03-04 08:12:46 -0500406{
407 ASSERT_SINGLE_OWNER
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400408 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
Brian Osman32342f02017-03-04 08:12:46 -0500409}
410
Greg Danielb46add82019-01-02 14:51:29 -0500411sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
412 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
413 ASSERT_SINGLE_OWNER
414 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
415 vkInfo);
416
417}
418
Brian Osman32342f02017-03-04 08:12:46 -0500419void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
420 GrGpuResource* resource) {
421 ASSERT_SINGLE_OWNER
422 if (this->isAbandoned() || !resource) {
423 return;
424 }
425 resource->resourcePriv().setUniqueKey(key);
426}
427
Brian Salomond28a79d2017-10-16 13:01:07 -0400428sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500429 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400430 return this->isAbandoned() ? nullptr
431 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500432}
433
Brian Salomondbf70722019-02-07 11:31:24 -0500434sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
435 size_t size,
436 const void* data,
437 const GrUniqueKey& key) {
438 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Kevin Lubickf7621cb2018-04-16 15:51:44 -0400439 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700440 }
Brian Salomondbf70722019-02-07 11:31:24 -0500441 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500442 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500443 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700444 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
445 SkASSERT(!buffer->resourcePriv().hasPendingIO_debugOnly());
446 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500447 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700448 }
449 return nullptr;
450}
451
Brian Salomondbf70722019-02-07 11:31:24 -0500452sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
453 int patternSize,
454 int reps,
455 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500456 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700457 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
458
Brian Salomon09d994e2016-12-21 11:14:46 -0500459 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
Brian Salomondbf70722019-02-07 11:31:24 -0500460 sk_sp<GrGpuBuffer> buffer(
461 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700462 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700463 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700464 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400465 uint16_t* data = (uint16_t*) buffer->map();
466 SkAutoTArray<uint16_t> temp;
467 if (!data) {
468 temp.reset(reps * patternSize);
469 data = temp.get();
470 }
bsalomoned0bcad2015-05-04 10:36:42 -0700471 for (int i = 0; i < reps; ++i) {
472 int baseIdx = i * patternSize;
473 uint16_t baseVert = (uint16_t)(i * vertCount);
474 for (int j = 0; j < patternSize; ++j) {
475 data[baseIdx+j] = baseVert + pattern[j];
476 }
477 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400478 if (temp.get()) {
479 if (!buffer->updateData(data, bufferSize)) {
480 return nullptr;
481 }
482 } else {
483 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700484 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500485 if (key) {
486 SkASSERT(key->isValid());
487 this->assignUniqueKeyToResource(*key, buffer.get());
488 }
Brian Salomond28a79d2017-10-16 13:01:07 -0400489 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700490}
491
Brian Salomon34169692017-08-28 15:32:01 -0400492static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
493
Brian Salomondbf70722019-02-07 11:31:24 -0500494sk_sp<const GrGpuBuffer> GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700495 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
Brian Salomon57caa662017-10-18 12:21:05 +0000496 static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
Brian Salomona29dd9d2019-02-07 13:27:18 -0500497 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700498}
499
Brian Salomon763abf02018-05-01 18:49:38 +0000500int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
Brian Salomon34169692017-08-28 15:32:01 -0400501
Robert Phillips67d52cf2017-06-05 13:38:13 -0400502sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400503 if (this->isAbandoned()) {
504 return nullptr;
505 }
506
bsalomon706f08f2015-05-22 07:35:58 -0700507 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700508 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700509}
510
Brian Salomondbf70722019-02-07 11:31:24 -0500511sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
512 GrAccessPattern accessPattern,
513 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700514 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700515 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700516 }
cdaltond37fe762016-04-21 07:41:50 -0700517 if (kDynamic_GrAccessPattern != accessPattern) {
518 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
519 }
cdaltond37fe762016-04-21 07:41:50 -0700520 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400521 static const size_t MIN_SIZE = 1 << 12;
522 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700523
cdaltond37fe762016-04-21 07:41:50 -0700524 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500525 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
526 auto buffer =
527 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
528 key, allocSize, GrResourceCache::ScratchFlags::kNone)));
cdaltond37fe762016-04-21 07:41:50 -0700529 if (!buffer) {
530 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
531 if (!buffer) {
532 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700533 }
534 }
cdaltond37fe762016-04-21 07:41:50 -0700535 if (data) {
536 buffer->updateData(data, size);
537 }
538 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800539}
540
Chris Daltoneffee202019-07-01 22:28:03 -0600541bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int minStencilSampleCount) {
egdanielec00d942015-09-14 12:56:10 -0700542 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600543 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
544 if (stencil && stencil->numSamples() >= minStencilSampleCount) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400545 return true;
egdanielec00d942015-09-14 12:56:10 -0700546 }
547
548 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
549 GrUniqueKey sbKey;
550
551 int width = rt->width();
552 int height = rt->height();
553#if 0
554 if (this->caps()->oversizedStencilSupport()) {
555 width = SkNextPow2(width);
556 height = SkNextPow2(height);
557 }
558#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600559 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
560 width, height, minStencilSampleCount, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400561 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700562 if (!stencil) {
563 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600564 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
565 rt, width, height, minStencilSampleCount));
Robert Phillips01a91282018-07-26 08:03:04 -0400566 if (!stencil) {
567 return false;
egdanielec00d942015-09-14 12:56:10 -0700568 }
Robert Phillips01a91282018-07-26 08:03:04 -0400569 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700570 }
Greg Danielcfa39352018-10-05 12:01:59 -0400571 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700572 }
Chris Dalton215ff332019-07-02 09:38:22 -0600573
574 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
575 return stencil->numSamples() >= minStencilSampleCount;
576 }
577 return false;
egdanielec00d942015-09-14 12:56:10 -0700578}
579
bungeman6bd52842016-10-27 09:30:08 -0700580sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400581 const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
bungeman6bd52842016-10-27 09:30:08 -0700582{
ericrkf7b8b8a2016-02-24 14:49:51 -0800583 if (this->isAbandoned()) {
584 return nullptr;
585 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400586 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
ericrkf7b8b8a2016-02-24 14:49:51 -0800587}
Greg Danield85f97d2017-03-07 13:37:21 -0500588
Greg Daniela5cb7812017-06-16 09:45:32 -0400589sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
590 return fGpu->makeSemaphore(isOwned);
591}
592
593sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
Greg Daniel17b7c052018-01-09 13:55:33 -0500594 SemaphoreWrapType wrapType,
Greg Daniela5cb7812017-06-16 09:45:32 -0400595 GrWrapOwnership ownership) {
596 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500597 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
598 wrapType,
599 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500600}