blob: 0076a1a82d12bb9566058dcf7747746972b4fd5b [file] [log] [blame]
Robert Phillips1afd4cd2018-01-08 13:40:32 -05001/*
2 * Copyright 2018 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 "GrProxyProvider.h"
9
10#include "GrCaps.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050011#include "GrRenderTarget.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050012#include "GrResourceKey.h"
13#include "GrResourceProvider.h"
14#include "GrSurfaceProxy.h"
15#include "GrSurfaceProxyPriv.h"
16#include "GrTexture.h"
17#include "GrTextureProxyCacheAccess.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050018#include "GrTextureRenderTargetProxy.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050019#include "../private/GrSingleOwner.h"
Greg Daniela4ead652018-02-07 10:21:48 -050020#include "SkBitmap.h"
Greg Daniel9d86f1d2018-01-29 09:33:59 -050021#include "SkGr.h"
22#include "SkImage.h"
23#include "SkImage_Base.h"
Greg Daniela4ead652018-02-07 10:21:48 -050024#include "SkImageInfoPriv.h"
25#include "SkImagePriv.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050026#include "SkMipMap.h"
Greg Daniela4ead652018-02-07 10:21:48 -050027#include "SkTraceEvent.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050028
29#define ASSERT_SINGLE_OWNER \
30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
31
32GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider,
33 GrResourceCache* resourceCache,
34 sk_sp<const GrCaps> caps,
35 GrSingleOwner* owner)
36 : fResourceProvider(resourceProvider)
37 , fResourceCache(resourceCache)
Robert Phillips4d120512018-01-19 13:22:07 -050038 , fAbandoned(false)
Robert Phillips1afd4cd2018-01-08 13:40:32 -050039 , fCaps(caps)
40#ifdef SK_DEBUG
41 , fSingleOwner(owner)
42#endif
43{
44
45}
46
47GrProxyProvider::~GrProxyProvider() {
48 SkASSERT(!fUniquelyKeyedProxies.count());
49}
50
Robert Phillipsadbe1322018-01-17 13:35:46 -050051bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050052 ASSERT_SINGLE_OWNER
53 SkASSERT(key.isValid());
54 if (this->isAbandoned() || !proxy) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050055 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050056 }
57
58 // If there is already a GrResource with this key then the caller has violated the normal
59 // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
60 // if it already existed in the cache).
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -050061 SkASSERT(!fResourceCache || !fResourceCache->findAndRefUniqueResource(key));
Robert Phillips1afd4cd2018-01-08 13:40:32 -050062
63 // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
64 // resources are a special case: the unique keys give us a weak ref so that we can reuse the
65 // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
66 // it will always be released - it is never converted to a scratch resource.
67 if (SkBudgeted::kNo == proxy->isBudgeted() &&
68 (!proxy->priv().isInstantiated() ||
69 !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050070 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050071 }
72
73 SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key
74
75 proxy->cacheAccess().setUniqueKey(this, key);
76 SkASSERT(proxy->getUniqueKey() == key);
77 fUniquelyKeyedProxies.add(proxy);
Robert Phillipsadbe1322018-01-17 13:35:46 -050078 return true;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050079}
80
81void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
82 SkASSERT(surf->getUniqueKey().isValid());
83 proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
84 SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
85 // multiple proxies can't get the same key
86 SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
87 fUniquelyKeyedProxies.add(proxy);
88}
89
90void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
91 ASSERT_SINGLE_OWNER
92 if (this->isAbandoned() || !proxy) {
93 return;
94 }
95 this->processInvalidProxyUniqueKey(key, proxy, true);
96}
97
98sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
99 GrSurfaceOrigin origin) {
100 ASSERT_SINGLE_OWNER
101
102 if (this->isAbandoned()) {
103 return nullptr;
104 }
105
106 sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
107 if (result) {
108 SkASSERT(result->origin() == origin);
109 }
110 return result;
111}
112
Robert Phillipsadbe1322018-01-17 13:35:46 -0500113sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin) {
114#ifdef SK_DEBUG
115 if (tex->getUniqueKey().isValid()) {
116 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
117 }
118#endif
119
120 if (tex->asRenderTarget()) {
121 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin));
122 } else {
123 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin));
124 }
125}
126
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500127sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
128 GrSurfaceOrigin origin) {
129 ASSERT_SINGLE_OWNER
130
131 if (this->isAbandoned()) {
132 return nullptr;
133 }
134
135 sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
136 if (result) {
137 return result;
138 }
139
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500140 if (!fResourceCache) {
141 return nullptr;
142 }
143
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500144 GrGpuResource* resource = fResourceCache->findAndRefUniqueResource(key);
145 if (!resource) {
146 return nullptr;
147 }
148
149 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
150 SkASSERT(texture);
151
Robert Phillipsadbe1322018-01-17 13:35:46 -0500152 result = this->createWrapped(std::move(texture), origin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500153 SkASSERT(result->getUniqueKey() == key);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500154 // createWrapped should've added this for us
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500155 SkASSERT(fUniquelyKeyedProxies.find(key));
156 return result;
157}
158
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500159sk_sp<GrTextureProxy> GrProxyProvider::createInstantiatedProxy(const GrSurfaceDesc& desc,
160 SkBackingFit fit,
161 SkBudgeted budgeted,
162 uint32_t flags) {
163 sk_sp<GrTexture> tex;
164
165 if (SkBackingFit::kApprox == fit) {
166 tex = fResourceProvider->createApproxTexture(desc, flags);
167 } else {
168 tex = fResourceProvider->createTexture(desc, budgeted, flags);
169 }
170 if (!tex) {
171 return nullptr;
172 }
173
Robert Phillipsadbe1322018-01-17 13:35:46 -0500174 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500175}
176
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500177sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(const GrSurfaceDesc& desc,
178 SkBudgeted budgeted,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500179 const void* srcData, size_t rowBytes) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500180 ASSERT_SINGLE_OWNER
181
Robert Phillips579f0942018-01-08 14:53:35 -0500182 if (this->isAbandoned()) {
183 return nullptr;
184 }
185
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500186 if (srcData) {
187 GrMipLevel mipLevel = { srcData, rowBytes };
188
Greg Danielfb3abcd2018-02-02 15:48:33 -0500189 sk_sp<GrTexture> tex = fResourceProvider->createTexture(desc, budgeted,
190 SkBackingFit::kExact, mipLevel);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500191 if (!tex) {
192 return nullptr;
193 }
194
Robert Phillipsadbe1322018-01-17 13:35:46 -0500195 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500196 }
197
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500198 return this->createProxy(desc, SkBackingFit::kExact, budgeted);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500199}
200
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500201sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
202 GrSurfaceFlags flags,
203 GrSurfaceOrigin origin,
204 int sampleCnt,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500205 SkBudgeted budgeted,
206 SkBackingFit fit) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500207 ASSERT_SINGLE_OWNER
208 SkASSERT(srcImage);
209
210 if (this->isAbandoned()) {
211 return nullptr;
212 }
213
214 GrSurfaceDesc desc;
215 desc.fWidth = srcImage->width();
216 desc.fHeight = srcImage->height();
217 desc.fFlags = flags;
218 desc.fOrigin = origin;
219 desc.fSampleCnt = sampleCnt;
220 desc.fConfig = SkImageInfo2GrPixelConfig(as_IB(srcImage)->onImageInfo(), *this->caps());
221
222 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Greg Danielfb3abcd2018-02-02 15:48:33 -0500223 [desc, budgeted, srcImage, fit]
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500224 (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
225 if (!resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500226 // Nothing to clean up here. Once the proxy (and thus lambda) is deleted the ref
227 // on srcImage will be released.
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500228 return sk_sp<GrTexture>();
229 }
230 SkPixmap pixMap;
231 SkAssertResult(srcImage->peekPixels(&pixMap));
232 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
233
Greg Danielfb3abcd2018-02-02 15:48:33 -0500234 return resourceProvider->createTexture(desc, budgeted, fit, mipLevel);
235 }, desc, GrMipMapped::kNo, fit, budgeted);
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500236
237 if (fResourceProvider) {
238 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
239 // we're better off instantiating the proxy immediately here.
240 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
241 return nullptr;
242 }
243 }
244 return proxy;
245}
246
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500247sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500248 const GrSurfaceDesc& desc, SkBudgeted budgeted,
249 const GrMipLevel texels[], int mipLevelCount,
250 SkDestinationSurfaceColorMode mipColorMode) {
Robert Phillips579f0942018-01-08 14:53:35 -0500251 ASSERT_SINGLE_OWNER
252
253 if (this->isAbandoned()) {
254 return nullptr;
255 }
256
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500257 if (!mipLevelCount) {
258 if (texels) {
259 return nullptr;
260 }
261 return this->createProxy(desc, SkBackingFit::kExact, budgeted);
262 }
263 if (!texels) {
264 return nullptr;
265 }
266
267 if (1 == mipLevelCount) {
268 return this->createTextureProxy(desc, budgeted, texels[0].fPixels, texels[0].fRowBytes);
269 }
270
271#ifdef SK_DEBUG
272 // There are only three states we want to be in when uploading data to a mipped surface.
273 // 1) We have data to upload to all layers
274 // 2) We are not uploading data to any layers
275 // 3) We are only uploading data to the base layer
276 // We check here to make sure we do not have any other state.
277 bool firstLevelHasData = SkToBool(texels[0].fPixels);
278 bool allOtherLevelsHaveData = true, allOtherLevelsLackData = true;
279 for (int i = 1; i < mipLevelCount; ++i) {
280 if (texels[i].fPixels) {
281 allOtherLevelsLackData = false;
282 } else {
283 allOtherLevelsHaveData = false;
284 }
285 }
286 SkASSERT((firstLevelHasData && allOtherLevelsHaveData) || allOtherLevelsLackData);
287#endif
288
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500289 sk_sp<GrTexture> tex(fResourceProvider->createTexture(desc, budgeted,
290 texels, mipLevelCount,
291 mipColorMode));
292 if (!tex) {
293 return nullptr;
294 }
295
Robert Phillipsadbe1322018-01-17 13:35:46 -0500296 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500297}
298
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500299sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& desc,
300 SkBudgeted budgeted) {
301 // SkMipMap doesn't include the base level in the level count so we have to add 1
302 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
303
304 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
305
306 // We don't want to upload any texel data
307 for (int i = 0; i < mipCount; i++) {
308 texels[i].fPixels = nullptr;
309 texels[i].fRowBytes = 0;
310 }
311
312 return this->createMipMapProxy(desc, budgeted, texels.get(), mipCount,
313 SkDestinationSurfaceColorMode::kLegacy);
314}
315
Greg Daniela4ead652018-02-07 10:21:48 -0500316sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxyFromBitmap(const SkBitmap& bitmap,
317 SkColorSpace* dstColorSpace) {
318 SkDestinationSurfaceColorMode mipColorMode = dstColorSpace
319 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
320 : SkDestinationSurfaceColorMode::kLegacy;
321
322 if (!SkImageInfoIsValid(bitmap.info(), mipColorMode)) {
323 return nullptr;
324 }
325
326 SkPixmap pixmap;
327 if (!bitmap.peekPixels(&pixmap)) {
328 return nullptr;
329 }
330
331 ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height());
332 sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, mipColorMode, nullptr));
333 if (!mipmaps) {
334 return nullptr;
335 }
336
337 if (mipmaps->countLevels() < 0) {
338 return nullptr;
339 }
340
341 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
342 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
343 // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
Greg Daniel7e1912a2018-02-08 09:15:33 -0500344 SkCopyPixelsMode copyMode = this->mutableBitmapsNeedCopy() ? kIfMutable_SkCopyPixelsMode
345 : kNever_SkCopyPixelsMode;
Greg Daniela4ead652018-02-07 10:21:48 -0500346 sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
347
348 if (!baseLevel) {
349 return nullptr;
350 }
351
352 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *this->caps());
353
354 if (0 == mipmaps->countLevels()) {
355 return this->createTextureProxy(baseLevel, kNone_GrSurfaceFlags, kTopLeft_GrSurfaceOrigin,
356 1, SkBudgeted::kYes, SkBackingFit::kExact);
357
358 }
359
360 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
361 [desc, baseLevel, mipmaps, mipColorMode]
362 (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
363 if (!resourceProvider) {
364 return sk_sp<GrTexture>();
365 }
366
367 const int mipLevelCount = mipmaps->countLevels() + 1;
368 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
369
370 SkPixmap pixmap;
371 SkAssertResult(baseLevel->peekPixels(&pixmap));
372
373 // DDL TODO: Instead of copying all this info into GrMipLevels we should just plumb
374 // the use of SkMipMap down through Ganesh.
375 texels[0].fPixels = pixmap.addr();
376 texels[0].fRowBytes = pixmap.rowBytes();
377
378 for (int i = 1; i < mipLevelCount; ++i) {
379 SkMipMap::Level generatedMipLevel;
380 mipmaps->getLevel(i - 1, &generatedMipLevel);
381 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
382 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
383 SkASSERT(texels[i].fPixels);
384 }
385
386 return resourceProvider->createTexture(desc, SkBudgeted::kYes, texels.get(),
387 mipLevelCount, mipColorMode);
388 }, desc, GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes);
389
390 if (fResourceProvider) {
391 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
392 // we're better off instantiating the proxy immediately here.
393 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
394 return nullptr;
395 }
396 }
397 return proxy;
398}
399
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500400sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
401 SkBackingFit fit,
402 SkBudgeted budgeted,
403 uint32_t flags) {
404 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
405
Brian Salomonbdecacf2018-02-02 20:32:49 -0500406 if (!this->caps()->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500407 return nullptr;
408 }
Brian Salomon3a2cc2c2018-02-03 00:25:12 +0000409 GrSurfaceDesc copyDesc = desc;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500410 if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
411 copyDesc.fSampleCnt =
412 this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
413 }
Brian Salomon3a2cc2c2018-02-03 00:25:12 +0000414
Brian Salomonbdecacf2018-02-02 20:32:49 -0500415 if (copyDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500416 // We know anything we instantiate later from this deferred path will be
417 // both texturable and renderable
Brian Salomonbdecacf2018-02-02 20:32:49 -0500418 return sk_sp<GrTextureProxy>(
419 new GrTextureRenderTargetProxy(*this->caps(), copyDesc, fit, budgeted, flags));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500420 }
421
422 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500423}
424
Robert Phillipsadbe1322018-01-17 13:35:46 -0500425sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(
426 const GrBackendTexture& backendTex,
427 GrSurfaceOrigin origin,
428 GrWrapOwnership ownership,
429 ReleaseProc releaseProc,
430 ReleaseContext releaseCtx) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500431 if (this->isAbandoned()) {
432 return nullptr;
433 }
434
Greg Danielf2336e42018-01-23 16:38:14 -0500435 GrSurfaceDesc desc;
436 desc.fOrigin = origin;
437 desc.fWidth = backendTex.width();
438 desc.fHeight = backendTex.height();
439 desc.fConfig = backendTex.config();
440 GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
Robert Phillipsadbe1322018-01-17 13:35:46 -0500441
Greg Daniel6a0176b2018-01-30 09:28:44 -0500442 sk_sp<GrReleaseProcHelper> releaseHelper;
443 if (releaseProc) {
444 releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
445 }
446
Greg Danielf2336e42018-01-23 16:38:14 -0500447 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Greg Daniel6a0176b2018-01-30 09:28:44 -0500448 [backendTex, ownership, releaseHelper]
Greg Danielf2336e42018-01-23 16:38:14 -0500449 (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
450 if (!resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500451 // If this had a releaseHelper it will get unrefed when we delete this lambda
452 // and will call the release proc so that the client knows they can free the
453 // underlying backend object.
Greg Danielf2336e42018-01-23 16:38:14 -0500454 return sk_sp<GrTexture>();
455 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500456
Greg Danielf2336e42018-01-23 16:38:14 -0500457 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex,
458 ownership);
459 if (!tex) {
460 return sk_sp<GrTexture>();
461 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500462 if (releaseHelper) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500463 // This gives the texture a ref on the releaseHelper
464 tex->setRelease(releaseHelper);
Greg Danielf2336e42018-01-23 16:38:14 -0500465 }
466 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
467 // Make sure we match how we created the proxy with SkBudgeted::kNo
468 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
469
470 return tex;
471 }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
472
473 if (fResourceProvider) {
474 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
475 // we're better off instantiating the proxy immediately here.
Greg Danielbddcc952018-01-24 13:22:24 -0500476 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
477 return nullptr;
478 }
Greg Danielf2336e42018-01-23 16:38:14 -0500479 }
480 return proxy;
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500481}
482
483sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(const GrBackendTexture& tex,
484 GrSurfaceOrigin origin,
485 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500486 if (this->isAbandoned()) {
487 return nullptr;
488 }
489
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500490 sk_sp<GrTexture> texture(fResourceProvider->wrapRenderableBackendTexture(tex, sampleCnt));
491 if (!texture) {
492 return nullptr;
493 }
494 SkASSERT(texture->asRenderTarget()); // A GrTextureRenderTarget
495
Robert Phillipsadbe1322018-01-17 13:35:46 -0500496 return this->createWrapped(std::move(texture), origin);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500497}
498
499sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(
500 const GrBackendRenderTarget& backendRT,
501 GrSurfaceOrigin origin) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500502 if (this->isAbandoned()) {
503 return nullptr;
504 }
505
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500506 sk_sp<GrRenderTarget> rt(fResourceProvider->wrapBackendRenderTarget(backendRT));
507 if (!rt) {
508 return nullptr;
509 }
510 SkASSERT(!rt->asTexture()); // Strictly a GrRenderTarget
511 SkASSERT(!rt->getUniqueKey().isValid());
512
513 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
514}
515
516sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(const GrBackendTexture& tex,
517 GrSurfaceOrigin origin,
518 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500519 if (this->isAbandoned()) {
520 return nullptr;
521 }
522
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500523 sk_sp<GrRenderTarget> rt(fResourceProvider->wrapBackendTextureAsRenderTarget(tex, sampleCnt));
524 if (!rt) {
525 return nullptr;
526 }
527 SkASSERT(!rt->asTexture()); // Strictly a GrRenderTarget
528 SkASSERT(!rt->getUniqueKey().isValid());
529
530 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
531}
532
Robert Phillips777707b2018-01-17 11:40:14 -0500533sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
534 const GrSurfaceDesc& desc,
535 GrMipMapped mipMapped,
536 SkBackingFit fit, SkBudgeted budgeted) {
537 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
538 (desc.fWidth > 0 && desc.fHeight > 0));
539 uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
540 return sk_sp<GrTextureProxy>(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags) ?
541 new GrTextureRenderTargetProxy(std::move(callback), desc,
542 mipMapped, fit, budgeted, flags) :
543 new GrTextureProxy(std::move(callback), desc, mipMapped, fit,
544 budgeted, flags));
Robert Phillips777707b2018-01-17 11:40:14 -0500545}
546
Robert Phillipse8fabb22018-02-04 14:33:21 -0500547sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
548 LazyInstantiateCallback&& callback,
549 const GrSurfaceDesc& desc,
550 Textureable textureable,
551 GrMipMapped mipMapped,
552 SkBackingFit fit, SkBudgeted budgeted) {
553 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
554 (desc.fWidth > 0 && desc.fHeight > 0));
555 uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
556 if (Textureable::kYes == textureable) {
557 return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(std::move(callback), desc,
558 mipMapped, fit, budgeted,
559 flags));
560 }
561
562 return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(callback), desc,
563 fit, budgeted, flags));
564}
565
Robert Phillips777707b2018-01-17 11:40:14 -0500566sk_sp<GrTextureProxy> GrProxyProvider::createFullyLazyProxy(LazyInstantiateCallback&& callback,
567 Renderable renderable,
568 GrPixelConfig config) {
569 GrSurfaceDesc desc;
570 if (Renderable::kYes == renderable) {
571 desc.fFlags = kRenderTarget_GrSurfaceFlag;
572 }
573 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
574 desc.fWidth = -1;
575 desc.fHeight = -1;
576 desc.fConfig = config;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500577 desc.fSampleCnt = 1;
Robert Phillips777707b2018-01-17 11:40:14 -0500578
579 return this->createLazyProxy(std::move(callback), desc, GrMipMapped::kNo,
580 SkBackingFit::kApprox, SkBudgeted::kYes);
581
582}
583
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500584bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
585 return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
586}
587
588void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
589 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
590 // will not be in 'fUniquelyKeyedProxies'.
591 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
592 if (proxy) {
593 this->processInvalidProxyUniqueKey(key, proxy, false);
594 }
595}
596
597void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
598 bool invalidateSurface) {
599 SkASSERT(proxy);
600 SkASSERT(proxy->getUniqueKey().isValid());
601 SkASSERT(proxy->getUniqueKey() == key);
602
603 fUniquelyKeyedProxies.remove(key);
604 proxy->cacheAccess().clearUniqueKey();
605
606 if (invalidateSurface && proxy->priv().isInstantiated()) {
607 GrSurface* surface = proxy->priv().peekSurface();
608 if (surface) {
609 surface->resourcePriv().removeUniqueKey();
610 }
611 }
612}
613
614void GrProxyProvider::removeAllUniqueKeys() {
615 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
616 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
617 GrTextureProxy& tmp = *iter;
618
619 this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
620 }
621 SkASSERT(!fUniquelyKeyedProxies.count());
622}