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