blob: d2ec204d6c78cd5e48e6b11fa226fdaa25c3012b [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"
halcanary4dbbd042016-06-07 17:21:10 -070025#include "SkMathPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070026
27GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
28
Brian Osman32342f02017-03-04 08:12:46 -050029const int GrResourceProvider::kMinScratchTextureSize = 16;
30
31#define ASSERT_SINGLE_OWNER \
32 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
33
joshualitt6d0872d2016-01-11 08:27:48 -080034GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050035 : fCache(cache)
36 , fGpu(gpu)
37#ifdef SK_DEBUG
38 , fSingleOwner(owner)
39#endif
40 {
Robert Phillips26c90e02017-03-14 14:39:29 -040041 fCaps = sk_ref_sp(fGpu->caps());
42
bsalomoned0bcad2015-05-04 10:36:42 -070043 GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
44 fQuadIndexBufferKey = gQuadIndexBufferKey;
45}
46
Robert Phillipsf7a72612017-03-31 10:03:45 -040047bool GrResourceProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
Robert Phillipsb66b42f2017-03-14 08:53:02 -040048 return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
49}
Brian Osman32342f02017-03-04 08:12:46 -050050
Robert Phillipse78b7252017-04-06 07:59:41 -040051// MDB TODO: this should probably be a factory on GrSurfaceProxy
52sk_sp<GrTextureProxy> GrResourceProvider::createMipMappedTexture(
53 const GrSurfaceDesc& desc,
54 SkBudgeted budgeted,
55 const GrMipLevel* texels,
56 int mipLevelCount,
57 uint32_t flags,
Robert Phillipsa4c41b32017-03-15 13:02:45 -040058 SkDestinationSurfaceColorMode mipColorMode) {
Brian Osman32342f02017-03-04 08:12:46 -050059 ASSERT_SINGLE_OWNER
60
Robert Phillips1119dc32017-04-11 12:54:57 -040061 if (!mipLevelCount) {
62 if (texels) {
63 return nullptr;
64 }
65 return GrSurfaceProxy::MakeDeferred(this, desc, budgeted, nullptr, 0);
66 }
67
Brian Osman32342f02017-03-04 08:12:46 -050068 if (this->isAbandoned()) {
69 return nullptr;
70 }
Robert Phillips1119dc32017-04-11 12:54:57 -040071
Brian Osman32342f02017-03-04 08:12:46 -050072 for (int i = 0; i < mipLevelCount; ++i) {
73 if (!texels[i].fPixels) {
74 return nullptr;
75 }
76 }
77 if (mipLevelCount > 1 && GrPixelConfigIsSint(desc.fConfig)) {
78 return nullptr;
79 }
80 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
81 !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
82 return nullptr;
83 }
84 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
85 if (mipLevelCount < 2) {
86 flags |= kExact_Flag | kNoCreate_Flag;
Robert Phillipse78b7252017-04-06 07:59:41 -040087 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
88 if (tex) {
89 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(tex);
Robert Phillips1119dc32017-04-11 12:54:57 -040090
91 if (fGpu->getContext()->contextPriv().writeSurfacePixels(
Robert Phillipse78b7252017-04-06 07:59:41 -040092 proxy.get(), nullptr, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
93 nullptr, texels[0].fPixels, texels[0].fRowBytes)) {
Brian Osman32342f02017-03-04 08:12:46 -050094 if (SkBudgeted::kNo == budgeted) {
Robert Phillipse78b7252017-04-06 07:59:41 -040095 tex->resourcePriv().makeUnbudgeted();
Brian Osman32342f02017-03-04 08:12:46 -050096 }
Robert Phillipse78b7252017-04-06 07:59:41 -040097 tex->texturePriv().setMipColorMode(mipColorMode);
98 return proxy;
Brian Osman32342f02017-03-04 08:12:46 -050099 }
Brian Osman32342f02017-03-04 08:12:46 -0500100 }
101 }
102 }
103
104 SkTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
105 for (int i = 0; i < mipLevelCount; ++i) {
106 texelsShallowCopy.push_back(texels[i]);
107 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400108 sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texelsShallowCopy));
109 if (tex) {
110 tex->texturePriv().setMipColorMode(mipColorMode);
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400111 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400112
113 return GrSurfaceProxy::MakeWrapped(std::move(tex));
Brian Osman32342f02017-03-04 08:12:46 -0500114}
115
Robert Phillipse78b7252017-04-06 07:59:41 -0400116sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
117 uint32_t flags) {
118 ASSERT_SINGLE_OWNER
119
120 if (this->isAbandoned()) {
121 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500122 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400123
124 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
125 !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
126 return nullptr;
127 }
128
129 if (!GrPixelConfigIsCompressed(desc.fConfig)) {
130 flags |= kExact_Flag | kNoCreate_Flag;
131 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
132 if (tex) {
133 if (SkBudgeted::kNo == budgeted) {
134 tex->resourcePriv().makeUnbudgeted();
135 }
136 return tex;
137 }
138 }
139
140 sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted));
141 return tex;
Brian Osman32342f02017-03-04 08:12:46 -0500142}
143
144GrTexture* GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) {
145 ASSERT_SINGLE_OWNER
146 SkASSERT(0 == flags || kNoPendingIO_Flag == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500147
Brian Osman32342f02017-03-04 08:12:46 -0500148 if (this->isAbandoned()) {
149 return nullptr;
150 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400151
Brian Osman32342f02017-03-04 08:12:46 -0500152 // Currently we don't recycle compressed textures as scratch.
153 if (GrPixelConfigIsCompressed(desc.fConfig)) {
154 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500155 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400156
157 return this->refScratchTexture(desc, flags);
Brian Osman32342f02017-03-04 08:12:46 -0500158}
159
160GrTexture* GrResourceProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
161 uint32_t flags) {
162 ASSERT_SINGLE_OWNER
163 SkASSERT(!this->isAbandoned());
164 SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
165
166 SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
167
168 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
169 if (!(kExact_Flag & flags)) {
170 // bin by pow2 with a reasonable min
171 GrSurfaceDesc* wdesc = desc.writable();
172 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fWidth));
173 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fHeight));
174 }
175
176 GrScratchKey key;
177 GrTexturePriv::ComputeScratchKey(*desc, &key);
178 uint32_t scratchFlags = 0;
179 if (kNoPendingIO_Flag & flags) {
180 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
181 } else if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
182 // If it is not a render target then it will most likely be populated by
183 // writePixels() which will trigger a flush if the texture has pending IO.
184 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
185 }
186 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
187 GrSurface::WorstCaseSize(*desc),
188 scratchFlags);
189 if (resource) {
190 GrSurface* surface = static_cast<GrSurface*>(resource);
Brian Osman32342f02017-03-04 08:12:46 -0500191 return surface->asTexture();
192 }
193 }
194
195 if (!(kNoCreate_Flag & flags)) {
196 return fGpu->createTexture(*desc, SkBudgeted::kYes);
197 }
198
199 return nullptr;
200}
201
202sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
203 GrWrapOwnership ownership) {
204 ASSERT_SINGLE_OWNER
205 if (this->isAbandoned()) {
206 return nullptr;
207 }
208 return fGpu->wrapBackendTexture(desc, ownership);
209}
210
211sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
212 const GrBackendRenderTargetDesc& desc)
213{
214 ASSERT_SINGLE_OWNER
Brian Osman0b791f52017-03-10 08:30:22 -0500215 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc);
Brian Osman32342f02017-03-04 08:12:46 -0500216}
217
218void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
219 GrGpuResource* resource) {
220 ASSERT_SINGLE_OWNER
221 if (this->isAbandoned() || !resource) {
222 return;
223 }
224 resource->resourcePriv().setUniqueKey(key);
225}
226
227GrGpuResource* GrResourceProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
228 ASSERT_SINGLE_OWNER
229 return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
230}
231
232GrTexture* GrResourceProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
233 ASSERT_SINGLE_OWNER
234 GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
235 if (resource) {
236 GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
237 SkASSERT(texture);
238 return texture;
239 }
240 return NULL;
241}
242
Robert Phillipsd3749482017-03-14 09:17:43 -0400243// MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs
244void GrResourceProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
245 ASSERT_SINGLE_OWNER
246 SkASSERT(key.isValid());
247 if (this->isAbandoned() || !proxy) {
248 return;
249 }
250
251 GrTexture* texture = proxy->instantiate(this);
252 if (!texture) {
253 return;
254 }
255
256 this->assignUniqueKeyToResource(key, texture);
257}
258
259// MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs
260sk_sp<GrTextureProxy> GrResourceProvider::findProxyByUniqueKey(const GrUniqueKey& key) {
261 ASSERT_SINGLE_OWNER
262
263 sk_sp<GrTexture> texture(this->findAndRefTextureByUniqueKey(key));
264 if (!texture) {
265 return nullptr;
266 }
267
268 return GrSurfaceProxy::MakeWrapped(std::move(texture));
269}
270
cdalton397536c2016-03-25 12:15:03 -0700271const GrBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern,
272 int patternSize,
273 int reps,
274 int vertCount,
275 const GrUniqueKey& key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700276 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
277
Brian Salomon09d994e2016-12-21 11:14:46 -0500278 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
cdaltone2e71c22016-04-07 18:13:29 -0700279 GrBuffer* buffer = this->createBuffer(bufferSize, kIndex_GrBufferType, kStatic_GrAccessPattern,
cdalton397536c2016-03-25 12:15:03 -0700280 kNoPendingIO_Flag);
bsalomoned0bcad2015-05-04 10:36:42 -0700281 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700282 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700283 }
284 uint16_t* data = (uint16_t*) buffer->map();
halcanary96fcdcc2015-08-27 07:41:13 -0700285 bool useTempData = (nullptr == data);
bsalomoned0bcad2015-05-04 10:36:42 -0700286 if (useTempData) {
halcanary385fe4d2015-08-26 13:07:48 -0700287 data = new uint16_t[reps * patternSize];
bsalomoned0bcad2015-05-04 10:36:42 -0700288 }
289 for (int i = 0; i < reps; ++i) {
290 int baseIdx = i * patternSize;
291 uint16_t baseVert = (uint16_t)(i * vertCount);
292 for (int j = 0; j < patternSize; ++j) {
293 data[baseIdx+j] = baseVert + pattern[j];
294 }
295 }
296 if (useTempData) {
297 if (!buffer->updateData(data, bufferSize)) {
298 buffer->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700299 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700300 }
halcanary385fe4d2015-08-26 13:07:48 -0700301 delete[] data;
bsalomoned0bcad2015-05-04 10:36:42 -0700302 } else {
303 buffer->unmap();
304 }
305 this->assignUniqueKeyToResource(key, buffer);
306 return buffer;
307}
308
cdalton397536c2016-03-25 12:15:03 -0700309const GrBuffer* GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700310 static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
311 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
312 static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 };
313
314 return this->createInstancedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey);
315}
316
bsalomon6663acf2016-05-10 09:14:17 -0700317GrPath* GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700318 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700319 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700320}
321
322GrPathRange* GrResourceProvider::createPathRange(GrPathRange::PathGenerator* gen,
bsalomon6663acf2016-05-10 09:14:17 -0700323 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700324 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700325 return this->gpu()->pathRendering()->createPathRange(gen, style);
bsalomon706f08f2015-05-22 07:35:58 -0700326}
327
reeda9322c22016-04-12 06:47:05 -0700328GrPathRange* GrResourceProvider::createGlyphs(const SkTypeface* tf,
329 const SkScalerContextEffects& effects,
330 const SkDescriptor* desc,
bsalomon6663acf2016-05-10 09:14:17 -0700331 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700332
333 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700334 return this->gpu()->pathRendering()->createGlyphs(tf, effects, desc, style);
bsalomon706f08f2015-05-22 07:35:58 -0700335}
336
cdaltone2e71c22016-04-07 18:13:29 -0700337GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700338 GrAccessPattern accessPattern, uint32_t flags,
339 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700340 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700341 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700342 }
cdaltond37fe762016-04-21 07:41:50 -0700343 if (kDynamic_GrAccessPattern != accessPattern) {
344 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
345 }
csmartdalton485a1202016-07-13 10:16:32 -0700346 if (!(flags & kRequireGpuMemory_Flag) &&
347 this->gpu()->caps()->preferClientSideDynamicBuffers() &&
348 GrBufferTypeIsVertexOrIndex(intendedType) &&
349 kDynamic_GrAccessPattern == accessPattern) {
350 return GrBuffer::CreateCPUBacked(this->gpu(), size, intendedType, data);
351 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700352
cdaltond37fe762016-04-21 07:41:50 -0700353 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400354 static const size_t MIN_SIZE = 1 << 12;
355 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700356
cdaltond37fe762016-04-21 07:41:50 -0700357 GrScratchKey key;
csmartdalton485a1202016-07-13 10:16:32 -0700358 GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
cdaltond37fe762016-04-21 07:41:50 -0700359 uint32_t scratchFlags = 0;
360 if (flags & kNoPendingIO_Flag) {
361 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
362 } else {
363 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
364 }
365 GrBuffer* buffer = static_cast<GrBuffer*>(
366 this->cache()->findAndRefScratchResource(key, allocSize, scratchFlags));
367 if (!buffer) {
368 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
369 if (!buffer) {
370 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700371 }
372 }
cdaltond37fe762016-04-21 07:41:50 -0700373 if (data) {
374 buffer->updateData(data, size);
375 }
csmartdalton485a1202016-07-13 10:16:32 -0700376 SkASSERT(!buffer->isCPUBacked()); // We should only cache real VBOs.
cdaltond37fe762016-04-21 07:41:50 -0700377 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800378}
379
egdanielec00d942015-09-14 12:56:10 -0700380GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
381 SkASSERT(rt);
382 if (rt->renderTargetPriv().getStencilAttachment()) {
383 return rt->renderTargetPriv().getStencilAttachment();
384 }
385
386 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
387 GrUniqueKey sbKey;
388
389 int width = rt->width();
390 int height = rt->height();
391#if 0
392 if (this->caps()->oversizedStencilSupport()) {
393 width = SkNextPow2(width);
394 height = SkNextPow2(height);
395 }
396#endif
397 bool newStencil = false;
398 GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
399 rt->numStencilSamples(), &sbKey);
400 GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
401 this->findAndRefResourceByUniqueKey(sbKey));
402 if (!stencil) {
403 // Need to try and create a new stencil
404 stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
405 if (stencil) {
Robert Phillipsf7cf81a2017-03-02 10:23:52 -0500406 this->assignUniqueKeyToResource(sbKey, stencil);
egdanielec00d942015-09-14 12:56:10 -0700407 newStencil = true;
408 }
409 }
410 if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
411 if (newStencil) {
412 // Right now we're clearing the stencil attachment here after it is
bsalomon7ea33f52015-11-22 14:51:00 -0800413 // attached to a RT for the first time. When we start matching
egdanielec00d942015-09-14 12:56:10 -0700414 // stencil buffers with smaller color targets this will no longer
415 // be correct because it won't be guaranteed to clear the entire
416 // sb.
417 // We used to clear down in the GL subclass using a special purpose
418 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
419 // FBO status.
420 this->gpu()->clearStencil(rt);
421 }
422 }
423 }
424 return rt->renderTargetPriv().getStencilAttachment();
425}
426
bungeman6bd52842016-10-27 09:30:08 -0700427sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
428 const GrBackendTextureDesc& desc)
429{
ericrkf7b8b8a2016-02-24 14:49:51 -0800430 if (this->isAbandoned()) {
431 return nullptr;
432 }
kkinnunen49c4c222016-04-01 04:50:37 -0700433 return this->gpu()->wrapBackendTextureAsRenderTarget(desc);
ericrkf7b8b8a2016-02-24 14:49:51 -0800434}
Greg Danield85f97d2017-03-07 13:37:21 -0500435
436sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore() {
437 return fGpu->makeSemaphore();
438}
439
440void GrResourceProvider::takeOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
441 semaphore->resetGpu(fGpu);
442}
443
444void GrResourceProvider::releaseOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
445 semaphore->resetGpu(nullptr);
446}