blob: 09298abd796a72ac17e73471a996babb34b862cf [file] [log] [blame]
Robert Phillips1afd4cd2018-01-08 13:40:32 -05001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrProxyProvider.h"
9
10#include "GrCaps.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050011#include "GrRenderTarget.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050012#include "GrResourceKey.h"
13#include "GrResourceProvider.h"
14#include "GrSurfaceProxy.h"
15#include "GrSurfaceProxyPriv.h"
16#include "GrTexture.h"
17#include "GrTextureProxyCacheAccess.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050018#include "GrTextureRenderTargetProxy.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050019#include "../private/GrSingleOwner.h"
Greg Daniela4ead652018-02-07 10:21:48 -050020#include "SkBitmap.h"
Greg Daniel9d86f1d2018-01-29 09:33:59 -050021#include "SkGr.h"
22#include "SkImage.h"
23#include "SkImage_Base.h"
Greg Daniela4ead652018-02-07 10:21:48 -050024#include "SkImageInfoPriv.h"
25#include "SkImagePriv.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050026#include "SkMipMap.h"
Greg Daniela4ead652018-02-07 10:21:48 -050027#include "SkTraceEvent.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050028
29#define ASSERT_SINGLE_OWNER \
30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
31
32GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider,
33 GrResourceCache* resourceCache,
34 sk_sp<const GrCaps> caps,
35 GrSingleOwner* owner)
36 : fResourceProvider(resourceProvider)
37 , fResourceCache(resourceCache)
Robert Phillips4d120512018-01-19 13:22:07 -050038 , fAbandoned(false)
Robert Phillips1afd4cd2018-01-08 13:40:32 -050039 , fCaps(caps)
40#ifdef SK_DEBUG
41 , fSingleOwner(owner)
42#endif
43{
44
45}
46
47GrProxyProvider::~GrProxyProvider() {
48 SkASSERT(!fUniquelyKeyedProxies.count());
49}
50
Robert Phillipsadbe1322018-01-17 13:35:46 -050051bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050052 ASSERT_SINGLE_OWNER
53 SkASSERT(key.isValid());
54 if (this->isAbandoned() || !proxy) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050055 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050056 }
57
58 // If there is already a GrResource with this key then the caller has violated the normal
59 // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
60 // if it already existed in the cache).
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -050061 SkASSERT(!fResourceCache || !fResourceCache->findAndRefUniqueResource(key));
Robert Phillips1afd4cd2018-01-08 13:40:32 -050062
63 // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
64 // resources are a special case: the unique keys give us a weak ref so that we can reuse the
65 // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
66 // it will always be released - it is never converted to a scratch resource.
67 if (SkBudgeted::kNo == proxy->isBudgeted() &&
68 (!proxy->priv().isInstantiated() ||
69 !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050070 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050071 }
72
73 SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key
74
75 proxy->cacheAccess().setUniqueKey(this, key);
76 SkASSERT(proxy->getUniqueKey() == key);
77 fUniquelyKeyedProxies.add(proxy);
Robert Phillipsadbe1322018-01-17 13:35:46 -050078 return true;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050079}
80
81void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
82 SkASSERT(surf->getUniqueKey().isValid());
83 proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
84 SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
85 // multiple proxies can't get the same key
86 SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
87 fUniquelyKeyedProxies.add(proxy);
88}
89
90void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
91 ASSERT_SINGLE_OWNER
92 if (this->isAbandoned() || !proxy) {
93 return;
94 }
95 this->processInvalidProxyUniqueKey(key, proxy, true);
96}
97
98sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
99 GrSurfaceOrigin origin) {
100 ASSERT_SINGLE_OWNER
101
102 if (this->isAbandoned()) {
103 return nullptr;
104 }
105
106 sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
107 if (result) {
108 SkASSERT(result->origin() == origin);
109 }
110 return result;
111}
112
Robert Phillipsadbe1322018-01-17 13:35:46 -0500113sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin) {
114#ifdef SK_DEBUG
115 if (tex->getUniqueKey().isValid()) {
116 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
117 }
118#endif
119
120 if (tex->asRenderTarget()) {
121 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin));
122 } else {
123 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin));
124 }
125}
126
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500127sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
128 GrSurfaceOrigin origin) {
129 ASSERT_SINGLE_OWNER
130
131 if (this->isAbandoned()) {
132 return nullptr;
133 }
134
135 sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
136 if (result) {
137 return result;
138 }
139
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500140 if (!fResourceCache) {
141 return nullptr;
142 }
143
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500144 GrGpuResource* resource = fResourceCache->findAndRefUniqueResource(key);
145 if (!resource) {
146 return nullptr;
147 }
148
149 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
150 SkASSERT(texture);
151
Robert Phillipsadbe1322018-01-17 13:35:46 -0500152 result = this->createWrapped(std::move(texture), origin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500153 SkASSERT(result->getUniqueKey() == key);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500154 // createWrapped should've added this for us
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500155 SkASSERT(fUniquelyKeyedProxies.find(key));
156 return result;
157}
158
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500159sk_sp<GrTextureProxy> GrProxyProvider::createInstantiatedProxy(const GrSurfaceDesc& desc,
160 SkBackingFit fit,
161 SkBudgeted budgeted,
162 uint32_t flags) {
163 sk_sp<GrTexture> tex;
164
165 if (SkBackingFit::kApprox == fit) {
166 tex = fResourceProvider->createApproxTexture(desc, flags);
167 } else {
168 tex = fResourceProvider->createTexture(desc, budgeted, flags);
169 }
170 if (!tex) {
171 return nullptr;
172 }
173
Robert Phillipsadbe1322018-01-17 13:35:46 -0500174 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500175}
176
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500177sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(const GrSurfaceDesc& desc,
178 SkBudgeted budgeted,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500179 const void* srcData, size_t rowBytes) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500180 ASSERT_SINGLE_OWNER
181
Robert Phillips579f0942018-01-08 14:53:35 -0500182 if (this->isAbandoned()) {
183 return nullptr;
184 }
185
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500186 if (srcData) {
187 GrMipLevel mipLevel = { srcData, rowBytes };
188
Greg Danielfb3abcd2018-02-02 15:48:33 -0500189 sk_sp<GrTexture> tex = fResourceProvider->createTexture(desc, budgeted,
190 SkBackingFit::kExact, mipLevel);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500191 if (!tex) {
192 return nullptr;
193 }
194
Robert Phillipsadbe1322018-01-17 13:35:46 -0500195 return this->createWrapped(std::move(tex), desc.fOrigin);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500196 }
197
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500198 return this->createProxy(desc, SkBackingFit::kExact, budgeted);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500199}
200
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500201sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
202 GrSurfaceFlags flags,
203 GrSurfaceOrigin origin,
204 int sampleCnt,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500205 SkBudgeted budgeted,
206 SkBackingFit fit) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500207 ASSERT_SINGLE_OWNER
208 SkASSERT(srcImage);
209
210 if (this->isAbandoned()) {
211 return nullptr;
212 }
213
Greg Daniel2a303902018-02-20 10:25:54 -0500214 GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
215 if (SkToBool(flags & kRenderTarget_GrSurfaceFlag)) {
216 if (fCaps->usesMixedSamples() && sampleCnt > 1) {
217 renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
218 }
219 if (fCaps->maxWindowRectangles() > 0) {
220 renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
221 }
222 }
223
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500224 GrSurfaceDesc desc;
225 desc.fWidth = srcImage->width();
226 desc.fHeight = srcImage->height();
227 desc.fFlags = flags;
228 desc.fOrigin = origin;
229 desc.fSampleCnt = sampleCnt;
230 desc.fConfig = SkImageInfo2GrPixelConfig(as_IB(srcImage)->onImageInfo(), *this->caps());
231
232 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Greg Danielfb3abcd2018-02-02 15:48:33 -0500233 [desc, budgeted, srcImage, fit]
Robert Phillipsce5209a2018-02-13 11:13:51 -0500234 (GrResourceProvider* resourceProvider) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500235 if (!resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500236 // Nothing to clean up here. Once the proxy (and thus lambda) is deleted the ref
237 // on srcImage will be released.
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500238 return sk_sp<GrTexture>();
239 }
240 SkPixmap pixMap;
241 SkAssertResult(srcImage->peekPixels(&pixMap));
242 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
243
Greg Danielfb3abcd2018-02-02 15:48:33 -0500244 return resourceProvider->createTexture(desc, budgeted, fit, mipLevel);
Greg Daniel2a303902018-02-20 10:25:54 -0500245 }, desc, GrMipMapped::kNo, renderTargetFlags, fit, budgeted);
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500246
247 if (fResourceProvider) {
248 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
249 // we're better off instantiating the proxy immediately here.
250 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
251 return nullptr;
252 }
253 }
254 return proxy;
255}
256
Greg Daniel30815082018-02-09 16:08:30 -0500257sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& desc,
258 SkBudgeted budgeted) {
Robert Phillips579f0942018-01-08 14:53:35 -0500259 ASSERT_SINGLE_OWNER
260
261 if (this->isAbandoned()) {
262 return nullptr;
263 }
264
Greg Danielf6f7b672018-02-15 13:06:26 -0500265 return this->createProxy(desc, GrMipMapped::kYes, SkBackingFit::kExact, budgeted, 0);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500266}
267
Greg Daniela4ead652018-02-07 10:21:48 -0500268sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxyFromBitmap(const SkBitmap& bitmap,
269 SkColorSpace* dstColorSpace) {
270 SkDestinationSurfaceColorMode mipColorMode = dstColorSpace
271 ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
272 : SkDestinationSurfaceColorMode::kLegacy;
273
274 if (!SkImageInfoIsValid(bitmap.info(), mipColorMode)) {
275 return nullptr;
276 }
277
278 SkPixmap pixmap;
279 if (!bitmap.peekPixels(&pixmap)) {
280 return nullptr;
281 }
282
283 ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height());
284 sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, mipColorMode, nullptr));
285 if (!mipmaps) {
286 return nullptr;
287 }
288
289 if (mipmaps->countLevels() < 0) {
290 return nullptr;
291 }
292
293 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
294 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
295 // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
Greg Daniel7e1912a2018-02-08 09:15:33 -0500296 SkCopyPixelsMode copyMode = this->mutableBitmapsNeedCopy() ? kIfMutable_SkCopyPixelsMode
297 : kNever_SkCopyPixelsMode;
Greg Daniela4ead652018-02-07 10:21:48 -0500298 sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
299
300 if (!baseLevel) {
301 return nullptr;
302 }
303
304 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *this->caps());
305
306 if (0 == mipmaps->countLevels()) {
307 return this->createTextureProxy(baseLevel, kNone_GrSurfaceFlags, kTopLeft_GrSurfaceOrigin,
308 1, SkBudgeted::kYes, SkBackingFit::kExact);
309
310 }
311
312 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
313 [desc, baseLevel, mipmaps, mipColorMode]
Robert Phillipsce5209a2018-02-13 11:13:51 -0500314 (GrResourceProvider* resourceProvider) {
Greg Daniela4ead652018-02-07 10:21:48 -0500315 if (!resourceProvider) {
316 return sk_sp<GrTexture>();
317 }
318
319 const int mipLevelCount = mipmaps->countLevels() + 1;
320 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
321
322 SkPixmap pixmap;
323 SkAssertResult(baseLevel->peekPixels(&pixmap));
324
325 // DDL TODO: Instead of copying all this info into GrMipLevels we should just plumb
326 // the use of SkMipMap down through Ganesh.
327 texels[0].fPixels = pixmap.addr();
328 texels[0].fRowBytes = pixmap.rowBytes();
329
330 for (int i = 1; i < mipLevelCount; ++i) {
331 SkMipMap::Level generatedMipLevel;
332 mipmaps->getLevel(i - 1, &generatedMipLevel);
333 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
334 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
335 SkASSERT(texels[i].fPixels);
336 }
337
338 return resourceProvider->createTexture(desc, SkBudgeted::kYes, texels.get(),
339 mipLevelCount, mipColorMode);
340 }, desc, GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes);
341
342 if (fResourceProvider) {
343 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
344 // we're better off instantiating the proxy immediately here.
345 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
346 return nullptr;
347 }
348 }
349 return proxy;
350}
351
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500352sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
Greg Danielf6f7b672018-02-15 13:06:26 -0500353 GrMipMapped mipMapped,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500354 SkBackingFit fit,
355 SkBudgeted budgeted,
356 uint32_t flags) {
357 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
358
Greg Danielf6f7b672018-02-15 13:06:26 -0500359 if (GrMipMapped::kYes == mipMapped) {
360 // SkMipMap doesn't include the base level in the level count so we have to add 1
361 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
362 if (1 == mipCount) {
363 mipMapped = GrMipMapped::kNo;
364 }
365 }
366
367 if (!this->caps()->validateSurfaceDesc(desc, mipMapped)) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500368 return nullptr;
369 }
Brian Salomon3a2cc2c2018-02-03 00:25:12 +0000370 GrSurfaceDesc copyDesc = desc;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500371 if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
372 copyDesc.fSampleCnt =
373 this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
374 }
Brian Salomon3a2cc2c2018-02-03 00:25:12 +0000375
Brian Salomonbdecacf2018-02-02 20:32:49 -0500376 if (copyDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500377 // We know anything we instantiate later from this deferred path will be
378 // both texturable and renderable
Brian Salomonbdecacf2018-02-02 20:32:49 -0500379 return sk_sp<GrTextureProxy>(
Greg Danielf6f7b672018-02-15 13:06:26 -0500380 new GrTextureRenderTargetProxy(*this->caps(), copyDesc, mipMapped, fit, budgeted,
381 flags));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500382 }
383
Greg Danielf6f7b672018-02-15 13:06:26 -0500384 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, mipMapped, fit, budgeted, nullptr, 0,
385 flags));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500386}
387
Robert Phillipsadbe1322018-01-17 13:35:46 -0500388sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(
389 const GrBackendTexture& backendTex,
390 GrSurfaceOrigin origin,
391 GrWrapOwnership ownership,
392 ReleaseProc releaseProc,
393 ReleaseContext releaseCtx) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500394 if (this->isAbandoned()) {
395 return nullptr;
396 }
397
Greg Danielf2336e42018-01-23 16:38:14 -0500398 GrSurfaceDesc desc;
399 desc.fOrigin = origin;
400 desc.fWidth = backendTex.width();
401 desc.fHeight = backendTex.height();
402 desc.fConfig = backendTex.config();
403 GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
Robert Phillipsadbe1322018-01-17 13:35:46 -0500404
Greg Daniel6a0176b2018-01-30 09:28:44 -0500405 sk_sp<GrReleaseProcHelper> releaseHelper;
406 if (releaseProc) {
407 releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
408 }
409
Greg Danielf2336e42018-01-23 16:38:14 -0500410 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Greg Daniel6a0176b2018-01-30 09:28:44 -0500411 [backendTex, ownership, releaseHelper]
Robert Phillipsce5209a2018-02-13 11:13:51 -0500412 (GrResourceProvider* resourceProvider) {
Greg Danielf2336e42018-01-23 16:38:14 -0500413 if (!resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500414 // If this had a releaseHelper it will get unrefed when we delete this lambda
415 // and will call the release proc so that the client knows they can free the
416 // underlying backend object.
Greg Danielf2336e42018-01-23 16:38:14 -0500417 return sk_sp<GrTexture>();
418 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500419
Greg Danielf2336e42018-01-23 16:38:14 -0500420 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex,
421 ownership);
422 if (!tex) {
423 return sk_sp<GrTexture>();
424 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500425 if (releaseHelper) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500426 // This gives the texture a ref on the releaseHelper
427 tex->setRelease(releaseHelper);
Greg Danielf2336e42018-01-23 16:38:14 -0500428 }
429 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
430 // Make sure we match how we created the proxy with SkBudgeted::kNo
431 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
432
433 return tex;
434 }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
435
436 if (fResourceProvider) {
437 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
438 // we're better off instantiating the proxy immediately here.
Greg Danielbddcc952018-01-24 13:22:24 -0500439 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
440 return nullptr;
441 }
Greg Danielf2336e42018-01-23 16:38:14 -0500442 }
443 return proxy;
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500444}
445
Greg Daniel6abda432018-02-15 14:55:00 -0500446sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(const GrBackendTexture& backendTex,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500447 GrSurfaceOrigin origin,
448 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500449 if (this->isAbandoned()) {
450 return nullptr;
451 }
452
Greg Daniel6abda432018-02-15 14:55:00 -0500453 sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config());
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500454
Greg Daniel6abda432018-02-15 14:55:00 -0500455 GrSurfaceDesc desc;
456 desc.fOrigin = origin;
457 desc.fWidth = backendTex.width();
458 desc.fHeight = backendTex.height();
459 desc.fConfig = backendTex.config();
460 desc.fFlags = kRenderTarget_GrSurfaceFlag;
461 desc.fSampleCnt = sampleCnt;
462 GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
463
Greg Daniel2a303902018-02-20 10:25:54 -0500464 GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
465 if (fCaps->usesMixedSamples() && sampleCnt > 1) {
466 renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
467 }
468 if (fCaps->maxWindowRectangles() > 0) {
469 renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
470 }
471
Greg Daniel6abda432018-02-15 14:55:00 -0500472 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
473 [backendTex, sampleCnt] (GrResourceProvider* resourceProvider) {
474 if (!resourceProvider) {
475 return sk_sp<GrTexture>();
476 }
477
478 sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture(backendTex,
479 sampleCnt);
480 if (!tex) {
481 return sk_sp<GrTexture>();
482 }
483 SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
484 // Make sure we match how we created the proxy with SkBudgeted::kNo
485 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
486
487 return tex;
Greg Daniel2a303902018-02-20 10:25:54 -0500488 }, desc, mipMapped, renderTargetFlags, SkBackingFit::kExact, SkBudgeted::kNo);
Greg Daniel6abda432018-02-15 14:55:00 -0500489
490 if (fResourceProvider) {
491 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
492 // we're better off instantiating the proxy immediately here.
493 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
494 return nullptr;
495 }
496 }
497 return proxy;
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500498}
499
500sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(
501 const GrBackendRenderTarget& backendRT,
502 GrSurfaceOrigin origin) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500503 if (this->isAbandoned()) {
504 return nullptr;
505 }
506
Greg Daniel2a303902018-02-20 10:25:54 -0500507 GrSurfaceDesc desc;
508 desc.fOrigin = origin;
509 desc.fWidth = backendRT.width();
510 desc.fHeight = backendRT.height();
511 desc.fConfig = backendRT.config();
512 desc.fFlags = kRenderTarget_GrSurfaceFlag;
513 desc.fSampleCnt = backendRT.sampleCnt();
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500514
Greg Daniel2a303902018-02-20 10:25:54 -0500515 GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
516 if (fCaps->isMixedSamplesSupportedForRT(backendRT) && backendRT.sampleCnt() > 1) {
517 renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
518 }
519 if (fCaps->isWindowRectanglesSupportedForRT(backendRT)) {
520 renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
521 }
522
523 sk_sp<GrRenderTargetProxy> proxy = this->createLazyRenderTargetProxy(
524 [backendRT] (GrResourceProvider* resourceProvider) {
525 if (!resourceProvider) {
526 return sk_sp<GrRenderTarget>();
527 }
528
529 sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT);
530 if (!rt) {
531 return sk_sp<GrRenderTarget>();
532 }
533 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
534 SkASSERT(!rt->getUniqueKey().isValid());
535 // Make sure we match how we created the proxy with SkBudgeted::kNo
536 SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
537
538 return rt;
539 }, desc, renderTargetFlags, Textureable::kNo, GrMipMapped::kNo, SkBackingFit::kExact,
540 SkBudgeted::kNo);
541
542 if (fResourceProvider) {
543 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
544 // we're better off instantiating the proxy immediately here.
545 if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
546 return nullptr;
547 }
548 }
549 return proxy;
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500550}
551
552sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(const GrBackendTexture& tex,
553 GrSurfaceOrigin origin,
554 int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500555 if (this->isAbandoned()) {
556 return nullptr;
557 }
558
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500559 sk_sp<GrRenderTarget> rt(fResourceProvider->wrapBackendTextureAsRenderTarget(tex, sampleCnt));
560 if (!rt) {
561 return nullptr;
562 }
563 SkASSERT(!rt->asTexture()); // Strictly a GrRenderTarget
564 SkASSERT(!rt->getUniqueKey().isValid());
565
566 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
567}
568
Robert Phillips777707b2018-01-17 11:40:14 -0500569sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
570 const GrSurfaceDesc& desc,
571 GrMipMapped mipMapped,
572 SkBackingFit fit, SkBudgeted budgeted) {
Greg Daniel2a303902018-02-20 10:25:54 -0500573 return this->createLazyProxy(std::move(callback), desc, mipMapped, GrRenderTargetFlags::kNone,
574 fit, budgeted);
575}
576
577sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
578 const GrSurfaceDesc& desc,
579 GrMipMapped mipMapped,
580 GrRenderTargetFlags renderTargetFlags,
581 SkBackingFit fit, SkBudgeted budgeted) {
Robert Phillips777707b2018-01-17 11:40:14 -0500582 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
583 (desc.fWidth > 0 && desc.fHeight > 0));
584 uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
Greg Daniel457469c2018-02-08 15:05:44 -0500585
Greg Daniel2a303902018-02-20 10:25:54 -0500586#ifdef SK_DEBUG
587 if (SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags)) {
588 if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kMixedSampled)) {
589 SkASSERT(fCaps->usesMixedSamples() && desc.fSampleCnt > 1);
590 }
591 if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kWindowRectsSupport)) {
592 SkASSERT(fCaps->maxWindowRectangles() > 0);
593 }
594 }
595#endif
596
Greg Daniel457469c2018-02-08 15:05:44 -0500597 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
598 // For non-ddl draws always make lazy proxy's single use.
599 LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
600 : LazyInstantiationType::kMultipleUse;
601
Robert Phillips777707b2018-01-17 11:40:14 -0500602 return sk_sp<GrTextureProxy>(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags) ?
Greg Daniel457469c2018-02-08 15:05:44 -0500603 new GrTextureRenderTargetProxy(std::move(callback), lazyType, desc,
Greg Daniel2a303902018-02-20 10:25:54 -0500604 mipMapped, fit, budgeted, flags,
605 renderTargetFlags) :
Greg Daniel457469c2018-02-08 15:05:44 -0500606 new GrTextureProxy(std::move(callback), lazyType, desc, mipMapped,
607 fit, budgeted, flags));
Robert Phillips777707b2018-01-17 11:40:14 -0500608}
609
Robert Phillipse8fabb22018-02-04 14:33:21 -0500610sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
611 LazyInstantiateCallback&& callback,
612 const GrSurfaceDesc& desc,
Greg Daniel2a303902018-02-20 10:25:54 -0500613 GrRenderTargetFlags renderTargetFlags,
Robert Phillipse8fabb22018-02-04 14:33:21 -0500614 Textureable textureable,
615 GrMipMapped mipMapped,
616 SkBackingFit fit, SkBudgeted budgeted) {
617 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
618 (desc.fWidth > 0 && desc.fHeight > 0));
Greg Daniel2a303902018-02-20 10:25:54 -0500619 SkASSERT(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500620 uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
Greg Daniel457469c2018-02-08 15:05:44 -0500621
Greg Daniel2a303902018-02-20 10:25:54 -0500622#ifdef SK_DEBUG
623 if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kMixedSampled)) {
624 SkASSERT(fCaps->usesMixedSamples() && desc.fSampleCnt > 1);
625 }
626 if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kWindowRectsSupport)) {
627 SkASSERT(fCaps->maxWindowRectangles() > 0);
628 }
629#endif
630
Greg Daniel457469c2018-02-08 15:05:44 -0500631 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
632 // For non-ddl draws always make lazy proxy's single use.
633 LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
634 : LazyInstantiationType::kMultipleUse;
635
Robert Phillipse8fabb22018-02-04 14:33:21 -0500636 if (Textureable::kYes == textureable) {
Greg Daniel457469c2018-02-08 15:05:44 -0500637 return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(std::move(callback),
638 lazyType, desc, mipMapped,
Greg Daniel2a303902018-02-20 10:25:54 -0500639 fit, budgeted, flags,
640 renderTargetFlags));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500641 }
642
Greg Daniel457469c2018-02-08 15:05:44 -0500643 return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(callback), lazyType, desc,
Greg Daniel2a303902018-02-20 10:25:54 -0500644 fit, budgeted, flags,
645 renderTargetFlags));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500646}
647
Robert Phillips777707b2018-01-17 11:40:14 -0500648sk_sp<GrTextureProxy> GrProxyProvider::createFullyLazyProxy(LazyInstantiateCallback&& callback,
649 Renderable renderable,
Robert Phillipsce5209a2018-02-13 11:13:51 -0500650 GrSurfaceOrigin origin,
Robert Phillips777707b2018-01-17 11:40:14 -0500651 GrPixelConfig config) {
652 GrSurfaceDesc desc;
Greg Daniel2a303902018-02-20 10:25:54 -0500653 GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
Robert Phillips777707b2018-01-17 11:40:14 -0500654 if (Renderable::kYes == renderable) {
655 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Greg Daniel2a303902018-02-20 10:25:54 -0500656 if (fCaps->maxWindowRectangles() > 0) {
657 renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
658 }
Robert Phillips777707b2018-01-17 11:40:14 -0500659 }
Robert Phillipsce5209a2018-02-13 11:13:51 -0500660 desc.fOrigin = origin;
Robert Phillips777707b2018-01-17 11:40:14 -0500661 desc.fWidth = -1;
662 desc.fHeight = -1;
663 desc.fConfig = config;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500664 desc.fSampleCnt = 1;
Robert Phillips777707b2018-01-17 11:40:14 -0500665
Greg Daniel2a303902018-02-20 10:25:54 -0500666 return this->createLazyProxy(std::move(callback), desc, GrMipMapped::kNo, renderTargetFlags,
Robert Phillips777707b2018-01-17 11:40:14 -0500667 SkBackingFit::kApprox, SkBudgeted::kYes);
668
669}
670
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500671bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
672 return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
673}
674
675void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
676 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
677 // will not be in 'fUniquelyKeyedProxies'.
678 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
679 if (proxy) {
680 this->processInvalidProxyUniqueKey(key, proxy, false);
681 }
682}
683
684void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
685 bool invalidateSurface) {
686 SkASSERT(proxy);
687 SkASSERT(proxy->getUniqueKey().isValid());
688 SkASSERT(proxy->getUniqueKey() == key);
689
690 fUniquelyKeyedProxies.remove(key);
691 proxy->cacheAccess().clearUniqueKey();
692
693 if (invalidateSurface && proxy->priv().isInstantiated()) {
694 GrSurface* surface = proxy->priv().peekSurface();
695 if (surface) {
696 surface->resourcePriv().removeUniqueKey();
697 }
698 }
699}
700
701void GrProxyProvider::removeAllUniqueKeys() {
702 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
703 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
704 GrTextureProxy& tmp = *iter;
705
706 this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
707 }
708 SkASSERT(!fUniquelyKeyedProxies.count());
709}