blob: 79fcd952bb61c380be466699609ec3e0fb4c1bc6 [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
8#include "GrResourceProvider.h"
9
cdalton397536c2016-03-25 12:15:03 -070010#include "GrBuffer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070011#include "GrCaps.h"
Robert Phillips26c90e02017-03-14 14:39:29 -040012#include "GrContext.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040013#include "GrContextPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070014#include "GrGpu.h"
kkinnunencabe20c2015-06-01 01:37:26 -070015#include "GrPathRendering.h"
egdanielec00d942015-09-14 12:56:10 -070016#include "GrRenderTarget.h"
17#include "GrRenderTargetPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070018#include "GrResourceCache.h"
19#include "GrResourceKey.h"
Greg Danield85f97d2017-03-07 13:37:21 -050020#include "GrSemaphore.h"
egdanielec00d942015-09-14 12:56:10 -070021#include "GrStencilAttachment.h"
Robert Phillipsb66b42f2017-03-14 08:53:02 -040022#include "GrSurfaceProxyPriv.h"
Brian Osman32342f02017-03-04 08:12:46 -050023#include "GrTexturePriv.h"
24#include "../private/GrSingleOwner.h"
Robert Phillips45fdae12017-04-17 12:57:27 -040025#include "SkGr.h"
halcanary4dbbd042016-06-07 17:21:10 -070026#include "SkMathPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070027
28GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
29
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
joshualitt6d0872d2016-01-11 08:27:48 -080035GrResourceProvider::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
41 {
Robert Phillips26c90e02017-03-14 14:39:29 -040042 fCaps = sk_ref_sp(fGpu->caps());
43
bsalomoned0bcad2015-05-04 10:36:42 -070044 GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
45 fQuadIndexBufferKey = gQuadIndexBufferKey;
46}
47
Robert Phillipsf7a72612017-03-31 10:03:45 -040048bool GrResourceProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
Robert Phillipsb66b42f2017-03-14 08:53:02 -040049 return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
50}
Brian Osman32342f02017-03-04 08:12:46 -050051
Brian Salomond34edf32017-05-19 15:45:48 -040052bool validate_desc(const GrSurfaceDesc& desc, const GrCaps& caps, int levelCount = 0) {
53 if (desc.fWidth <= 0 || desc.fHeight <= 0) {
54 return false;
55 }
56 if (!caps.isConfigTexturable(desc.fConfig)) {
57 return false;
58 }
59 if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
60 if (!caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
61 return false;
62 }
63 } else {
64 if (desc.fSampleCnt) {
65 return false;
66 }
67 }
Brian Osman48c99192017-06-02 08:45:06 -040068 if (levelCount > 1 && (GrPixelConfigIsSint(desc.fConfig) || !caps.mipMapSupport())) {
Brian Salomond34edf32017-05-19 15:45:48 -040069 return false;
70 }
71 return true;
72}
73
Robert Phillipse78b7252017-04-06 07:59:41 -040074// MDB TODO: this should probably be a factory on GrSurfaceProxy
75sk_sp<GrTextureProxy> GrResourceProvider::createMipMappedTexture(
76 const GrSurfaceDesc& desc,
77 SkBudgeted budgeted,
78 const GrMipLevel* texels,
79 int mipLevelCount,
Robert Phillipsa4c41b32017-03-15 13:02:45 -040080 SkDestinationSurfaceColorMode mipColorMode) {
Brian Osman32342f02017-03-04 08:12:46 -050081 ASSERT_SINGLE_OWNER
82
Robert Phillips1119dc32017-04-11 12:54:57 -040083 if (!mipLevelCount) {
84 if (texels) {
85 return nullptr;
86 }
87 return GrSurfaceProxy::MakeDeferred(this, desc, budgeted, nullptr, 0);
Robert Phillips45fdae12017-04-17 12:57:27 -040088 } else if (1 == mipLevelCount) {
89 if (!texels) {
90 return nullptr;
91 }
92 return this->createTextureProxy(desc, budgeted, texels[0]);
Robert Phillips1119dc32017-04-11 12:54:57 -040093 }
94
Brian Osman32342f02017-03-04 08:12:46 -050095 if (this->isAbandoned()) {
96 return nullptr;
97 }
Robert Phillips1119dc32017-04-11 12:54:57 -040098
Brian Salomond34edf32017-05-19 15:45:48 -040099 if (!validate_desc(desc, *fCaps, mipLevelCount)) {
Brian Osman32342f02017-03-04 08:12:46 -0500100 return nullptr;
101 }
Brian Osman32342f02017-03-04 08:12:46 -0500102
103 SkTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
104 for (int i = 0; i < mipLevelCount; ++i) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400105 if (!texels[i].fPixels) {
106 return nullptr;
107 }
108
Brian Osman32342f02017-03-04 08:12:46 -0500109 texelsShallowCopy.push_back(texels[i]);
110 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400111 sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texelsShallowCopy));
112 if (tex) {
113 tex->texturePriv().setMipColorMode(mipColorMode);
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400114 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400115
116 return GrSurfaceProxy::MakeWrapped(std::move(tex));
Brian Osman32342f02017-03-04 08:12:46 -0500117}
118
Robert Phillips45fdae12017-04-17 12:57:27 -0400119sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
120 SkBudgeted budgeted, uint32_t flags) {
121
122 flags |= kExact_Flag | kNoCreate_Flag;
123 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
124 if (tex && SkBudgeted::kNo == budgeted) {
125 tex->resourcePriv().makeUnbudgeted();
126 }
127
128 return tex;
129}
130
131static bool make_info(int w, int h, GrPixelConfig config, SkImageInfo* ii) {
132 SkColorType colorType;
133 if (!GrPixelConfigToColorType(config, &colorType)) {
134 return false;
135 }
136
137 *ii = SkImageInfo::Make(w, h, colorType, kUnknown_SkAlphaType, nullptr);
138 return true;
139}
140
141sk_sp<GrTextureProxy> GrResourceProvider::createTextureProxy(const GrSurfaceDesc& desc,
142 SkBudgeted budgeted,
143 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400144 ASSERT_SINGLE_OWNER
145
146 if (this->isAbandoned()) {
147 return nullptr;
148 }
149
Robert Phillips45fdae12017-04-17 12:57:27 -0400150 if (!mipLevel.fPixels) {
151 return nullptr;
152 }
153
Brian Salomond34edf32017-05-19 15:45:48 -0400154 if (!validate_desc(desc, *fCaps)) {
155 return nullptr;
156 }
157
Robert Phillips45fdae12017-04-17 12:57:27 -0400158 GrContext* context = fGpu->getContext();
159
Robert Phillips92de6312017-05-23 07:43:48 -0400160 SkImageInfo srcInfo;
Robert Phillips45fdae12017-04-17 12:57:27 -0400161
Robert Phillips92de6312017-05-23 07:43:48 -0400162 if (make_info(desc.fWidth, desc.fHeight, desc.fConfig, &srcInfo)) {
163 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, 0);
Robert Phillipsfe50d962017-06-01 10:22:03 -0400164 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex));
165 if (proxy) {
166 sk_sp<GrSurfaceContext> sContext =
167 context->contextPriv().makeWrappedSurfaceContext(std::move(proxy), nullptr);
168 if (sContext) {
169 if (sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, 0, 0)) {
170 return sContext->asTextureProxyRef();
171 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400172 }
173 }
174 }
175
176 SkTArray<GrMipLevel> texels(1);
177 texels.push_back(mipLevel);
178
179 sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texels));
180 return GrSurfaceProxy::MakeWrapped(std::move(tex));
181}
182
183
Robert Phillipse78b7252017-04-06 07:59:41 -0400184sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
185 uint32_t flags) {
186 ASSERT_SINGLE_OWNER
187
188 if (this->isAbandoned()) {
189 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500190 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400191
Brian Salomond34edf32017-05-19 15:45:48 -0400192 if (!validate_desc(desc, *fCaps)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400193 return nullptr;
194 }
195
Robert Phillips92de6312017-05-23 07:43:48 -0400196 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, flags);
197 if (tex) {
198 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400199 }
200
Robert Phillips92de6312017-05-23 07:43:48 -0400201 tex.reset(fGpu->createTexture(desc, budgeted));
Robert Phillipse78b7252017-04-06 07:59:41 -0400202 return tex;
Brian Osman32342f02017-03-04 08:12:46 -0500203}
204
205GrTexture* GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) {
206 ASSERT_SINGLE_OWNER
207 SkASSERT(0 == flags || kNoPendingIO_Flag == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500208
Brian Osman32342f02017-03-04 08:12:46 -0500209 if (this->isAbandoned()) {
210 return nullptr;
211 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400212
Brian Salomond34edf32017-05-19 15:45:48 -0400213 if (!validate_desc(desc, *fCaps)) {
214 return nullptr;
215 }
216
Robert Phillips1119dc32017-04-11 12:54:57 -0400217 return this->refScratchTexture(desc, flags);
Brian Osman32342f02017-03-04 08:12:46 -0500218}
219
Brian Salomond34edf32017-05-19 15:45:48 -0400220GrTexture* GrResourceProvider::refScratchTexture(const GrSurfaceDesc& inDesc, uint32_t flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500221 ASSERT_SINGLE_OWNER
222 SkASSERT(!this->isAbandoned());
Brian Salomond34edf32017-05-19 15:45:48 -0400223 SkASSERT(validate_desc(inDesc, *fCaps));
Brian Osman32342f02017-03-04 08:12:46 -0500224
225 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
226
Brian Salomond17b4a62017-05-23 16:53:47 -0400227 // We could make initial clears work with scratch textures but it is a rare case so we just opt
228 // to fall back to making a new texture.
229 if (!SkToBool(inDesc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
230 (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag))) {
Brian Osman32342f02017-03-04 08:12:46 -0500231 if (!(kExact_Flag & flags)) {
232 // bin by pow2 with a reasonable min
233 GrSurfaceDesc* wdesc = desc.writable();
234 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fWidth));
235 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fHeight));
236 }
237
238 GrScratchKey key;
239 GrTexturePriv::ComputeScratchKey(*desc, &key);
240 uint32_t scratchFlags = 0;
241 if (kNoPendingIO_Flag & flags) {
242 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
243 } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
244 // If it is not a render target then it will most likely be populated by
245 // writePixels() which will trigger a flush if the texture has pending IO.
246 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
247 }
248 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
249 GrSurface::WorstCaseSize(*desc),
250 scratchFlags);
251 if (resource) {
252 GrSurface* surface = static_cast<GrSurface*>(resource);
Brian Osman32342f02017-03-04 08:12:46 -0500253 return surface->asTexture();
254 }
255 }
256
257 if (!(kNoCreate_Flag & flags)) {
258 return fGpu->createTexture(*desc, SkBudgeted::kYes);
259 }
260
261 return nullptr;
262}
263
Greg Daniel7ef28f32017-04-20 16:41:55 +0000264sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
265 GrSurfaceOrigin origin,
266 GrBackendTextureFlags flags,
267 int sampleCnt,
Brian Osman32342f02017-03-04 08:12:46 -0500268 GrWrapOwnership ownership) {
269 ASSERT_SINGLE_OWNER
270 if (this->isAbandoned()) {
271 return nullptr;
272 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000273 return fGpu->wrapBackendTexture(tex, origin, flags, sampleCnt, ownership);
Brian Osman32342f02017-03-04 08:12:46 -0500274}
275
276sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Greg Danielbcf612b2017-05-01 13:50:58 +0000277 const GrBackendRenderTarget& backendRT, GrSurfaceOrigin origin)
Brian Osman32342f02017-03-04 08:12:46 -0500278{
279 ASSERT_SINGLE_OWNER
Greg Danielbcf612b2017-05-01 13:50:58 +0000280 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, origin);
Brian Osman32342f02017-03-04 08:12:46 -0500281}
282
283void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
284 GrGpuResource* resource) {
285 ASSERT_SINGLE_OWNER
286 if (this->isAbandoned() || !resource) {
287 return;
288 }
289 resource->resourcePriv().setUniqueKey(key);
290}
291
292GrGpuResource* GrResourceProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
293 ASSERT_SINGLE_OWNER
294 return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
295}
296
297GrTexture* GrResourceProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
298 ASSERT_SINGLE_OWNER
299 GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
300 if (resource) {
301 GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
302 SkASSERT(texture);
303 return texture;
304 }
305 return NULL;
306}
307
Robert Phillipsd3749482017-03-14 09:17:43 -0400308// MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs
309void GrResourceProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
310 ASSERT_SINGLE_OWNER
311 SkASSERT(key.isValid());
312 if (this->isAbandoned() || !proxy) {
313 return;
314 }
315
Brian Salomonbb5711a2017-05-17 13:49:59 -0400316 GrTexture* texture = proxy->instantiateTexture(this);
Robert Phillipsd3749482017-03-14 09:17:43 -0400317 if (!texture) {
318 return;
319 }
320
321 this->assignUniqueKeyToResource(key, texture);
322}
323
324// MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs
325sk_sp<GrTextureProxy> GrResourceProvider::findProxyByUniqueKey(const GrUniqueKey& key) {
326 ASSERT_SINGLE_OWNER
327
328 sk_sp<GrTexture> texture(this->findAndRefTextureByUniqueKey(key));
329 if (!texture) {
330 return nullptr;
331 }
332
333 return GrSurfaceProxy::MakeWrapped(std::move(texture));
334}
335
Chris Daltonff926502017-05-03 14:36:54 -0400336const GrBuffer* GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
cdalton397536c2016-03-25 12:15:03 -0700337 int patternSize,
338 int reps,
339 int vertCount,
340 const GrUniqueKey& key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700341 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
342
Brian Salomon09d994e2016-12-21 11:14:46 -0500343 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
cdaltone2e71c22016-04-07 18:13:29 -0700344 GrBuffer* buffer = this->createBuffer(bufferSize, kIndex_GrBufferType, kStatic_GrAccessPattern,
cdalton397536c2016-03-25 12:15:03 -0700345 kNoPendingIO_Flag);
bsalomoned0bcad2015-05-04 10:36:42 -0700346 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700347 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700348 }
349 uint16_t* data = (uint16_t*) buffer->map();
halcanary96fcdcc2015-08-27 07:41:13 -0700350 bool useTempData = (nullptr == data);
bsalomoned0bcad2015-05-04 10:36:42 -0700351 if (useTempData) {
halcanary385fe4d2015-08-26 13:07:48 -0700352 data = new uint16_t[reps * patternSize];
bsalomoned0bcad2015-05-04 10:36:42 -0700353 }
354 for (int i = 0; i < reps; ++i) {
355 int baseIdx = i * patternSize;
356 uint16_t baseVert = (uint16_t)(i * vertCount);
357 for (int j = 0; j < patternSize; ++j) {
358 data[baseIdx+j] = baseVert + pattern[j];
359 }
360 }
361 if (useTempData) {
362 if (!buffer->updateData(data, bufferSize)) {
363 buffer->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700364 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700365 }
halcanary385fe4d2015-08-26 13:07:48 -0700366 delete[] data;
bsalomoned0bcad2015-05-04 10:36:42 -0700367 } else {
368 buffer->unmap();
369 }
370 this->assignUniqueKeyToResource(key, buffer);
371 return buffer;
372}
373
cdalton397536c2016-03-25 12:15:03 -0700374const GrBuffer* GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700375 static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
376 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
377 static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 };
378
Chris Daltonff926502017-05-03 14:36:54 -0400379 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey);
bsalomoned0bcad2015-05-04 10:36:42 -0700380}
381
bsalomon6663acf2016-05-10 09:14:17 -0700382GrPath* GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700383 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700384 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700385}
386
387GrPathRange* GrResourceProvider::createPathRange(GrPathRange::PathGenerator* gen,
bsalomon6663acf2016-05-10 09:14:17 -0700388 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700389 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700390 return this->gpu()->pathRendering()->createPathRange(gen, style);
bsalomon706f08f2015-05-22 07:35:58 -0700391}
392
reeda9322c22016-04-12 06:47:05 -0700393GrPathRange* GrResourceProvider::createGlyphs(const SkTypeface* tf,
394 const SkScalerContextEffects& effects,
395 const SkDescriptor* desc,
bsalomon6663acf2016-05-10 09:14:17 -0700396 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700397
398 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700399 return this->gpu()->pathRendering()->createGlyphs(tf, effects, desc, style);
bsalomon706f08f2015-05-22 07:35:58 -0700400}
401
cdaltone2e71c22016-04-07 18:13:29 -0700402GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700403 GrAccessPattern accessPattern, uint32_t flags,
404 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700405 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700406 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700407 }
cdaltond37fe762016-04-21 07:41:50 -0700408 if (kDynamic_GrAccessPattern != accessPattern) {
409 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
410 }
csmartdalton485a1202016-07-13 10:16:32 -0700411 if (!(flags & kRequireGpuMemory_Flag) &&
412 this->gpu()->caps()->preferClientSideDynamicBuffers() &&
413 GrBufferTypeIsVertexOrIndex(intendedType) &&
414 kDynamic_GrAccessPattern == accessPattern) {
415 return GrBuffer::CreateCPUBacked(this->gpu(), size, intendedType, data);
416 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700417
cdaltond37fe762016-04-21 07:41:50 -0700418 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400419 static const size_t MIN_SIZE = 1 << 12;
420 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700421
cdaltond37fe762016-04-21 07:41:50 -0700422 GrScratchKey key;
csmartdalton485a1202016-07-13 10:16:32 -0700423 GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
cdaltond37fe762016-04-21 07:41:50 -0700424 uint32_t scratchFlags = 0;
425 if (flags & kNoPendingIO_Flag) {
426 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
427 } else {
428 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
429 }
430 GrBuffer* buffer = static_cast<GrBuffer*>(
431 this->cache()->findAndRefScratchResource(key, allocSize, scratchFlags));
432 if (!buffer) {
433 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
434 if (!buffer) {
435 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700436 }
437 }
cdaltond37fe762016-04-21 07:41:50 -0700438 if (data) {
439 buffer->updateData(data, size);
440 }
csmartdalton485a1202016-07-13 10:16:32 -0700441 SkASSERT(!buffer->isCPUBacked()); // We should only cache real VBOs.
cdaltond37fe762016-04-21 07:41:50 -0700442 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800443}
444
egdanielec00d942015-09-14 12:56:10 -0700445GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
446 SkASSERT(rt);
447 if (rt->renderTargetPriv().getStencilAttachment()) {
448 return rt->renderTargetPriv().getStencilAttachment();
449 }
450
451 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
452 GrUniqueKey sbKey;
453
454 int width = rt->width();
455 int height = rt->height();
456#if 0
457 if (this->caps()->oversizedStencilSupport()) {
458 width = SkNextPow2(width);
459 height = SkNextPow2(height);
460 }
461#endif
462 bool newStencil = false;
463 GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
464 rt->numStencilSamples(), &sbKey);
465 GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
466 this->findAndRefResourceByUniqueKey(sbKey));
467 if (!stencil) {
468 // Need to try and create a new stencil
469 stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
470 if (stencil) {
Robert Phillipsf7cf81a2017-03-02 10:23:52 -0500471 this->assignUniqueKeyToResource(sbKey, stencil);
egdanielec00d942015-09-14 12:56:10 -0700472 newStencil = true;
473 }
474 }
475 if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
476 if (newStencil) {
477 // Right now we're clearing the stencil attachment here after it is
bsalomon7ea33f52015-11-22 14:51:00 -0800478 // attached to a RT for the first time. When we start matching
egdanielec00d942015-09-14 12:56:10 -0700479 // stencil buffers with smaller color targets this will no longer
480 // be correct because it won't be guaranteed to clear the entire
481 // sb.
482 // We used to clear down in the GL subclass using a special purpose
483 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
484 // FBO status.
485 this->gpu()->clearStencil(rt);
486 }
487 }
488 }
489 return rt->renderTargetPriv().getStencilAttachment();
490}
491
bungeman6bd52842016-10-27 09:30:08 -0700492sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Greg Daniel7ef28f32017-04-20 16:41:55 +0000493 const GrBackendTexture& tex, GrSurfaceOrigin origin, int sampleCnt)
bungeman6bd52842016-10-27 09:30:08 -0700494{
ericrkf7b8b8a2016-02-24 14:49:51 -0800495 if (this->isAbandoned()) {
496 return nullptr;
497 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000498 return this->gpu()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800499}
Greg Danield85f97d2017-03-07 13:37:21 -0500500
501sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore() {
502 return fGpu->makeSemaphore();
503}
504
505void GrResourceProvider::takeOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
506 semaphore->resetGpu(fGpu);
507}
508
509void GrResourceProvider::releaseOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
510 semaphore->resetGpu(nullptr);
511}