blob: 0e171a8efa4bb40482107df5a28533cf7a0a6d5a [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,
48 GrMipLevel* outLevel, std::unique_ptr<char[]>* data) {
49 if (!inLevel.fPixels) {
50 outLevel->fPixels = nullptr;
51 outLevel->fRowBytes = 0;
52 return true;
53 }
54 size_t minRB = w * bpp;
55 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
56 if (actualRB < minRB) {
57 return false;
58 }
59 if (actualRB == minRB || rowBytesSupport) {
60 outLevel->fRowBytes = actualRB;
61 outLevel->fPixels = inLevel.fPixels;
62 } else {
63 data->reset(new char[minRB * h]);
64 outLevel->fPixels = data->get();
65 outLevel->fRowBytes = minRB;
66 SkRectMemcpy(data->get(), outLevel->fRowBytes, inLevel.fPixels, inLevel.fRowBytes, minRB,
67 h);
68 }
69 return true;
70}
71
Robert Phillips8e8c7552017-07-10 12:06:05 -040072sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Brian Osman2b23c4b2018-06-01 12:25:08 -040073 const GrMipLevel texels[], int mipLevelCount) {
Brian Osman32342f02017-03-04 08:12:46 -050074 ASSERT_SINGLE_OWNER
75
Robert Phillips7f1b4f82017-11-28 07:38:39 -050076 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040077
Brian Osman32342f02017-03-04 08:12:46 -050078 if (this->isAbandoned()) {
79 return nullptr;
80 }
Robert Phillips1119dc32017-04-11 12:54:57 -040081
Brian Salomonbdecacf2018-02-02 20:32:49 -050082 GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
83 if (!fCaps->validateSurfaceDesc(desc, mipMapped)) {
Brian Osman32342f02017-03-04 08:12:46 -050084 return nullptr;
85 }
Brian Osman32342f02017-03-04 08:12:46 -050086
Brian Salomon1047a492019-07-02 12:25:21 -040087 SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
Brian Salomonc9d81f72019-07-03 07:52:41 -040088 SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
Brian Salomon1047a492019-07-02 12:25:21 -040089 if (mipLevelCount > 0 && texels) {
90 tmpTexels.reset(mipLevelCount);
91 tmpDatas.reset(mipLevelCount);
92 int w = desc.fWidth;
93 int h = desc.fHeight;
94 size_t bpp = GrBytesPerPixel(desc.fConfig);
95 for (int i = 0; i < mipLevelCount; ++i) {
Brian Salomona3ffaab2019-07-09 12:26:46 -040096 if (!prepare_level(texels[i], bpp, w, h, this->caps()->writePixelsRowBytesSupport(),
97 &tmpTexels[i], &tmpDatas[i])) {
98 return nullptr;
Brian Salomon1047a492019-07-02 12:25:21 -040099 }
100 w = std::max(w / 2, 1);
101 h = std::max(h / 2, 1);
102 }
103 }
104 return fGpu->createTexture(desc, budgeted, tmpTexels.get(), mipLevelCount);
Brian Osman32342f02017-03-04 08:12:46 -0500105}
106
Robert Phillips45fdae12017-04-17 12:57:27 -0400107sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Chris Daltond004e0b2018-09-27 09:28:03 -0600108 SkBudgeted budgeted, Flags flags) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400109 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
110 if (tex && SkBudgeted::kNo == budgeted) {
111 tex->resourcePriv().makeUnbudgeted();
112 }
113
114 return tex;
115}
116
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500117sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
118 SkBudgeted budgeted,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500119 SkBackingFit fit,
Chris Daltond004e0b2018-09-27 09:28:03 -0600120 const GrMipLevel& mipLevel,
121 Flags flags) {
Robert Phillips774831a2017-04-20 10:19:33 -0400122 ASSERT_SINGLE_OWNER
123
124 if (this->isAbandoned()) {
125 return nullptr;
126 }
127
Robert Phillips45fdae12017-04-17 12:57:27 -0400128 if (!mipLevel.fPixels) {
129 return nullptr;
130 }
131
Brian Salomonbdecacf2018-02-02 20:32:49 -0500132 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400133 return nullptr;
134 }
135
Robert Phillips45fdae12017-04-17 12:57:27 -0400136 GrContext* context = fGpu->getContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500137 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Robert Phillips45fdae12017-04-17 12:57:27 -0400138
Brian Salomona3ffaab2019-07-09 12:26:46 -0400139 size_t bpp = GrBytesPerPixel(desc.fConfig);
140 std::unique_ptr<char[]> tmpData;
141 GrMipLevel tmpLevel;
142 if (!prepare_level(mipLevel, bpp, desc.fWidth, desc.fHeight,
143 this->caps()->writePixelsRowBytesSupport(), &tmpLevel, &tmpData)) {
144 return nullptr;
145 }
146
Brian Salomon1fcac052018-05-09 16:33:09 -0400147 SkColorType colorType;
148 if (GrPixelConfigToColorType(desc.fConfig, &colorType)) {
Chris Daltond004e0b2018-09-27 09:28:03 -0600149 sk_sp<GrTexture> tex = (SkBackingFit::kApprox == fit)
150 ? this->createApproxTexture(desc, flags)
151 : this->createTexture(desc, budgeted, flags);
152 if (!tex) {
153 return nullptr;
154 }
155
156 sk_sp<GrTextureProxy> proxy = proxyProvider->createWrapped(std::move(tex),
157 kTopLeft_GrSurfaceOrigin);
Brian Salomon1fcac052018-05-09 16:33:09 -0400158 if (!proxy) {
159 return nullptr;
Robert Phillips45fdae12017-04-17 12:57:27 -0400160 }
Brian Salomon1d435302019-07-01 13:05:28 -0400161 // Here we don't really know the alpha type of the data we want to upload. All we really
162 // care about is that it is not converted. So we use the same alpha type of the data
163 // and the surface context.
164 static constexpr auto kAlphaType = kPremul_SkAlphaType;
165 auto srcInfo = SkImageInfo::Make(desc.fWidth, desc.fHeight, colorType, kAlphaType);
Brian Salomond6287472019-06-24 15:50:07 -0400166 sk_sp<GrSurfaceContext> sContext = context->priv().makeWrappedSurfaceContext(
Brian Salomon1d435302019-07-01 13:05:28 -0400167 std::move(proxy), SkColorTypeToGrColorType(colorType), kAlphaType);
Brian Salomon1fcac052018-05-09 16:33:09 -0400168 if (!sContext) {
169 return nullptr;
170 }
Brian Salomon1d435302019-07-01 13:05:28 -0400171 SkAssertResult(
Brian Salomona3ffaab2019-07-09 12:26:46 -0400172 sContext->writePixels(srcInfo, tmpLevel.fPixels, tmpLevel.fRowBytes, {0, 0}));
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400173 return sk_ref_sp(sContext->asTextureProxy()->peekTexture());
Brian Salomon1fcac052018-05-09 16:33:09 -0400174 } else {
Brian Salomona3ffaab2019-07-09 12:26:46 -0400175 return fGpu->createTexture(desc, budgeted, &tmpLevel, 1);
Robert Phillips45fdae12017-04-17 12:57:27 -0400176 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400177}
178
Brian Salomonbb8dde82019-06-27 10:52:13 -0400179sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
180 SkImage::CompressionType compression,
181 SkBudgeted budgeted, SkData* data) {
182 ASSERT_SINGLE_OWNER
183 if (this->isAbandoned()) {
184 return nullptr;
185 }
186 return fGpu->createCompressedTexture(width, height, compression, budgeted, data->data(),
187 data->size());
188}
189
Robert Phillipse78b7252017-04-06 07:59:41 -0400190sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Chris Daltond004e0b2018-09-27 09:28:03 -0600191 Flags flags) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400192 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400193 if (this->isAbandoned()) {
194 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500195 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400196
Brian Salomonbdecacf2018-02-02 20:32:49 -0500197 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400198 return nullptr;
199 }
200
Jim Van Verth1676cb92019-01-15 13:24:45 -0500201 // Compressed textures are read-only so they don't support re-use for scratch.
202 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
203 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, flags);
204 if (tex) {
205 return tex;
206 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400207 }
208
Robert Phillips67d52cf2017-06-05 13:38:13 -0400209 return fGpu->createTexture(desc, budgeted);
Brian Osman32342f02017-03-04 08:12:46 -0500210}
211
Robert Phillips67d52cf2017-06-05 13:38:13 -0400212sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
Chris Daltond004e0b2018-09-27 09:28:03 -0600213 Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500214 ASSERT_SINGLE_OWNER
Chris Daltond004e0b2018-09-27 09:28:03 -0600215 SkASSERT(Flags::kNone == flags || Flags::kNoPendingIO == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500216
Brian Osman32342f02017-03-04 08:12:46 -0500217 if (this->isAbandoned()) {
218 return nullptr;
219 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400220
Jim Van Verth1676cb92019-01-15 13:24:45 -0500221 // Currently we don't recycle compressed textures as scratch.
222 if (GrPixelConfigIsCompressed(desc.fConfig)) {
223 return nullptr;
224 }
225
Brian Salomonbdecacf2018-02-02 20:32:49 -0500226 if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Brian Salomond34edf32017-05-19 15:45:48 -0400227 return nullptr;
228 }
229
Greg Daniel6b60b6e2017-09-26 16:37:12 -0400230 if (auto tex = this->refScratchTexture(desc, flags)) {
231 return tex;
232 }
233
Greg Daniel29bf84f2017-09-25 12:25:12 -0400234 SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
235
236 // bin by pow2 with a reasonable min
237 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
238 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
239 GrSurfaceDesc* wdesc = copyDesc.writable();
240 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fWidth));
241 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fHeight));
242 }
243
244 if (auto tex = this->refScratchTexture(*copyDesc, flags)) {
245 return tex;
246 }
247
248 return fGpu->createTexture(*copyDesc, SkBudgeted::kYes);
Brian Osman32342f02017-03-04 08:12:46 -0500249}
250
Chris Daltond004e0b2018-09-27 09:28:03 -0600251sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc, Flags flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500252 ASSERT_SINGLE_OWNER
253 SkASSERT(!this->isAbandoned());
Jim Van Verth1676cb92019-01-15 13:24:45 -0500254 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
Brian Salomonbdecacf2018-02-02 20:32:49 -0500255 SkASSERT(fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo));
Brian Osman32342f02017-03-04 08:12:46 -0500256
Brian Salomond17b4a62017-05-23 16:53:47 -0400257 // We could make initial clears work with scratch textures but it is a rare case so we just opt
258 // to fall back to making a new texture.
Greg Daniel29bf84f2017-09-25 12:25:12 -0400259 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
260 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
Brian Osman32342f02017-03-04 08:12:46 -0500261
262 GrScratchKey key;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400263 GrTexturePriv::ComputeScratchKey(desc, &key);
Chris Daltond004e0b2018-09-27 09:28:03 -0600264 auto scratchFlags = GrResourceCache::ScratchFlags::kNone;
265 if (Flags::kNoPendingIO & flags) {
266 scratchFlags |= GrResourceCache::ScratchFlags::kRequireNoPendingIO;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400267 } else if (!(desc.fFlags & kRenderTarget_GrSurfaceFlag)) {
Brian Osman32342f02017-03-04 08:12:46 -0500268 // If it is not a render target then it will most likely be populated by
269 // writePixels() which will trigger a flush if the texture has pending IO.
Chris Daltond004e0b2018-09-27 09:28:03 -0600270 scratchFlags |= GrResourceCache::ScratchFlags::kPreferNoPendingIO;
Brian Osman32342f02017-03-04 08:12:46 -0500271 }
272 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
Greg Daniel29bf84f2017-09-25 12:25:12 -0400273 GrSurface::WorstCaseSize(desc),
274 scratchFlags);
Brian Osman32342f02017-03-04 08:12:46 -0500275 if (resource) {
276 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,
Greg Daniel2268ad22018-11-15 09:27:38 -0500285 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500286 GrWrapCacheable cacheable,
287 GrIOType ioType) {
Brian Osman32342f02017-03-04 08:12:46 -0500288 ASSERT_SINGLE_OWNER
289 if (this->isAbandoned()) {
290 return nullptr;
291 }
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500292 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
Brian Salomond17f6582017-07-19 18:28:58 -0400293}
294
295sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400296 int sampleCnt,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500297 GrWrapOwnership ownership,
298 GrWrapCacheable cacheable) {
Brian Salomond17f6582017-07-19 18:28:58 -0400299 ASSERT_SINGLE_OWNER
300 if (this->isAbandoned()) {
301 return nullptr;
302 }
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500303 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
Brian Osman32342f02017-03-04 08:12:46 -0500304}
305
306sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400307 const GrBackendRenderTarget& backendRT)
Brian Osman32342f02017-03-04 08:12:46 -0500308{
309 ASSERT_SINGLE_OWNER
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400310 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500311}
312
Greg Danielb46add82019-01-02 14:51:29 -0500313sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
314 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
315 ASSERT_SINGLE_OWNER
316 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
317 vkInfo);
318
319}
320
Brian Osman32342f02017-03-04 08:12:46 -0500321void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
322 GrGpuResource* resource) {
323 ASSERT_SINGLE_OWNER
324 if (this->isAbandoned() || !resource) {
325 return;
326 }
327 resource->resourcePriv().setUniqueKey(key);
328}
329
Brian Salomond28a79d2017-10-16 13:01:07 -0400330sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500331 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400332 return this->isAbandoned() ? nullptr
333 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500334}
335
Brian Salomondbf70722019-02-07 11:31:24 -0500336sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
337 size_t size,
338 const void* data,
339 const GrUniqueKey& key) {
340 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
Kevin Lubickf7621cb2018-04-16 15:51:44 -0400341 return std::move(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700342 }
Brian Salomondbf70722019-02-07 11:31:24 -0500343 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
Chris Dalton133944a2018-11-16 23:30:29 -0500344 // We shouldn't bin and/or cache static buffers.
Brian Salomondbf70722019-02-07 11:31:24 -0500345 SkASSERT(buffer->size() == size);
Chris Dalton5d2de082017-12-19 10:40:23 -0700346 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
347 SkASSERT(!buffer->resourcePriv().hasPendingIO_debugOnly());
348 buffer->resourcePriv().setUniqueKey(key);
Brian Salomondbf70722019-02-07 11:31:24 -0500349 return sk_sp<const GrGpuBuffer>(buffer);
Chris Dalton5d2de082017-12-19 10:40:23 -0700350 }
351 return nullptr;
352}
353
Brian Salomondbf70722019-02-07 11:31:24 -0500354sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
355 int patternSize,
356 int reps,
357 int vertCount,
Brian Salomona29dd9d2019-02-07 13:27:18 -0500358 const GrUniqueKey* key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700359 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
360
Brian Salomon09d994e2016-12-21 11:14:46 -0500361 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
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 Salomond28a79d2017-10-16 13:01:07 -0400391 return std::move(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(
430 key, allocSize, GrResourceCache::ScratchFlags::kNone)));
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 Phillipsb0e93a22017-08-29 08:26:54 -0400483 const GrBackendTexture& tex, int sampleCnt)
bungeman6bd52842016-10-27 09:30:08 -0700484{
ericrkf7b8b8a2016-02-24 14:49:51 -0800485 if (this->isAbandoned()) {
486 return nullptr;
487 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500488 return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
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}