blob: 604dd1bb323981ca2555642f8a26c9bc41909d09 [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 Daniel9d86f1d2018-01-29 09:33:59 -050020#include "SkGr.h"
21#include "SkImage.h"
22#include "SkImage_Base.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050023#include "SkMipMap.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050024
25#define ASSERT_SINGLE_OWNER \
26 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
27
28GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider,
29 GrResourceCache* resourceCache,
30 sk_sp<const GrCaps> caps,
31 GrSingleOwner* owner)
32 : fResourceProvider(resourceProvider)
33 , fResourceCache(resourceCache)
Robert Phillips4d120512018-01-19 13:22:07 -050034 , fAbandoned(false)
Robert Phillips1afd4cd2018-01-08 13:40:32 -050035 , fCaps(caps)
36#ifdef SK_DEBUG
37 , fSingleOwner(owner)
38#endif
39{
40
41}
42
43GrProxyProvider::~GrProxyProvider() {
44 SkASSERT(!fUniquelyKeyedProxies.count());
45}
46
Robert Phillipsadbe1322018-01-17 13:35:46 -050047bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050048 ASSERT_SINGLE_OWNER
49 SkASSERT(key.isValid());
50 if (this->isAbandoned() || !proxy) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050051 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050052 }
53
54 // If there is already a GrResource with this key then the caller has violated the normal
55 // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
56 // if it already existed in the cache).
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -050057 SkASSERT(!fResourceCache || !fResourceCache->findAndRefUniqueResource(key));
Robert Phillips1afd4cd2018-01-08 13:40:32 -050058
59 // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
60 // resources are a special case: the unique keys give us a weak ref so that we can reuse the
61 // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
62 // it will always be released - it is never converted to a scratch resource.
63 if (SkBudgeted::kNo == proxy->isBudgeted() &&
64 (!proxy->priv().isInstantiated() ||
65 !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050066 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050067 }
68
69 SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key
70
71 proxy->cacheAccess().setUniqueKey(this, key);
72 SkASSERT(proxy->getUniqueKey() == key);
73 fUniquelyKeyedProxies.add(proxy);
Robert Phillipsadbe1322018-01-17 13:35:46 -050074 return true;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050075}
76
77void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
78 SkASSERT(surf->getUniqueKey().isValid());
79 proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
80 SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
81 // multiple proxies can't get the same key
82 SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
83 fUniquelyKeyedProxies.add(proxy);
84}
85
86void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
87 ASSERT_SINGLE_OWNER
88 if (this->isAbandoned() || !proxy) {
89 return;
90 }
91 this->processInvalidProxyUniqueKey(key, proxy, true);
92}
93
94sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
95 GrSurfaceOrigin origin) {
96 ASSERT_SINGLE_OWNER
97
98 if (this->isAbandoned()) {
99 return nullptr;
100 }
101
102 sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
103 if (result) {
104 SkASSERT(result->origin() == origin);
105 }
106 return result;
107}
108
Robert Phillipsadbe1322018-01-17 13:35:46 -0500109sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin) {
110#ifdef SK_DEBUG
111 if (tex->getUniqueKey().isValid()) {
112 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
113 }
114#endif
115
116 if (tex->asRenderTarget()) {
117 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin));
118 } else {
119 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin));
120 }
121}
122
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500123sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
124 GrSurfaceOrigin origin) {
125 ASSERT_SINGLE_OWNER
126
127 if (this->isAbandoned()) {
128 return nullptr;
129 }
130
131 sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
132 if (result) {
133 return result;
134 }
135
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500136 if (!fResourceCache) {
137 return nullptr;
138 }
139
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500140 GrGpuResource* resource = fResourceCache->findAndRefUniqueResource(key);
141 if (!resource) {
142 return nullptr;
143 }
144
145 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
146 SkASSERT(texture);
147
Robert Phillipsadbe1322018-01-17 13:35:46 -0500148 result = this->createWrapped(std::move(texture), origin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500149 SkASSERT(result->getUniqueKey() == key);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500150 // createWrapped should've added this for us
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500151 SkASSERT(fUniquelyKeyedProxies.find(key));
152 return result;
153}
154
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500155sk_sp<GrTextureProxy> GrProxyProvider::createInstantiatedProxy(const GrSurfaceDesc& desc,
156 SkBackingFit fit,
157 SkBudgeted budgeted,
158 uint32_t flags) {
159 sk_sp<GrTexture> tex;
160
161 if (SkBackingFit::kApprox == fit) {
162 tex = fResourceProvider->createApproxTexture(desc, flags);
163 } else {
164 tex = fResourceProvider->createTexture(desc, budgeted, flags);
165 }
166 if (!tex) {
167 return nullptr;
168 }
169
Robert Phillipsadbe1322018-01-17 13:35:46 -0500170 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500171}
172
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500173sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(const GrSurfaceDesc& desc,
174 SkBudgeted budgeted,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500175 const void* srcData, size_t rowBytes) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500176 ASSERT_SINGLE_OWNER
177
Robert Phillips579f0942018-01-08 14:53:35 -0500178 if (this->isAbandoned()) {
179 return nullptr;
180 }
181
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500182 if (srcData) {
183 GrMipLevel mipLevel = { srcData, rowBytes };
184
185 sk_sp<GrTexture> tex = fResourceProvider->createTexture(desc, budgeted, mipLevel);
186 if (!tex) {
187 return nullptr;
188 }
189
Robert Phillipsadbe1322018-01-17 13:35:46 -0500190 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500191 }
192
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500193 return this->createProxy(desc, SkBackingFit::kExact, budgeted);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500194}
195
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500196sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
197 GrSurfaceFlags flags,
198 GrSurfaceOrigin origin,
199 int sampleCnt,
200 SkBudgeted budgeted) {
201 ASSERT_SINGLE_OWNER
202 SkASSERT(srcImage);
203
204 if (this->isAbandoned()) {
205 return nullptr;
206 }
207
208 GrSurfaceDesc desc;
209 desc.fWidth = srcImage->width();
210 desc.fHeight = srcImage->height();
211 desc.fFlags = flags;
212 desc.fOrigin = origin;
213 desc.fSampleCnt = sampleCnt;
214 desc.fConfig = SkImageInfo2GrPixelConfig(as_IB(srcImage)->onImageInfo(), *this->caps());
215
216 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
217 [desc, budgeted, srcImage]
218 (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
219 if (!resourceProvider) {
220 return sk_sp<GrTexture>();
221 }
222 SkPixmap pixMap;
223 SkAssertResult(srcImage->peekPixels(&pixMap));
224 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
225
226 return resourceProvider->createTexture(desc, budgeted, mipLevel);
227 }, desc, GrMipMapped::kNo, SkBackingFit::kExact, budgeted);
228
229 if (fResourceProvider) {
230 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
231 // we're better off instantiating the proxy immediately here.
232 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
233 return nullptr;
234 }
235 }
236 return proxy;
237}
238
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500239sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500240 const GrSurfaceDesc& desc, SkBudgeted budgeted,
241 const GrMipLevel texels[], int mipLevelCount,
242 SkDestinationSurfaceColorMode mipColorMode) {
Robert Phillips579f0942018-01-08 14:53:35 -0500243 ASSERT_SINGLE_OWNER
244
245 if (this->isAbandoned()) {
246 return nullptr;
247 }
248
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500249 if (!mipLevelCount) {
250 if (texels) {
251 return nullptr;
252 }
253 return this->createProxy(desc, SkBackingFit::kExact, budgeted);
254 }
255 if (!texels) {
256 return nullptr;
257 }
258
259 if (1 == mipLevelCount) {
260 return this->createTextureProxy(desc, budgeted, texels[0].fPixels, texels[0].fRowBytes);
261 }
262
263#ifdef SK_DEBUG
264 // There are only three states we want to be in when uploading data to a mipped surface.
265 // 1) We have data to upload to all layers
266 // 2) We are not uploading data to any layers
267 // 3) We are only uploading data to the base layer
268 // We check here to make sure we do not have any other state.
269 bool firstLevelHasData = SkToBool(texels[0].fPixels);
270 bool allOtherLevelsHaveData = true, allOtherLevelsLackData = true;
271 for (int i = 1; i < mipLevelCount; ++i) {
272 if (texels[i].fPixels) {
273 allOtherLevelsLackData = false;
274 } else {
275 allOtherLevelsHaveData = false;
276 }
277 }
278 SkASSERT((firstLevelHasData && allOtherLevelsHaveData) || allOtherLevelsLackData);
279#endif
280
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500281 sk_sp<GrTexture> tex(fResourceProvider->createTexture(desc, budgeted,
282 texels, mipLevelCount,
283 mipColorMode));
284 if (!tex) {
285 return nullptr;
286 }
287
Robert Phillipsadbe1322018-01-17 13:35:46 -0500288 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500289}
290
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500291sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& desc,
292 SkBudgeted budgeted) {
293 // SkMipMap doesn't include the base level in the level count so we have to add 1
294 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
295
296 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
297
298 // We don't want to upload any texel data
299 for (int i = 0; i < mipCount; i++) {
300 texels[i].fPixels = nullptr;
301 texels[i].fRowBytes = 0;
302 }
303
304 return this->createMipMapProxy(desc, budgeted, texels.get(), mipCount,
305 SkDestinationSurfaceColorMode::kLegacy);
306}
307
308sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
309 SkBackingFit fit,
310 SkBudgeted budgeted,
311 uint32_t flags) {
312 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
313
314 const GrCaps* caps = this->caps();
315
316 // TODO: move this logic into GrResourceProvider!
317 // TODO: share this testing code with check_texture_creation_params
318 if (!caps->isConfigTexturable(desc.fConfig)) {
319 return nullptr;
320 }
321
322 bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
323 if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
324 return nullptr;
325 }
326
327 // We currently do not support multisampled textures
328 if (!willBeRT && desc.fSampleCnt > 0) {
329 return nullptr;
330 }
331
332 int maxSize;
333 if (willBeRT) {
334 maxSize = caps->maxRenderTargetSize();
335 } else {
336 maxSize = caps->maxTextureSize();
337 }
338
339 if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
340 return nullptr;
341 }
342
343 GrSurfaceDesc copyDesc = desc;
344 copyDesc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
345
346#ifdef SK_DISABLE_DEFERRED_PROXIES
347 // Temporarily force instantiation for crbug.com/769760 and crbug.com/769898
348 sk_sp<GrTexture> tex;
349
350 if (SkBackingFit::kApprox == fit) {
351 tex = resourceProvider->createApproxTexture(copyDesc, flags);
352 } else {
353 tex = resourceProvider->createTexture(copyDesc, budgeted, flags);
354 }
355
356 if (!tex) {
357 return nullptr;
358 }
359
360 return GrSurfaceProxy::MakeWrapped(std::move(tex), copyDesc.fOrigin);
361#else
362 if (willBeRT) {
363 // We know anything we instantiate later from this deferred path will be
364 // both texturable and renderable
365 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
366 budgeted, flags));
367 }
368
369 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
370#endif
371}
372
Robert Phillipsadbe1322018-01-17 13:35:46 -0500373sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(
374 const GrBackendTexture& backendTex,
375 GrSurfaceOrigin origin,
376 GrWrapOwnership ownership,
377 ReleaseProc releaseProc,
378 ReleaseContext releaseCtx) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500379 if (this->isAbandoned()) {
380 return nullptr;
381 }
382
Greg Danielf2336e42018-01-23 16:38:14 -0500383 GrSurfaceDesc desc;
384 desc.fOrigin = origin;
385 desc.fWidth = backendTex.width();
386 desc.fHeight = backendTex.height();
387 desc.fConfig = backendTex.config();
388 GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
Robert Phillipsadbe1322018-01-17 13:35:46 -0500389
Greg Daniel6a0176b2018-01-30 09:28:44 -0500390 sk_sp<GrReleaseProcHelper> releaseHelper;
391 if (releaseProc) {
392 releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
393 }
394
Greg Danielf2336e42018-01-23 16:38:14 -0500395 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Greg Daniel6a0176b2018-01-30 09:28:44 -0500396 [backendTex, ownership, releaseHelper]
Greg Danielf2336e42018-01-23 16:38:14 -0500397 (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
398 if (!resourceProvider) {
Greg Daniel6a0176b2018-01-30 09:28:44 -0500399 // This lazy proxy was never initialized. If this had a releaseHelper it will
400 // get unrefed when we delete this lambda and will call the release proc so that
401 // the client knows they can free the underlying backend object.
Greg Danielf2336e42018-01-23 16:38:14 -0500402 return sk_sp<GrTexture>();
403 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500404
Greg Danielf2336e42018-01-23 16:38:14 -0500405 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex,
406 ownership);
407 if (!tex) {
408 return sk_sp<GrTexture>();
409 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500410 if (releaseHelper) {
411 // DDL TODO: once we are reusing lazy proxies, remove this move and hold onto to
412 // the ref till the lambda goes away.
413 tex->setRelease(std::move(releaseHelper));
Greg Danielf2336e42018-01-23 16:38:14 -0500414 }
415 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
416 // Make sure we match how we created the proxy with SkBudgeted::kNo
417 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
418
419 return tex;
420 }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
421
422 if (fResourceProvider) {
423 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
424 // we're better off instantiating the proxy immediately here.
Greg Danielbddcc952018-01-24 13:22:24 -0500425 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
426 return nullptr;
427 }
Greg Danielf2336e42018-01-23 16:38:14 -0500428 }
429 return proxy;
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500430}
431
432sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(const GrBackendTexture& tex,
433 GrSurfaceOrigin origin,
434 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500435 if (this->isAbandoned()) {
436 return nullptr;
437 }
438
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500439 sk_sp<GrTexture> texture(fResourceProvider->wrapRenderableBackendTexture(tex, sampleCnt));
440 if (!texture) {
441 return nullptr;
442 }
443 SkASSERT(texture->asRenderTarget()); // A GrTextureRenderTarget
444
Robert Phillipsadbe1322018-01-17 13:35:46 -0500445 return this->createWrapped(std::move(texture), origin);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500446}
447
448sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(
449 const GrBackendRenderTarget& backendRT,
450 GrSurfaceOrigin origin) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500451 if (this->isAbandoned()) {
452 return nullptr;
453 }
454
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500455 sk_sp<GrRenderTarget> rt(fResourceProvider->wrapBackendRenderTarget(backendRT));
456 if (!rt) {
457 return nullptr;
458 }
459 SkASSERT(!rt->asTexture()); // Strictly a GrRenderTarget
460 SkASSERT(!rt->getUniqueKey().isValid());
461
462 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
463}
464
465sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(const GrBackendTexture& tex,
466 GrSurfaceOrigin origin,
467 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500468 if (this->isAbandoned()) {
469 return nullptr;
470 }
471
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500472 sk_sp<GrRenderTarget> rt(fResourceProvider->wrapBackendTextureAsRenderTarget(tex, sampleCnt));
473 if (!rt) {
474 return nullptr;
475 }
476 SkASSERT(!rt->asTexture()); // Strictly a GrRenderTarget
477 SkASSERT(!rt->getUniqueKey().isValid());
478
479 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
480}
481
Robert Phillips777707b2018-01-17 11:40:14 -0500482sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
483 const GrSurfaceDesc& desc,
484 GrMipMapped mipMapped,
485 SkBackingFit fit, SkBudgeted budgeted) {
486 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
487 (desc.fWidth > 0 && desc.fHeight > 0));
488 uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
489 return sk_sp<GrTextureProxy>(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags) ?
490 new GrTextureRenderTargetProxy(std::move(callback), desc,
491 mipMapped, fit, budgeted, flags) :
492 new GrTextureProxy(std::move(callback), desc, mipMapped, fit,
493 budgeted, flags));
494
495}
496
497sk_sp<GrTextureProxy> GrProxyProvider::createFullyLazyProxy(LazyInstantiateCallback&& callback,
498 Renderable renderable,
499 GrPixelConfig config) {
500 GrSurfaceDesc desc;
501 if (Renderable::kYes == renderable) {
502 desc.fFlags = kRenderTarget_GrSurfaceFlag;
503 }
504 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
505 desc.fWidth = -1;
506 desc.fHeight = -1;
507 desc.fConfig = config;
508 desc.fSampleCnt = 0;
509
510 return this->createLazyProxy(std::move(callback), desc, GrMipMapped::kNo,
511 SkBackingFit::kApprox, SkBudgeted::kYes);
512
513}
514
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500515bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
516 return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
517}
518
519void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
520 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
521 // will not be in 'fUniquelyKeyedProxies'.
522 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
523 if (proxy) {
524 this->processInvalidProxyUniqueKey(key, proxy, false);
525 }
526}
527
528void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
529 bool invalidateSurface) {
530 SkASSERT(proxy);
531 SkASSERT(proxy->getUniqueKey().isValid());
532 SkASSERT(proxy->getUniqueKey() == key);
533
534 fUniquelyKeyedProxies.remove(key);
535 proxy->cacheAccess().clearUniqueKey();
536
537 if (invalidateSurface && proxy->priv().isInstantiated()) {
538 GrSurface* surface = proxy->priv().peekSurface();
539 if (surface) {
540 surface->resourcePriv().removeUniqueKey();
541 }
542 }
543}
544
545void GrProxyProvider::removeAllUniqueKeys() {
546 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
547 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
548 GrTextureProxy& tmp = *iter;
549
550 this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
551 }
552 SkASSERT(!fUniquelyKeyedProxies.count());
553}