blob: e4b01c28bd576941848be46790b4f500df0e08cc [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
Robert Phillips8e8c7552017-07-10 12:06:05 -040045sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Brian Osman2b23c4b2018-06-01 12:25:08 -040046 const GrMipLevel texels[], int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050047 ASSERT_SINGLE_OWNER
48
Robert Phillips7f1b4f82017-11-28 07:38:39 -050049 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040050
Brian Osman32342f02017-03-04 08:12:46 -050051 if (this->isAbandoned()) {
52 return nullptr;
53 }
Robert Phillips1119dc32017-04-11 12:54:57 -040054
Brian Salomonbdecacf2018-02-02 20:32:49 -050055 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
56 if (!fCaps->validateSurfaceDesc(desc, mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050057 return nullptr;
58 }
Brian Osman32342f02017-03-04 08:12:46 -050059
Brian Salomon1047a492019-07-02 12:25:21 -040060 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
61 SkAutoSTMalloc<14, std::unique_ptr<char[]>> tmpDatas;
62 if (mipLevelCount > 0 && texels) {
63 tmpTexels.reset(mipLevelCount);
64 tmpDatas.reset(mipLevelCount);
65 int w = desc.fWidth;
66 int h = desc.fHeight;
67 size_t bpp = GrBytesPerPixel(desc.fConfig);
68 for (int i = 0; i < mipLevelCount; ++i) {
69 if (texels->fPixels) {
70 size_t minRB = w * bpp;
71 if (!texels->fRowBytes) {
72 tmpTexels[i].fRowBytes = minRB;
73 tmpTexels[i].fPixels = texels[i].fPixels;
74 } else {
75 if (texels[i].fRowBytes < minRB) {
76 return nullptr;
77 }
78 if (this->caps()->writePixelsRowBytesSupport() &&
79 texels[i].fRowBytes != minRB) {
80 auto copy = new char[minRB * h];
81 tmpDatas[i].reset(copy);
82 SkRectMemcpy(copy, minRB, texels[i].fPixels, texels[i].fRowBytes, minRB, h);
83 tmpTexels[i].fPixels = copy;
84 tmpTexels[i].fRowBytes = minRB;
85 } else {
86 tmpTexels[i].fPixels = texels[i].fPixels;
87 tmpTexels[i].fRowBytes = texels[i].fRowBytes;
88 }
89 }
90 } else {
91 tmpTexels[i].fPixels = nullptr;
92 tmpTexels[i].fRowBytes = 0;
93 }
94 w = std::max(w / 2, 1);
95 h = std::max(h / 2, 1);
96 }
97 }
98 return fGpu->createTexture(desc, budgeted, tmpTexels.get(), mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -050099}
100
Robert Phillips45fdae12017-04-17 12:57:27 -0400101sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Chris Daltond004e0b2018-09-27 09:28:03 -0600102 SkBudgeted budgeted, Flags flags) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400103 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
104 if (tex && SkBudgeted::kNo == budgeted) {
105 tex->resourcePriv().makeUnbudgeted();
106 }
107
108 return tex;
109}
110
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500111sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
112 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500113 SkBackingFit fit,
Chris Daltond004e0b2018-09-27 09:28:03 -0600114 const GrMipLevel& mipLevel,
115 Flags flags) {
Robert Phillips774831a2017-04-20 10:19:33 -0400116 ASSERT_SINGLE_OWNER
117
118 if (this->isAbandoned()) {
119 return nullptr;
120 }
121
Robert Phillips45fdae12017-04-17 12:57:27 -0400122 if (!mipLevel.fPixels) {
123 return nullptr;
124 }
125
Brian Salomonbdecacf2018-02-02 20:32:49 -0500126 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400127 return nullptr;
128 }
129
Robert Phillips45fdae12017-04-17 12:57:27 -0400130 GrContext* context = fGpu->getContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500131 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Robert Phillips45fdae12017-04-17 12:57:27 -0400132
Brian Salomon1fcac052018-05-09 16:33:09 -0400133 SkColorType colorType;
134 if (GrPixelConfigToColorType(desc.fConfig, &colorType)) {
Chris Daltond004e0b2018-09-27 09:28:03 -0600135 sk_sp<GrTexture> tex = (SkBackingFit::kApprox == fit)
136 ? this->createApproxTexture(desc, flags)
137 : this->createTexture(desc, budgeted, flags);
138 if (!tex) {
139 return nullptr;
140 }
141
142 sk_sp<GrTextureProxy> proxy = proxyProvider->createWrapped(std::move(tex),
143 kTopLeft_GrSurfaceOrigin);
Brian Salomon1fcac052018-05-09 16:33:09 -0400144 if (!proxy) {
145 return nullptr;
Robert Phillips45fdae12017-04-17 12:57:27 -0400146 }
Brian Salomon1d435302019-07-01 13:05:28 -0400147 // Here we don't really know the alpha type of the data we want to upload. All we really
148 // care about is that it is not converted. So we use the same alpha type of the data
149 // and the surface context.
150 static constexpr auto kAlphaType = kPremul_SkAlphaType;
151 auto srcInfo = SkImageInfo::Make(desc.fWidth, desc.fHeight, colorType, kAlphaType);
Brian Salomond6287472019-06-24 15:50:07 -0400152 sk_sp<GrSurfaceContext> sContext = context->priv().makeWrappedSurfaceContext(
Brian Salomon1d435302019-07-01 13:05:28 -0400153 std::move(proxy), SkColorTypeToGrColorType(colorType), kAlphaType);
Brian Salomon1fcac052018-05-09 16:33:09 -0400154 if (!sContext) {
155 return nullptr;
156 }
Brian Salomon1d435302019-07-01 13:05:28 -0400157 SkAssertResult(
158 sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, {0, 0}));
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400159 return sk_ref_sp(sContext->asTextureProxy()->peekTexture());
Brian Salomon1fcac052018-05-09 16:33:09 -0400160 } else {
161 return fGpu->createTexture(desc, budgeted, &mipLevel, 1);
Robert Phillips45fdae12017-04-17 12:57:27 -0400162 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400163}
164
Brian Salomonbb8dde82019-06-27 10:52:13 -0400165sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
166 SkImage::CompressionType compression,
167 SkBudgeted budgeted, SkData* data) {
168 ASSERT_SINGLE_OWNER
169 if (this->isAbandoned()) {
170 return nullptr;
171 }
172 return fGpu->createCompressedTexture(width, height, compression, budgeted, data->data(),
173 data->size());
174}
175
Robert Phillipse78b7252017-04-06 07:59:41 -0400176sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Chris Daltond004e0b2018-09-27 09:28:03 -0600177 Flags flags) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400178 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400179 if (this->isAbandoned()) {
180 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500181 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400182
Brian Salomonbdecacf2018-02-02 20:32:49 -0500183 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400184 return nullptr;
185 }
186
Jim Van Verth1676cb92019-01-15 13:24:45 -0500187 // Compressed textures are read-only so they don't support re-use for scratch.
188 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
189 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, flags);
190 if (tex) {
191 return tex;
192 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400193 }
194
Robert Phillips67d52cf2017-06-05 13:38:13 -0400195 return fGpu->createTexture(desc, budgeted);
Brian Osman32342f02017-03-04 08:12:46 -0500196}
197
Robert Phillips67d52cf2017-06-05 13:38:13 -0400198sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Chris Daltond004e0b2018-09-27 09:28:03 -0600199 Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500200 ASSERT_SINGLE_OWNER
Chris Daltond004e0b2018-09-27 09:28:03 -0600201 SkASSERT(Flags::kNone == flags || Flags::kNoPendingIO == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500202
Brian Osman32342f02017-03-04 08:12:46 -0500203 if (this->isAbandoned()) {
204 return nullptr;
205 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400206
Jim Van Verth1676cb92019-01-15 13:24:45 -0500207 // Currently we don't recycle compressed textures as scratch.
208 if (GrPixelConfigIsCompressed(desc.fConfig)) {
209 return nullptr;
210 }
211
Brian Salomonbdecacf2018-02-02 20:32:49 -0500212 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400213 return nullptr;
214 }
215
Greg Daniel6b60b6e2017-09-26 16:37:12 -0400216 if (auto tex = this->refScratchTexture(desc, flags)) {
217 return tex;
218 }
219
Greg Daniel29bf84f2017-09-25 12:25:12 -0400220 SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
221
222 // bin by pow2 with a reasonable min
223 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
224 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
225 GrSurfaceDesc* wdesc = copyDesc.writable();
226 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fWidth));
227 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fHeight));
228 }
229
230 if (auto tex = this->refScratchTexture(*copyDesc, flags)) {
231 return tex;
232 }
233
234 return fGpu->createTexture(*copyDesc, SkBudgeted::kYes);
Brian Osman32342f02017-03-04 08:12:46 -0500235}
236
Chris Daltond004e0b2018-09-27 09:28:03 -0600237sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc, Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500238 ASSERT_SINGLE_OWNER
239 SkASSERT(!this->isAbandoned());
Jim Van Verth1676cb92019-01-15 13:24:45 -0500240 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
Brian Salomonbdecacf2018-02-02 20:32:49 -0500241 SkASSERT(fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500242
Brian Salomond17b4a62017-05-23 16:53:47 -0400243 // We could make initial clears work with scratch textures but it is a rare case so we just opt
244 // to fall back to making a new texture.
Greg Daniel29bf84f2017-09-25 12:25:12 -0400245 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
246 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
Brian Osman32342f02017-03-04 08:12:46 -0500247
248 GrScratchKey key;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400249 GrTexturePriv::ComputeScratchKey(desc, &key);
Chris Daltond004e0b2018-09-27 09:28:03 -0600250 auto scratchFlags = GrResourceCache::ScratchFlags::kNone;
251 if (Flags::kNoPendingIO & flags) {
252 scratchFlags |= GrResourceCache::ScratchFlags::kRequireNoPendingIO;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400253 } else if (!(desc.fFlags & kRenderTarget_GrSurfaceFlag)) {
Brian Osman32342f02017-03-04 08:12:46 -0500254 // If it is not a render target then it will most likely be populated by
255 // writePixels() which will trigger a flush if the texture has pending IO.
Chris Daltond004e0b2018-09-27 09:28:03 -0600256 scratchFlags |= GrResourceCache::ScratchFlags::kPreferNoPendingIO;
Brian Osman32342f02017-03-04 08:12:46 -0500257 }
258 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
Greg Daniel29bf84f2017-09-25 12:25:12 -0400259 GrSurface::WorstCaseSize(desc),
260 scratchFlags);
Brian Osman32342f02017-03-04 08:12:46 -0500261 if (resource) {
262 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400263 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500264 }
265 }
266
Brian Osman32342f02017-03-04 08:12:46 -0500267 return nullptr;
268}
269
Greg Daniel7ef28f32017-04-20 16:41:55 +0000270sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Greg Daniel2268ad22018-11-15 09:27:38 -0500271 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500272 GrWrapCacheable cacheable,
273 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500274 ASSERT_SINGLE_OWNER
275 if (this->isAbandoned()) {
276 return nullptr;
277 }
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500278 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400279}
280
281sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400282 int sampleCnt,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500283 GrWrapOwnership ownership,
284 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400285 ASSERT_SINGLE_OWNER
286 if (this->isAbandoned()) {
287 return nullptr;
288 }
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500289 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500290}
291
292sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400293 const GrBackendRenderTarget& backendRT)
Brian Osman32342f02017-03-04 08:12:46 -0500294{
295 ASSERT_SINGLE_OWNER
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400296 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500297}
298
Greg Danielb46add82019-01-02 14:51:29 -0500299sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
300 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
301 ASSERT_SINGLE_OWNER
302 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
303 vkInfo);
304
305}
306
Brian Osman32342f02017-03-04 08:12:46 -0500307void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
308 GrGpuResource* resource) {
309 ASSERT_SINGLE_OWNER
310 if (this->isAbandoned() || !resource) {
311 return;
312 }
313 resource->resourcePriv().setUniqueKey(key);
314}
315
Brian Salomond28a79d2017-10-16 13:01:07 -0400316sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500317 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400318 return this->isAbandoned() ? nullptr
319 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500320}
321
Brian Salomondbf70722019-02-07 11:31:24 -0500322sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
323 size_t size,
324 const void* data,
325 const GrUniqueKey& key) {
326 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Kevin Lubickf7621cb2018-04-16 15:51:44 -0400327 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700328 }
Brian Salomondbf70722019-02-07 11:31:24 -0500329 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500330 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500331 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700332 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
333 SkASSERT(!buffer->resourcePriv().hasPendingIO_debugOnly());
334 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500335 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700336 }
337 return nullptr;
338}
339
Brian Salomondbf70722019-02-07 11:31:24 -0500340sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
341 int patternSize,
342 int reps,
343 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500344 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700345 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
346
Brian Salomon09d994e2016-12-21 11:14:46 -0500347 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
Brian Salomondbf70722019-02-07 11:31:24 -0500348 sk_sp<GrGpuBuffer> buffer(
349 this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
bsalomoned0bcad2015-05-04 10:36:42 -0700350 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700351 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700352 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400353 uint16_t* data = (uint16_t*) buffer->map();
354 SkAutoTArray<uint16_t> temp;
355 if (!data) {
356 temp.reset(reps * patternSize);
357 data = temp.get();
358 }
bsalomoned0bcad2015-05-04 10:36:42 -0700359 for (int i = 0; i < reps; ++i) {
360 int baseIdx = i * patternSize;
361 uint16_t baseVert = (uint16_t)(i * vertCount);
362 for (int j = 0; j < patternSize; ++j) {
363 data[baseIdx+j] = baseVert + pattern[j];
364 }
365 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400366 if (temp.get()) {
367 if (!buffer->updateData(data, bufferSize)) {
368 return nullptr;
369 }
370 } else {
371 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700372 }
Brian Salomona29dd9d2019-02-07 13:27:18 -0500373 if (key) {
374 SkASSERT(key->isValid());
375 this->assignUniqueKeyToResource(*key, buffer.get());
376 }
Brian Salomond28a79d2017-10-16 13:01:07 -0400377 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700378}
379
Brian Salomon34169692017-08-28 15:32:01 -0400380static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
381
Brian Salomondbf70722019-02-07 11:31:24 -0500382sk_sp<const GrGpuBuffer> GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700383 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
Brian Salomon57caa662017-10-18 12:21:05 +0000384 static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
Brian Salomona29dd9d2019-02-07 13:27:18 -0500385 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, nullptr);
bsalomoned0bcad2015-05-04 10:36:42 -0700386}
387
Brian Salomon763abf02018-05-01 18:49:38 +0000388int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
Brian Salomon34169692017-08-28 15:32:01 -0400389
Robert Phillips67d52cf2017-06-05 13:38:13 -0400390sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400391 if (this->isAbandoned()) {
392 return nullptr;
393 }
394
bsalomon706f08f2015-05-22 07:35:58 -0700395 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700396 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700397}
398
Brian Salomondbf70722019-02-07 11:31:24 -0500399sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
400 GrAccessPattern accessPattern,
401 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700402 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700403 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700404 }
cdaltond37fe762016-04-21 07:41:50 -0700405 if (kDynamic_GrAccessPattern != accessPattern) {
406 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
407 }
cdaltond37fe762016-04-21 07:41:50 -0700408 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400409 static const size_t MIN_SIZE = 1 << 12;
410 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700411
cdaltond37fe762016-04-21 07:41:50 -0700412 GrScratchKey key;
Brian Salomondbf70722019-02-07 11:31:24 -0500413 GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
414 auto buffer =
415 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
416 key, allocSize, GrResourceCache::ScratchFlags::kNone)));
cdaltond37fe762016-04-21 07:41:50 -0700417 if (!buffer) {
418 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
419 if (!buffer) {
420 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700421 }
422 }
cdaltond37fe762016-04-21 07:41:50 -0700423 if (data) {
424 buffer->updateData(data, size);
425 }
426 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800427}
428
Chris Daltoneffee202019-07-01 22:28:03 -0600429bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int minStencilSampleCount) {
egdanielec00d942015-09-14 12:56:10 -0700430 SkASSERT(rt);
Chris Daltoneffee202019-07-01 22:28:03 -0600431 GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
432 if (stencil && stencil->numSamples() >= minStencilSampleCount) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400433 return true;
egdanielec00d942015-09-14 12:56:10 -0700434 }
435
436 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
437 GrUniqueKey sbKey;
438
439 int width = rt->width();
440 int height = rt->height();
441#if 0
442 if (this->caps()->oversizedStencilSupport()) {
443 width = SkNextPow2(width);
444 height = SkNextPow2(height);
445 }
446#endif
Chris Daltoneffee202019-07-01 22:28:03 -0600447 GrStencilAttachment::ComputeSharedStencilAttachmentKey(
448 width, height, minStencilSampleCount, &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400449 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700450 if (!stencil) {
451 // Need to try and create a new stencil
Chris Daltoneffee202019-07-01 22:28:03 -0600452 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
453 rt, width, height, minStencilSampleCount));
Robert Phillips01a91282018-07-26 08:03:04 -0400454 if (!stencil) {
455 return false;
egdanielec00d942015-09-14 12:56:10 -0700456 }
Robert Phillips01a91282018-07-26 08:03:04 -0400457 this->assignUniqueKeyToResource(sbKey, stencil.get());
egdanielec00d942015-09-14 12:56:10 -0700458 }
Greg Danielcfa39352018-10-05 12:01:59 -0400459 rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
egdanielec00d942015-09-14 12:56:10 -0700460 }
Chris Dalton215ff332019-07-02 09:38:22 -0600461
462 if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
463 return stencil->numSamples() >= minStencilSampleCount;
464 }
465 return false;
egdanielec00d942015-09-14 12:56:10 -0700466}
467
bungeman6bd52842016-10-27 09:30:08 -0700468sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400469 const GrBackendTexture& tex, int sampleCnt)
bungeman6bd52842016-10-27 09:30:08 -0700470{
ericrkf7b8b8a2016-02-24 14:49:51 -0800471 if (this->isAbandoned()) {
472 return nullptr;
473 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500474 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800475}
Greg Danield85f97d2017-03-07 13:37:21 -0500476
Greg Daniela5cb7812017-06-16 09:45:32 -0400477sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
478 return fGpu->makeSemaphore(isOwned);
479}
480
481sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
Greg Daniel17b7c052018-01-09 13:55:33 -0500482 SemaphoreWrapType wrapType,
Greg Daniela5cb7812017-06-16 09:45:32 -0400483 GrWrapOwnership ownership) {
484 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500485 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
486 wrapType,
487 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500488}