1 /*
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 "src/gpu/GrProxyProvider.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkImage.h"
12 #include "include/gpu/GrContext.h"
13 #include "include/gpu/GrTexture.h"
14 #include "include/private/GrImageContext.h"
15 #include "include/private/GrResourceKey.h"
16 #include "include/private/GrSingleOwner.h"
17 #include "include/private/SkImageInfoPriv.h"
18 #include "src/core/SkAutoPixmapStorage.h"
19 #include "src/core/SkImagePriv.h"
20 #include "src/core/SkMipMap.h"
21 #include "src/core/SkTraceEvent.h"
22 #include "src/gpu/GrCaps.h"
23 #include "src/gpu/GrContextPriv.h"
24 #include "src/gpu/GrImageContextPriv.h"
25 #include "src/gpu/GrRenderTarget.h"
26 #include "src/gpu/GrResourceProvider.h"
27 #include "src/gpu/GrSurfaceProxy.h"
28 #include "src/gpu/GrSurfaceProxyPriv.h"
29 #include "src/gpu/GrTextureProxyCacheAccess.h"
30 #include "src/gpu/GrTextureRenderTargetProxy.h"
31 #include "src/gpu/SkGr.h"
32 #include "src/image/SkImage_Base.h"
33
34 #define ASSERT_SINGLE_OWNER \
35 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());)
36
GrProxyProvider(GrImageContext * imageContext)37 GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
38
~GrProxyProvider()39 GrProxyProvider::~GrProxyProvider() {
40 if (this->renderingDirectly()) {
41 // In DDL-mode a proxy provider can still have extant uniquely keyed proxies (since
42 // they need their unique keys to, potentially, find a cached resource when the
43 // DDL is played) but, in non-DDL-mode they should all have been cleaned up by this point.
44 SkASSERT(!fUniquelyKeyedProxies.count());
45 }
46 }
47
assignUniqueKeyToProxy(const GrUniqueKey & key,GrTextureProxy * proxy)48 bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
49 ASSERT_SINGLE_OWNER
50 SkASSERT(key.isValid());
51 if (this->isAbandoned() || !proxy) {
52 return false;
53 }
54
55 #ifdef SK_DEBUG
56 {
57 GrContext* direct = fImageContext->priv().asDirectContext();
58 if (direct) {
59 GrResourceCache* resourceCache = direct->priv().getResourceCache();
60 // If there is already a GrResource with this key then the caller has violated the
61 // normal usage pattern of uniquely keyed resources (e.g., they have created one w/o
62 // first seeing if it already existed in the cache).
63 SkASSERT(!resourceCache->findAndRefUniqueResource(key));
64 }
65 }
66 #endif
67
68 SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key
69
70 proxy->cacheAccess().setUniqueKey(this, key);
71 SkASSERT(proxy->getUniqueKey() == key);
72 fUniquelyKeyedProxies.add(proxy);
73 return true;
74 }
75
76 template <class T>
assignTagToProxy(sk_sp<T> proxy)77 sk_sp<T> GrProxyProvider::assignTagToProxy(sk_sp<T> proxy) {
78 if (!proxy) {
79 return proxy;
80 }
81 GrContext* direct = fImageContext->priv().asDirectContext();
82 if (direct) {
83 proxy->setGrProxyTag(direct->getCurrentGrResourceTag());
84 }
85 return proxy;
86 }
87
adoptUniqueKeyFromSurface(GrTextureProxy * proxy,const GrSurface * surf)88 void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
89 SkASSERT(surf->getUniqueKey().isValid());
90 proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
91 SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
92 // multiple proxies can't get the same key
93 SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
94 fUniquelyKeyedProxies.add(proxy);
95 }
96
removeUniqueKeyFromProxy(GrTextureProxy * proxy)97 void GrProxyProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) {
98 ASSERT_SINGLE_OWNER
99 SkASSERT(proxy);
100 SkASSERT(proxy->getUniqueKey().isValid());
101
102 if (this->isAbandoned()) {
103 return;
104 }
105
106 this->processInvalidUniqueKey(proxy->getUniqueKey(), proxy, InvalidateGPUResource::kYes);
107 }
108
findProxyByUniqueKey(const GrUniqueKey & key,GrSurfaceOrigin origin)109 sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
110 GrSurfaceOrigin origin) {
111 ASSERT_SINGLE_OWNER
112
113 if (this->isAbandoned()) {
114 return nullptr;
115 }
116
117 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
118 if (proxy) {
119 SkASSERT(proxy->getProxyRefCnt() >= 1);
120 SkASSERT(proxy->origin() == origin);
121 return sk_ref_sp(proxy);
122 }
123 return nullptr;
124 }
125
126 ///////////////////////////////////////////////////////////////////////////////
127
128 #if GR_TEST_UTILS
testingOnly_createInstantiatedProxy(const SkISize & size,GrColorType colorType,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)129 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
130 const SkISize& size,
131 GrColorType colorType,
132 const GrBackendFormat& format,
133 GrRenderable renderable,
134 int renderTargetSampleCnt,
135 GrSurfaceOrigin origin,
136 SkBackingFit fit,
137 SkBudgeted budgeted,
138 GrProtected isProtected) {
139 GrContext* direct = fImageContext->priv().asDirectContext();
140 if (!direct) {
141 return nullptr;
142 }
143
144 if (this->caps()->isFormatCompressed(format)) {
145 // TODO: Allow this to go to GrResourceProvider::createCompressedTexture() once we no longer
146 // rely on GrColorType to get to GrPixelConfig. Currently this will cause
147 // makeConfigSpecific() to assert because GrColorTypeToPixelConfig() never returns a
148 // compressed GrPixelConfig.
149 return nullptr;
150 }
151 GrSurfaceDesc desc;
152 desc.fConfig = GrColorTypeToPixelConfig(colorType);
153 desc.fConfig = this->caps()->makeConfigSpecific(desc.fConfig, format);
154 desc.fWidth = size.width();
155 desc.fHeight = size.height();
156
157 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
158 sk_sp<GrTexture> tex;
159
160 if (SkBackingFit::kApprox == fit) {
161 tex = resourceProvider->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
162 isProtected,
163 GrResourceProvider::Flags::kNoPendingIO);
164 } else {
165 tex = resourceProvider->createTexture(desc, format, renderable, renderTargetSampleCnt,
166 budgeted, isProtected,
167 GrResourceProvider::Flags::kNoPendingIO);
168 }
169 if (!tex) {
170 return nullptr;
171 }
172
173 return this->createWrapped(std::move(tex), colorType, origin);
174 }
175
testingOnly_createInstantiatedProxy(const SkISize & size,GrColorType colorType,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)176 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
177 const SkISize& size,
178 GrColorType colorType,
179 GrRenderable renderable,
180 int renderTargetSampleCnt,
181 GrSurfaceOrigin origin,
182 SkBackingFit fit,
183 SkBudgeted budgeted,
184 GrProtected isProtected) {
185 auto format = this->caps()->getDefaultBackendFormat(colorType, renderable);
186 return this->testingOnly_createInstantiatedProxy(size,
187 colorType,
188 format,
189 renderable,
190 renderTargetSampleCnt,
191 origin,
192 fit,
193 budgeted,
194 isProtected);
195 }
196
testingOnly_createWrapped(sk_sp<GrTexture> tex,GrColorType colorType,GrSurfaceOrigin origin)197 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex,
198 GrColorType colorType,
199 GrSurfaceOrigin origin) {
200 return this->createWrapped(std::move(tex), colorType, origin);
201 }
202 #endif
203
createWrapped(sk_sp<GrTexture> tex,GrColorType colorType,GrSurfaceOrigin origin)204 sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, GrColorType colorType,
205 GrSurfaceOrigin origin) {
206 #ifdef SK_DEBUG
207 if (tex->getUniqueKey().isValid()) {
208 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
209 }
210 #endif
211 GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(tex->backendFormat(), colorType);
212
213 if (tex->asRenderTarget()) {
214 GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(tex->backendFormat(), colorType);
215 return assignTagToProxy(
216 sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin, texSwizzle, outSwizzle)));
217 } else {
218 return assignTagToProxy<GrTextureProxy>(
219 sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin, texSwizzle)));
220 }
221 }
222
findOrCreateProxyByUniqueKey(const GrUniqueKey & key,GrColorType colorType,GrSurfaceOrigin origin)223 sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
224 GrColorType colorType,
225 GrSurfaceOrigin origin) {
226 ASSERT_SINGLE_OWNER
227
228 if (this->isAbandoned()) {
229 return nullptr;
230 }
231
232 sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
233 if (result) {
234 return result;
235 }
236
237 GrContext* direct = fImageContext->priv().asDirectContext();
238 if (!direct) {
239 return nullptr;
240 }
241
242 GrResourceCache* resourceCache = direct->priv().getResourceCache();
243
244 GrGpuResource* resource = resourceCache->findAndRefUniqueResource(key);
245 if (!resource) {
246 return nullptr;
247 }
248
249 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
250 SkASSERT(texture);
251
252 result = this->createWrapped(std::move(texture), colorType, origin);
253 SkASSERT(result->getUniqueKey() == key);
254 // createWrapped should've added this for us
255 SkASSERT(fUniquelyKeyedProxies.find(key));
256 SkASSERT(result->textureSwizzle() ==
257 this->caps()->getTextureSwizzle(result->backendFormat(), colorType));
258 return result;
259 }
260
createTextureProxy(sk_sp<SkImage> srcImage,int sampleCnt,SkBudgeted budgeted,SkBackingFit fit,GrInternalSurfaceFlags surfaceFlags)261 sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
262 int sampleCnt,
263 SkBudgeted budgeted,
264 SkBackingFit fit,
265 GrInternalSurfaceFlags surfaceFlags) {
266 ASSERT_SINGLE_OWNER
267 SkASSERT(srcImage);
268
269 if (this->isAbandoned()) {
270 return nullptr;
271 }
272
273 const SkImageInfo& info = srcImage->imageInfo();
274 GrColorType ct = SkColorTypeToGrColorType(info.colorType());
275
276 GrBackendFormat format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
277
278 if (!format.isValid()) {
279 SkBitmap copy8888;
280 if (!copy8888.tryAllocPixels(info.makeColorType(kRGBA_8888_SkColorType)) ||
281 !srcImage->readPixels(copy8888.pixmap(), 0, 0)) {
282 return nullptr;
283 }
284 copy8888.setImmutable();
285 srcImage = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
286 ct = GrColorType::kRGBA_8888;
287 format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
288 if (!format.isValid()) {
289 return nullptr;
290 }
291 }
292
293 GrPixelConfig config = GrColorTypeToPixelConfig(ct);
294 if (kUnknown_GrPixelConfig == config) {
295 return nullptr;
296 }
297
298 GrSurfaceDesc desc;
299 desc.fWidth = srcImage->width();
300 desc.fHeight = srcImage->height();
301 desc.fConfig = config;
302
303 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
304 [desc, format, sampleCnt, budgeted, srcImage, fit,
305 ct](GrResourceProvider* resourceProvider) {
306 SkPixmap pixMap;
307 SkAssertResult(srcImage->peekPixels(&pixMap));
308 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
309
310 return LazyInstantiationResult(resourceProvider->createTexture(
311 desc, format, GrRenderable::kNo, sampleCnt, budgeted, fit, GrProtected::kNo,
312 ct, mipLevel, GrResourceProvider::Flags::kNoPendingIO));
313 },
314 format, desc, GrRenderable::kNo, sampleCnt, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
315 GrMipMapsStatus::kNotAllocated, surfaceFlags, fit, budgeted, GrProtected::kNo);
316
317 if (!proxy) {
318 return nullptr;
319 }
320
321 GrContext* direct = fImageContext->priv().asDirectContext();
322 if (direct) {
323 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
324
325 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
326 // we're better off instantiating the proxy immediately here.
327 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
328 return nullptr;
329 }
330 }
331
332 SkASSERT(proxy->width() == desc.fWidth);
333 SkASSERT(proxy->height() == desc.fHeight);
334 return proxy;
335 }
336
createMipMapProxy(const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,SkBudgeted budgeted,GrProtected isProtected)337 sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrBackendFormat& format,
338 const GrSurfaceDesc& desc,
339 GrRenderable renderable,
340 int renderTargetSampleCnt,
341 GrSurfaceOrigin origin,
342 SkBudgeted budgeted,
343 GrProtected isProtected) {
344 ASSERT_SINGLE_OWNER
345
346 if (this->isAbandoned()) {
347 return nullptr;
348 }
349
350 return this->createProxy(format, desc, renderable, renderTargetSampleCnt, origin,
351 GrMipMapped::kYes, SkBackingFit::kExact, budgeted, isProtected,
352 GrInternalSurfaceFlags::kNone);
353 }
354
createProxyFromBitmap(const SkBitmap & bitmap,GrMipMapped mipMapped)355 sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
356 GrMipMapped mipMapped) {
357 ASSERT_SINGLE_OWNER
358 SkASSERT(GrMipMapped::kNo == mipMapped || this->caps()->mipMapSupport());
359
360 if (this->isAbandoned()) {
361 return nullptr;
362 }
363
364 if (!SkImageInfoIsValid(bitmap.info())) {
365 return nullptr;
366 }
367
368 ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%ux%u]",
369 GrMipMapped::kYes == mipMapped ? "MipMap " : "",
370 bitmap.width(), bitmap.height());
371
372 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
373 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
374 // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
375 SkCopyPixelsMode copyMode = this->renderingDirectly() ? kNever_SkCopyPixelsMode
376 : kIfMutable_SkCopyPixelsMode;
377 sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
378 if (!baseLevel) {
379 return nullptr;
380 }
381
382 // If mips weren't requested (or this was too small to have any), then take the fast path
383 if (GrMipMapped::kNo == mipMapped ||
384 0 == SkMipMap::ComputeLevelCount(baseLevel->width(), baseLevel->height())) {
385 return this->createTextureProxy(std::move(baseLevel), 1, SkBudgeted::kYes,
386 SkBackingFit::kExact);
387 }
388
389 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
390
391 GrColorType grColorType = SkColorTypeToGrColorType(bitmap.info().colorType());
392 GrBackendFormat format = this->caps()->getDefaultBackendFormat(grColorType, GrRenderable::kNo);
393 if (!format.isValid()) {
394 SkBitmap copy8888;
395 if (!copy8888.tryAllocPixels(bitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
396 !bitmap.readPixels(copy8888.pixmap())) {
397 return nullptr;
398 }
399 copy8888.setImmutable();
400 baseLevel = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
401 desc.fConfig = kRGBA_8888_GrPixelConfig;
402 grColorType = GrColorType::kRGBA_8888;
403 format = this->caps()->getDefaultBackendFormat(grColorType, GrRenderable::kNo);
404 if (!format.isValid()) {
405 return nullptr;
406 }
407 }
408
409 SkPixmap pixmap;
410 SkAssertResult(baseLevel->peekPixels(&pixmap));
411 sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, nullptr));
412 if (!mipmaps) {
413 return nullptr;
414 }
415
416 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
417 [desc, format, baseLevel, mipmaps](GrResourceProvider* resourceProvider) {
418 const int mipLevelCount = mipmaps->countLevels() + 1;
419 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
420
421 SkPixmap pixmap;
422 SkAssertResult(baseLevel->peekPixels(&pixmap));
423
424 // DDL TODO: Instead of copying all this info into GrMipLevels we should just plumb
425 // the use of SkMipMap down through Ganesh.
426 texels[0].fPixels = pixmap.addr();
427 texels[0].fRowBytes = pixmap.rowBytes();
428
429 for (int i = 1; i < mipLevelCount; ++i) {
430 SkMipMap::Level generatedMipLevel;
431 mipmaps->getLevel(i - 1, &generatedMipLevel);
432 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
433 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
434 SkASSERT(texels[i].fPixels);
435 }
436
437 return LazyInstantiationResult(resourceProvider->createTexture(
438 desc, format, GrRenderable::kNo, 1, SkBudgeted::kYes, GrProtected::kNo,
439 texels.get(), mipLevelCount));
440 },
441 format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kYes,
442 GrMipMapsStatus::kValid, SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
443
444 if (!proxy) {
445 return nullptr;
446 }
447
448 GrContext* direct = fImageContext->priv().asDirectContext();
449 if (direct) {
450 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
451 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
452 // we're better off instantiating the proxy immediately here.
453 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
454 return nullptr;
455 }
456 }
457 return proxy;
458 }
459
460 #ifdef SK_DEBUG
validate_backend_format_and_config(const GrCaps * caps,const GrBackendFormat & format,GrPixelConfig config)461 static bool validate_backend_format_and_config(const GrCaps* caps,
462 const GrBackendFormat& format,
463 GrPixelConfig config) {
464 if (kUnknown_GrPixelConfig == config) {
465 return false;
466 }
467 if (GrPixelConfigIsCompressed(config)) {
468 // We have no way to verify these at the moment.
469 return true;
470 }
471
472 GrColorType grCT = GrPixelConfigToColorType(config);
473
474 return caps->areColorTypeAndFormatCompatible(grCT, format);
475 }
476 #endif
477
createProxy(const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags)478 sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format,
479 const GrSurfaceDesc& desc,
480 GrRenderable renderable,
481 int renderTargetSampleCnt,
482 GrSurfaceOrigin origin,
483 GrMipMapped mipMapped,
484 SkBackingFit fit,
485 SkBudgeted budgeted,
486 GrProtected isProtected,
487 GrInternalSurfaceFlags surfaceFlags) {
488 const GrCaps* caps = this->caps();
489
490 if (caps->isFormatCompressed(format)) {
491 // Deferred proxies for compressed textures are not supported.
492 return nullptr;
493 }
494
495 GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
496
497 SkASSERT(GrCaps::AreConfigsCompatible(desc.fConfig,
498 caps->getConfigFromBackendFormat(format, colorType)));
499 // TODO: This check should be removed once we get the swizzle outside of GrProxyProvider and
500 // either pass them to the proxy or store the on some view object.
501 if (!caps->areColorTypeAndFormatCompatible(colorType, format)) {
502 return nullptr;
503 }
504
505 if (GrMipMapped::kYes == mipMapped) {
506 // SkMipMap doesn't include the base level in the level count so we have to add 1
507 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
508 if (1 == mipCount) {
509 mipMapped = GrMipMapped::kNo;
510 }
511 }
512
513 if (!caps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
514 renderTargetSampleCnt, mipMapped)) {
515 return nullptr;
516 }
517 GrSurfaceDesc copyDesc = desc;
518 GrMipMapsStatus mipMapsStatus = (GrMipMapped::kYes == mipMapped)
519 ? GrMipMapsStatus::kDirty
520 : GrMipMapsStatus::kNotAllocated;
521 GrSwizzle texSwizzle = caps->getTextureSwizzle(format, colorType);
522 if (renderable == GrRenderable::kYes) {
523 renderTargetSampleCnt =
524 caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
525 SkASSERT(renderTargetSampleCnt);
526 // We know anything we instantiate later from this deferred path will be
527 // both texturable and renderable
528 GrSwizzle outSwizzle = caps->getOutputSwizzle(format, colorType);
529 return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
530 *caps, format, copyDesc, renderTargetSampleCnt, origin, mipMapped, mipMapsStatus,
531 texSwizzle, outSwizzle, fit, budgeted, isProtected, surfaceFlags)));
532 }
533
534 return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureProxy(
535 format, copyDesc, origin, mipMapped, mipMapsStatus, texSwizzle, fit, budgeted,
536 isProtected, surfaceFlags)));
537 }
538
createCompressedTextureProxy(int width,int height,SkBudgeted budgeted,SkImage::CompressionType compressionType,sk_sp<SkData> data)539 sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
540 int width, int height, SkBudgeted budgeted, SkImage::CompressionType compressionType,
541 sk_sp<SkData> data) {
542
543 GrSurfaceDesc desc;
544 desc.fConfig = GrCompressionTypePixelConfig(compressionType);
545 desc.fWidth = width;
546 desc.fHeight = height;
547
548 GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
549
550 if (!this->caps()->isFormatTexturable(format)) {
551 return nullptr;
552 }
553
554 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
555 [width, height, format, compressionType, budgeted, data]
556 (GrResourceProvider* resourceProvider) {
557 return LazyInstantiationResult(resourceProvider->createCompressedTexture(
558 width, height, format, compressionType, budgeted, data.get()));
559 },
560 format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
561 GrMipMapsStatus::kNotAllocated, SkBackingFit::kExact, SkBudgeted::kYes,
562 GrProtected::kNo);
563
564 if (!proxy) {
565 return nullptr;
566 }
567
568 GrContext* direct = fImageContext->priv().asDirectContext();
569 if (direct) {
570 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
571 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
572 // we're better off instantiating the proxy immediately here.
573 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
574 return nullptr;
575 }
576 }
577 return proxy;
578 }
579
wrapBackendTexture(const GrBackendTexture & backendTex,GrColorType grColorType,GrSurfaceOrigin origin,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType,ReleaseProc releaseProc,ReleaseContext releaseCtx)580 sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture& backendTex,
581 GrColorType grColorType,
582 GrSurfaceOrigin origin,
583 GrWrapOwnership ownership,
584 GrWrapCacheable cacheable,
585 GrIOType ioType,
586 ReleaseProc releaseProc,
587 ReleaseContext releaseCtx) {
588 SkASSERT(ioType != kWrite_GrIOType);
589 if (this->isAbandoned()) {
590 return nullptr;
591 }
592
593 // This is only supported on a direct GrContext.
594 GrContext* direct = fImageContext->priv().asDirectContext();
595 if (!direct) {
596 return nullptr;
597 }
598
599 const GrCaps* caps = this->caps();
600
601 SkASSERT(caps->areColorTypeAndFormatCompatible(grColorType, backendTex.getBackendFormat()));
602
603 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
604
605 sk_sp<GrTexture> tex =
606 resourceProvider->wrapBackendTexture(backendTex, grColorType,
607 ownership, cacheable, ioType);
608 if (!tex) {
609 return nullptr;
610 }
611
612 if (releaseProc) {
613 tex->setRelease(releaseProc, releaseCtx);
614 }
615
616 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
617 // Make sure we match how we created the proxy with SkBudgeted::kNo
618 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
619
620 GrSwizzle texSwizzle = caps->getTextureSwizzle(tex->backendFormat(), grColorType);
621
622 return assignTagToProxy(
623 sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin, texSwizzle)));
624 }
625
wrapRenderableBackendTexture(const GrBackendTexture & backendTex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,GrWrapOwnership ownership,GrWrapCacheable cacheable,ReleaseProc releaseProc,ReleaseContext releaseCtx)626 sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
627 const GrBackendTexture& backendTex, GrSurfaceOrigin origin, int sampleCnt,
628 GrColorType colorType, GrWrapOwnership ownership, GrWrapCacheable cacheable,
629 ReleaseProc releaseProc, ReleaseContext releaseCtx) {
630 if (this->isAbandoned()) {
631 return nullptr;
632 }
633
634 // This is only supported on a direct GrContext.
635 GrContext* direct = fImageContext->priv().asDirectContext();
636 if (!direct) {
637 return nullptr;
638 }
639
640 const GrCaps* caps = this->caps();
641
642 SkASSERT(caps->areColorTypeAndFormatCompatible(colorType, backendTex.getBackendFormat()));
643
644 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
645
646 // TODO: This should have been checked and validated before getting into GrProxyProvider.
647 if (!caps->isFormatAsColorTypeRenderable(colorType, backendTex.getBackendFormat(), sampleCnt)) {
648 return nullptr;
649 }
650
651 sampleCnt = caps->getRenderTargetSampleCount(sampleCnt, backendTex.getBackendFormat());
652 SkASSERT(sampleCnt);
653
654 sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture(backendTex, sampleCnt,
655 colorType, ownership,
656 cacheable);
657 if (!tex) {
658 return nullptr;
659 }
660
661 if (releaseProc) {
662 tex->setRelease(releaseProc, releaseCtx);
663 }
664
665 SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
666 // Make sure we match how we created the proxy with SkBudgeted::kNo
667 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
668
669 GrSwizzle texSwizzle = caps->getTextureSwizzle(tex->backendFormat(), colorType);
670 GrSwizzle outSwizzle = caps->getOutputSwizzle(tex->backendFormat(), colorType);
671
672 return assignTagToProxy(
673 sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin, texSwizzle, outSwizzle)));
674 }
675
wrapBackendRenderTarget(const GrBackendRenderTarget & backendRT,GrColorType grColorType,GrSurfaceOrigin origin,ReleaseProc releaseProc,ReleaseContext releaseCtx)676 sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
677 const GrBackendRenderTarget& backendRT, GrColorType grColorType,
678 GrSurfaceOrigin origin, ReleaseProc releaseProc, ReleaseContext releaseCtx) {
679 if (this->isAbandoned()) {
680 return nullptr;
681 }
682
683 // This is only supported on a direct GrContext.
684 GrContext* direct = fImageContext->priv().asDirectContext();
685 if (!direct) {
686 return nullptr;
687 }
688
689 const GrCaps* caps = this->caps();
690
691 SkASSERT(caps->areColorTypeAndFormatCompatible(grColorType, backendRT.getBackendFormat()));
692
693 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
694
695 sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT, grColorType);
696 if (!rt) {
697 return nullptr;
698 }
699
700 if (releaseProc) {
701 rt->setRelease(releaseProc, releaseCtx);
702 }
703
704 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
705 SkASSERT(!rt->getUniqueKey().isValid());
706 // Make sure we match how we created the proxy with SkBudgeted::kNo
707 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
708
709 GrSwizzle texSwizzle = caps->getTextureSwizzle(rt->backendFormat(), grColorType);
710 GrSwizzle outSwizzle = caps->getOutputSwizzle(rt->backendFormat(), grColorType);
711
712 return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), origin, texSwizzle,
713 outSwizzle)));
714 }
715
wrapBackendTextureAsRenderTarget(const GrBackendTexture & backendTex,GrColorType grColorType,GrSurfaceOrigin origin,int sampleCnt)716 sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendTextureAsRenderTarget(
717 const GrBackendTexture& backendTex, GrColorType grColorType,
718 GrSurfaceOrigin origin, int sampleCnt) {
719 if (this->isAbandoned()) {
720 return nullptr;
721 }
722
723 // This is only supported on a direct GrContext.
724 GrContext* direct = fImageContext->priv().asDirectContext();
725 if (!direct) {
726 return nullptr;
727 }
728
729 const GrCaps* caps = this->caps();
730
731 SkASSERT(caps->areColorTypeAndFormatCompatible(grColorType, backendTex.getBackendFormat()));
732
733 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
734
735 sk_sp<GrRenderTarget> rt =
736 resourceProvider->wrapBackendTextureAsRenderTarget(backendTex, sampleCnt, grColorType);
737 if (!rt) {
738 return nullptr;
739 }
740 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
741 SkASSERT(!rt->getUniqueKey().isValid());
742 // This proxy should be unbudgeted because we're just wrapping an external resource
743 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
744
745 GrSwizzle texSwizzle = caps->getTextureSwizzle(rt->backendFormat(), grColorType);
746 GrSwizzle outSwizzle = caps->getOutputSwizzle(rt->backendFormat(), grColorType);
747
748 return assignTagToProxy(
749 sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin, texSwizzle, outSwizzle)));
750 }
751
wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)752 sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
753 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
754 if (this->isAbandoned()) {
755 return nullptr;
756 }
757
758 // This is only supported on a direct GrContext.
759 GrContext* direct = fImageContext->priv().asDirectContext();
760 if (!direct) {
761 return nullptr;
762 }
763
764 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
765
766 sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
767 vkInfo);
768 if (!rt) {
769 return nullptr;
770 }
771
772 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
773 SkASSERT(!rt->getUniqueKey().isValid());
774 // This proxy should be unbudgeted because we're just wrapping an external resource
775 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
776
777 GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType());
778 GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(rt->backendFormat(), colorType);
779 GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(rt->backendFormat(), colorType);
780
781 if (!this->caps()->isFormatAsColorTypeRenderable(colorType, rt->backendFormat(),
782 rt->numSamples())) {
783 return nullptr;
784 }
785
786 // All Vulkan surfaces uses top left origins.
787 return assignTagToProxy(sk_sp<GrRenderTargetProxy>(
788 new GrRenderTargetProxy(std::move(rt),
789 kTopLeft_GrSurfaceOrigin, texSwizzle, outSwizzle,
790 GrRenderTargetProxy::WrapsVkSecondaryCB::kYes)));
791 }
792
createLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,GrMipMapsStatus mipMapsStatus,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)793 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
794 const GrBackendFormat& format,
795 const GrSurfaceDesc& desc,
796 GrRenderable renderable,
797 int renderTargetSampleCnt,
798 GrSurfaceOrigin origin,
799 GrMipMapped mipMapped,
800 GrMipMapsStatus mipMapsStatus,
801 SkBackingFit fit,
802 SkBudgeted budgeted,
803 GrProtected isProtected) {
804 return this->createLazyProxy(std::move(callback), format, desc, renderable,
805 renderTargetSampleCnt, origin, mipMapped, mipMapsStatus,
806 GrInternalSurfaceFlags::kNone, fit, budgeted, isProtected);
807 }
808
createLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,GrMipMapsStatus mipMapsStatus,GrInternalSurfaceFlags surfaceFlags,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)809 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
810 const GrBackendFormat& format,
811 const GrSurfaceDesc& desc,
812 GrRenderable renderable,
813 int renderTargetSampleCnt,
814 GrSurfaceOrigin origin,
815 GrMipMapped mipMapped,
816 GrMipMapsStatus mipMapsStatus,
817 GrInternalSurfaceFlags surfaceFlags,
818 SkBackingFit fit,
819 SkBudgeted budgeted,
820 GrProtected isProtected) {
821 // For non-ddl draws always make lazy proxy's single use.
822 LazyInstantiationType lazyType = this->renderingDirectly() ? LazyInstantiationType::kSingleUse
823 : LazyInstantiationType::kMultipleUse;
824 return this->createLazyProxy(std::move(callback), format, desc, renderable,
825 renderTargetSampleCnt, origin, mipMapped, mipMapsStatus,
826 surfaceFlags, fit, budgeted, isProtected, lazyType);
827 }
828
createLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,GrMipMapsStatus mipMapsStatus,GrInternalSurfaceFlags surfaceFlags,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,LazyInstantiationType lazyType)829 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
830 const GrBackendFormat& format,
831 const GrSurfaceDesc& desc,
832 GrRenderable renderable,
833 int renderTargetSampleCnt,
834 GrSurfaceOrigin origin,
835 GrMipMapped mipMapped,
836 GrMipMapsStatus mipMapsStatus,
837 GrInternalSurfaceFlags surfaceFlags,
838 SkBackingFit fit,
839 SkBudgeted budgeted,
840 GrProtected isProtected,
841 LazyInstantiationType lazyType) {
842 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
843 (desc.fWidth > 0 && desc.fHeight > 0));
844
845 if (!format.isValid()) {
846 return nullptr;
847 }
848
849 if (desc.fWidth > this->caps()->maxTextureSize() ||
850 desc.fHeight > this->caps()->maxTextureSize()) {
851 return nullptr;
852 }
853
854 SkASSERT(validate_backend_format_and_config(this->caps(), format, desc.fConfig));
855
856 GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
857 GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(format, colorType);
858 GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(format, colorType);
859
860 return assignTagToProxy(sk_sp<GrTextureProxy>((renderable == GrRenderable::kYes)
861 ? new GrTextureRenderTargetProxy(
862 std::move(callback), lazyType, format, desc, renderTargetSampleCnt, origin,
863 mipMapped, mipMapsStatus, texSwizzle, outSwizzle, fit, budgeted, isProtected,
864 surfaceFlags)
865 : new GrTextureProxy(
866 std::move(callback), lazyType, format, desc, origin, mipMapped, mipMapsStatus,
867 texSwizzle, fit, budgeted, isProtected, surfaceFlags)));
868 }
869
createLazyRenderTargetProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,int sampleCnt,GrSurfaceOrigin origin,GrInternalSurfaceFlags surfaceFlags,const TextureInfo * textureInfo,GrMipMapsStatus mipMapsStatus,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,bool wrapsVkSecondaryCB)870 sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
871 LazyInstantiateCallback&& callback, const GrBackendFormat& format,
872 const GrSurfaceDesc& desc, int sampleCnt, GrSurfaceOrigin origin,
873 GrInternalSurfaceFlags surfaceFlags, const TextureInfo* textureInfo,
874 GrMipMapsStatus mipMapsStatus, SkBackingFit fit, SkBudgeted budgeted,
875 GrProtected isProtected, bool wrapsVkSecondaryCB) {
876 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
877 (desc.fWidth > 0 && desc.fHeight > 0));
878
879 if (desc.fWidth > this->caps()->maxRenderTargetSize() ||
880 desc.fHeight > this->caps()->maxRenderTargetSize()) {
881 return nullptr;
882 }
883
884 SkASSERT(validate_backend_format_and_config(this->caps(), format, desc.fConfig));
885
886 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
887 // For non-ddl draws always make lazy proxy's single use.
888 LazyInstantiationType lazyType = this->renderingDirectly() ? LazyInstantiationType::kSingleUse
889 : LazyInstantiationType::kMultipleUse;
890
891 GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
892 GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(format, colorType);
893 GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(format, colorType);
894
895 if (textureInfo) {
896 // Wrapped vulkan secondary command buffers don't support texturing since we won't have an
897 // actual VkImage to texture from.
898 SkASSERT(!wrapsVkSecondaryCB);
899 return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
900 std::move(callback), lazyType, format, desc, sampleCnt, origin,
901 textureInfo->fMipMapped, mipMapsStatus, texSwizzle, outSwizzle, fit, budgeted,
902 isProtected, surfaceFlags)));
903 }
904
905 GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
906 wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes
907 : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo;
908
909 return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
910 std::move(callback), lazyType, format, desc, sampleCnt, origin, texSwizzle, outSwizzle,
911 fit, budgeted, isProtected, surfaceFlags, vkSCB)));
912 }
913
MakeFullyLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,GrProtected isProtected,GrSurfaceOrigin origin,GrPixelConfig config,const GrCaps & caps)914 sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(
915 LazyInstantiateCallback&& callback, const GrBackendFormat& format, GrRenderable renderable,
916 int renderTargetSampleCnt, GrProtected isProtected, GrSurfaceOrigin origin,
917 GrPixelConfig config, const GrCaps& caps) {
918 if (!format.isValid()) {
919 return nullptr;
920 }
921
922 SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes);
923 SkASSERT(validate_backend_format_and_config(&caps, format, config));
924 GrSurfaceDesc desc;
925 GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
926 desc.fWidth = -1;
927 desc.fHeight = -1;
928 desc.fConfig = config;
929
930 GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
931 GrSwizzle texSwizzle = caps.getTextureSwizzle(format, colorType);
932 GrSwizzle outSwizzle = caps.getOutputSwizzle(format, colorType);
933
934 return sk_sp<GrTextureProxy>((GrRenderable::kYes == renderable)
935 ? new GrTextureRenderTargetProxy(
936 std::move(callback), LazyInstantiationType::kSingleUse, format, desc,
937 renderTargetSampleCnt, origin, GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated,
938 texSwizzle, outSwizzle, SkBackingFit::kApprox, SkBudgeted::kYes, isProtected,
939 surfaceFlags)
940 : new GrTextureProxy(
941 std::move(callback), LazyInstantiationType::kSingleUse, format, desc, origin,
942 GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, texSwizzle,
943 SkBackingFit::kApprox, SkBudgeted::kYes, isProtected, surfaceFlags));
944 }
945
IsFunctionallyExact(GrSurfaceProxy * proxy)946 bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
947 const bool isInstantiated = proxy->isInstantiated();
948 // A proxy is functionally exact if:
949 // it is exact (obvs)
950 // when it is instantiated it will be exact (i.e., power of two dimensions)
951 // it is already instantiated and the proxy covers the entire backing surface
952 return proxy->priv().isExact() ||
953 (!isInstantiated && SkIsPow2(proxy->width()) && SkIsPow2(proxy->height())) ||
954 (isInstantiated && proxy->worstCaseWidth() == proxy->width() &&
955 proxy->worstCaseHeight() == proxy->height());
956 }
957
processInvalidUniqueKey(const GrUniqueKey & key,GrTextureProxy * proxy,InvalidateGPUResource invalidateGPUResource)958 void GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
959 InvalidateGPUResource invalidateGPUResource) {
960 SkASSERT(key.isValid());
961
962 if (!proxy) {
963 proxy = fUniquelyKeyedProxies.find(key);
964 }
965 SkASSERT(!proxy || proxy->getUniqueKey() == key);
966
967 // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the
968 // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
969 sk_sp<GrGpuResource> invalidGpuResource;
970 if (InvalidateGPUResource::kYes == invalidateGPUResource) {
971 GrContext* direct = fImageContext->priv().asDirectContext();
972 if (direct) {
973 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
974 invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
975 }
976 SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
977 }
978
979 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
980 // will not be in 'fUniquelyKeyedProxies'.
981 if (proxy) {
982 fUniquelyKeyedProxies.remove(key);
983 proxy->cacheAccess().clearUniqueKey();
984 }
985
986 if (invalidGpuResource) {
987 invalidGpuResource->resourcePriv().removeUniqueKey();
988 }
989 }
990
contextID() const991 uint32_t GrProxyProvider::contextID() const {
992 return fImageContext->priv().contextID();
993 }
994
caps() const995 const GrCaps* GrProxyProvider::caps() const {
996 return fImageContext->priv().caps();
997 }
998
refCaps() const999 sk_sp<const GrCaps> GrProxyProvider::refCaps() const {
1000 return fImageContext->priv().refCaps();
1001 }
1002
isAbandoned() const1003 bool GrProxyProvider::isAbandoned() const {
1004 return fImageContext->priv().abandoned();
1005 }
1006
orphanAllUniqueKeys()1007 void GrProxyProvider::orphanAllUniqueKeys() {
1008 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
1009 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
1010 GrTextureProxy& tmp = *iter;
1011
1012 tmp.fProxyProvider = nullptr;
1013 }
1014 }
1015
removeAllUniqueKeys()1016 void GrProxyProvider::removeAllUniqueKeys() {
1017 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
1018 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
1019 GrTextureProxy& tmp = *iter;
1020
1021 this->processInvalidUniqueKey(tmp.getUniqueKey(), &tmp, InvalidateGPUResource::kNo);
1022 }
1023 SkASSERT(!fUniquelyKeyedProxies.count());
1024 }
1025
renderingDirectly() const1026 bool GrProxyProvider::renderingDirectly() const {
1027 return fImageContext->priv().asDirectContext();
1028 }
1029