blob: 95c6a6ea441a1492f88d881ba04933c9203ef7e8 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrProxyProvider.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkBitmap.h"
11#include "include/core/SkImage.h"
12#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/gpu/GrTexture.h"
14#include "include/private/GrImageContext.h"
15#include "include/private/GrResourceKey.h"
16#include "include/private/GrSingleOwner.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#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"
Brian Salomon201cdbb2019-08-14 17:00:30 -040025#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrResourceProvider.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040027#include "src/gpu/GrSurfaceProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#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"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050033
34#define ASSERT_SINGLE_OWNER \
Robert Phillipsa41c6852019-02-07 10:44:10 -050035 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());)
Robert Phillips1afd4cd2018-01-08 13:40:32 -050036
Robert Phillipsa9162df2019-02-11 14:12:03 -050037GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
Robert Phillips1afd4cd2018-01-08 13:40:32 -050038
39GrProxyProvider::~GrProxyProvider() {
Robert Phillipsa41c6852019-02-07 10:44:10 -050040 if (this->renderingDirectly()) {
Robert Phillips0790f8a2018-09-18 13:11:03 -040041 // 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 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -050046}
47
Robert Phillipsadbe1322018-01-17 13:35:46 -050048bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050049 ASSERT_SINGLE_OWNER
50 SkASSERT(key.isValid());
51 if (this->isAbandoned() || !proxy) {
Robert Phillipsadbe1322018-01-17 13:35:46 -050052 return false;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050053 }
54
Robert Phillipsa41c6852019-02-07 10:44:10 -050055#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
Robert Phillips1afd4cd2018-01-08 13:40:32 -050067
Robert Phillips1afd4cd2018-01-08 13:40:32 -050068 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);
Robert Phillipsadbe1322018-01-17 13:35:46 -050073 return true;
Robert Phillips1afd4cd2018-01-08 13:40:32 -050074}
75
76void 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
Chris Dalton2de13dd2019-01-03 15:11:59 -070085void GrProxyProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050086 ASSERT_SINGLE_OWNER
Chris Dalton2de13dd2019-01-03 15:11:59 -070087 SkASSERT(proxy);
88 SkASSERT(proxy->getUniqueKey().isValid());
89
90 if (this->isAbandoned()) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050091 return;
92 }
Robert Phillips0790f8a2018-09-18 13:11:03 -040093
Chris Dalton2de13dd2019-01-03 15:11:59 -070094 this->processInvalidUniqueKey(proxy->getUniqueKey(), proxy, InvalidateGPUResource::kYes);
Robert Phillips1afd4cd2018-01-08 13:40:32 -050095}
96
97sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
98 GrSurfaceOrigin origin) {
99 ASSERT_SINGLE_OWNER
100
101 if (this->isAbandoned()) {
102 return nullptr;
103 }
104
Brian Salomon01ceae92019-04-02 11:49:54 -0400105 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
Brian Salomon01ceae92019-04-02 11:49:54 -0400106 if (proxy) {
Robert Phillipse5f73282019-06-18 17:15:04 -0400107 SkASSERT(proxy->origin() == origin);
108 return sk_ref_sp(proxy);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500109 }
Robert Phillipse5f73282019-06-18 17:15:04 -0400110 return nullptr;
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500111}
112
Robert Phillipsa41c6852019-02-07 10:44:10 -0500113///////////////////////////////////////////////////////////////////////////////
114
115#if GR_TEST_UTILS
116sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400117 const SkISize& dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400118 GrColorType colorType,
119 const GrBackendFormat& format,
120 GrRenderable renderable,
121 int renderTargetSampleCnt,
122 GrSurfaceOrigin origin,
123 SkBackingFit fit,
124 SkBudgeted budgeted,
125 GrProtected isProtected) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500126 ASSERT_SINGLE_OWNER
127 if (this->isAbandoned()) {
128 return nullptr;
129 }
Robert Phillipsa41c6852019-02-07 10:44:10 -0500130 GrContext* direct = fImageContext->priv().asDirectContext();
131 if (!direct) {
132 return nullptr;
133 }
134
Brian Salomon4eb38b72019-08-05 12:58:39 -0400135 if (this->caps()->isFormatCompressed(format)) {
136 // TODO: Allow this to go to GrResourceProvider::createCompressedTexture() once we no longer
Greg Daniel4cb29332020-01-23 10:07:02 -0500137 // rely on GrColorType to get a swizzle for the proxy.
Brian Salomon4eb38b72019-08-05 12:58:39 -0400138 return nullptr;
139 }
140 GrSurfaceDesc desc;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400141 desc.fWidth = dimensions.width();
142 desc.fHeight = dimensions.height();
Brian Salomon4eb38b72019-08-05 12:58:39 -0400143
Robert Phillipsa41c6852019-02-07 10:44:10 -0500144 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
145 sk_sp<GrTexture> tex;
146
147 if (SkBackingFit::kApprox == fit) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400148 tex = resourceProvider->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
Robert Phillipsaee18c92019-09-06 11:48:27 -0400149 isProtected);
Robert Phillipsa41c6852019-02-07 10:44:10 -0500150 } else {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400151 tex = resourceProvider->createTexture(desc, format, renderable, renderTargetSampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400152 GrMipMapped::kNo, budgeted, isProtected);
Robert Phillipsa41c6852019-02-07 10:44:10 -0500153 }
154 if (!tex) {
155 return nullptr;
156 }
157
Brian Salomonbeb7f522019-08-30 16:19:42 -0400158 return this->createWrapped(std::move(tex), colorType, origin, UseAllocator::kYes);
Robert Phillipsa41c6852019-02-07 10:44:10 -0500159}
160
Brian Salomon4eb38b72019-08-05 12:58:39 -0400161sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400162 const SkISize& dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400163 GrColorType colorType,
164 GrRenderable renderable,
165 int renderTargetSampleCnt,
166 GrSurfaceOrigin origin,
167 SkBackingFit fit,
168 SkBudgeted budgeted,
169 GrProtected isProtected) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500170 ASSERT_SINGLE_OWNER
171 if (this->isAbandoned()) {
172 return nullptr;
173 }
Brian Salomon4eb38b72019-08-05 12:58:39 -0400174 auto format = this->caps()->getDefaultBackendFormat(colorType, renderable);
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400175 return this->testingOnly_createInstantiatedProxy(dimensions,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400176 colorType,
177 format,
178 renderable,
179 renderTargetSampleCnt,
180 origin,
181 fit,
182 budgeted,
183 isProtected);
184}
185
Robert Phillipsa41c6852019-02-07 10:44:10 -0500186sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex,
Brian Salomon2af3e702019-08-11 19:10:31 -0400187 GrColorType colorType,
Robert Phillipsa41c6852019-02-07 10:44:10 -0500188 GrSurfaceOrigin origin) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400189 return this->createWrapped(std::move(tex), colorType, origin, UseAllocator::kYes);
Robert Phillipsa41c6852019-02-07 10:44:10 -0500190}
191#endif
192
Brian Salomonbeb7f522019-08-30 16:19:42 -0400193sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex,
194 GrColorType colorType,
195 GrSurfaceOrigin origin,
196 UseAllocator useAllocator) {
Robert Phillipsadbe1322018-01-17 13:35:46 -0500197#ifdef SK_DEBUG
198 if (tex->getUniqueKey().isValid()) {
199 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
200 }
201#endif
Greg Daniel14b57212019-12-17 16:18:06 -0500202 GrSwizzle readSwizzle = this->caps()->getReadSwizzle(tex->backendFormat(), colorType);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500203
204 if (tex->asRenderTarget()) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400205 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
Greg Daniel14b57212019-12-17 16:18:06 -0500206 std::move(tex), origin, readSwizzle, useAllocator));
Robert Phillipsadbe1322018-01-17 13:35:46 -0500207 } else {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400208 return sk_sp<GrTextureProxy>(
Greg Daniel14b57212019-12-17 16:18:06 -0500209 new GrTextureProxy(std::move(tex), origin, readSwizzle, useAllocator));
Robert Phillipsadbe1322018-01-17 13:35:46 -0500210 }
211}
212
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500213sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
Brian Salomon2af3e702019-08-11 19:10:31 -0400214 GrColorType colorType,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400215 GrSurfaceOrigin origin,
216 UseAllocator useAllocator) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500217 ASSERT_SINGLE_OWNER
218
219 if (this->isAbandoned()) {
220 return nullptr;
221 }
222
223 sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
224 if (result) {
225 return result;
226 }
227
Robert Phillipsa41c6852019-02-07 10:44:10 -0500228 GrContext* direct = fImageContext->priv().asDirectContext();
229 if (!direct) {
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500230 return nullptr;
231 }
232
Robert Phillipsa41c6852019-02-07 10:44:10 -0500233 GrResourceCache* resourceCache = direct->priv().getResourceCache();
234
235 GrGpuResource* resource = resourceCache->findAndRefUniqueResource(key);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500236 if (!resource) {
237 return nullptr;
238 }
239
240 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
241 SkASSERT(texture);
242
Brian Salomonbeb7f522019-08-30 16:19:42 -0400243 result = this->createWrapped(std::move(texture), colorType, origin, useAllocator);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500244 SkASSERT(result->getUniqueKey() == key);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500245 // createWrapped should've added this for us
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500246 SkASSERT(fUniquelyKeyedProxies.find(key));
Brian Salomon2af3e702019-08-11 19:10:31 -0400247 SkASSERT(result->textureSwizzle() ==
Greg Daniel14b57212019-12-17 16:18:06 -0500248 this->caps()->getReadSwizzle(result->backendFormat(), colorType));
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500249 return result;
250}
251
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500252sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500253 int sampleCnt,
Greg Danielfb3abcd2018-02-02 15:48:33 -0500254 SkBudgeted budgeted,
Chris Daltond004e0b2018-09-27 09:28:03 -0600255 SkBackingFit fit,
256 GrInternalSurfaceFlags surfaceFlags) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500257 ASSERT_SINGLE_OWNER
258 SkASSERT(srcImage);
259
260 if (this->isAbandoned()) {
261 return nullptr;
262 }
263
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400264 const SkImageInfo& info = srcImage->imageInfo();
Brian Salomon2af3e702019-08-11 19:10:31 -0400265 GrColorType ct = SkColorTypeToGrColorType(info.colorType());
Greg Danielf87651e2018-02-21 11:36:53 -0500266
Brian Salomon96b383a2019-08-13 16:55:41 -0400267 GrBackendFormat format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
Greg Daniel0a7aa142018-02-21 13:02:32 -0500268
Robert Phillips0a15cc62019-07-30 12:49:10 -0400269 if (!format.isValid()) {
Brian Osmand29dcd12018-09-13 15:04:29 -0400270 SkBitmap copy8888;
271 if (!copy8888.tryAllocPixels(info.makeColorType(kRGBA_8888_SkColorType)) ||
272 !srcImage->readPixels(copy8888.pixmap(), 0, 0)) {
273 return nullptr;
274 }
275 copy8888.setImmutable();
276 srcImage = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
Brian Salomon2af3e702019-08-11 19:10:31 -0400277 ct = GrColorType::kRGBA_8888;
Brian Salomon96b383a2019-08-13 16:55:41 -0400278 format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400279 if (!format.isValid()) {
280 return nullptr;
281 }
Brian Osmand29dcd12018-09-13 15:04:29 -0400282 }
283
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500284 GrSurfaceDesc desc;
285 desc.fWidth = srcImage->width();
286 desc.fHeight = srcImage->height();
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500287
Greg Danielce3ddaa2020-01-22 16:58:15 -0500288 GrSwizzle swizzle = this->caps()->getReadSwizzle(format, ct);
289
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500290 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Brian Salomon96b383a2019-08-13 16:55:41 -0400291 [desc, format, sampleCnt, budgeted, srcImage, fit,
Brian Salomon2af3e702019-08-11 19:10:31 -0400292 ct](GrResourceProvider* resourceProvider) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500293 SkPixmap pixMap;
294 SkAssertResult(srcImage->peekPixels(&pixMap));
295 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
296
Brian Salomonbeb7f522019-08-30 16:19:42 -0400297 return LazyCallbackResult(resourceProvider->createTexture(
Brian Salomona90382f2019-09-17 09:01:56 -0400298 desc, format, ct, GrRenderable::kNo, sampleCnt, budgeted, fit,
299 GrProtected::kNo, mipLevel));
Brian Salomon2a4f9832018-03-03 22:43:43 -0500300 },
Greg Danielce3ddaa2020-01-22 16:58:15 -0500301 format, desc, swizzle, GrRenderable::kNo, sampleCnt, kTopLeft_GrSurfaceOrigin,
302 GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, surfaceFlags, fit, budgeted,
303 GrProtected::kNo, UseAllocator::kYes);
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500304
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400305 if (!proxy) {
306 return nullptr;
307 }
308
Robert Phillipsa41c6852019-02-07 10:44:10 -0500309 GrContext* direct = fImageContext->priv().asDirectContext();
310 if (direct) {
311 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
312
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500313 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
314 // we're better off instantiating the proxy immediately here.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500315 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500316 return nullptr;
317 }
318 }
Robert Phillipsc1b60662018-06-26 10:20:08 -0400319
320 SkASSERT(proxy->width() == desc.fWidth);
321 SkASSERT(proxy->height() == desc.fHeight);
Greg Daniel9d86f1d2018-01-29 09:33:59 -0500322 return proxy;
323}
324
Brian Osmande496652019-03-22 13:42:33 -0400325sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
326 GrMipMapped mipMapped) {
Brian Osman412674f2019-02-07 15:34:58 -0500327 ASSERT_SINGLE_OWNER
Brian Osman7dcc6162019-03-25 10:12:57 -0400328 SkASSERT(GrMipMapped::kNo == mipMapped || this->caps()->mipMapSupport());
Brian Osman412674f2019-02-07 15:34:58 -0500329
330 if (this->isAbandoned()) {
331 return nullptr;
332 }
333
Brian Osman2b23c4b2018-06-01 12:25:08 -0400334 if (!SkImageInfoIsValid(bitmap.info())) {
Greg Daniela4ead652018-02-07 10:21:48 -0500335 return nullptr;
336 }
337
Brian Osmande496652019-03-22 13:42:33 -0400338 ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%ux%u]",
339 GrMipMapped::kYes == mipMapped ? "MipMap " : "",
340 bitmap.width(), bitmap.height());
Greg Daniela4ead652018-02-07 10:21:48 -0500341
342 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
343 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
344 // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500345 SkCopyPixelsMode copyMode = this->renderingDirectly() ? kNever_SkCopyPixelsMode
346 : kIfMutable_SkCopyPixelsMode;
Greg Daniela4ead652018-02-07 10:21:48 -0500347 sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
Greg Daniela4ead652018-02-07 10:21:48 -0500348 if (!baseLevel) {
349 return nullptr;
350 }
351
Brian Osmande496652019-03-22 13:42:33 -0400352 // If mips weren't requested (or this was too small to have any), then take the fast path
353 if (GrMipMapped::kNo == mipMapped ||
354 0 == SkMipMap::ComputeLevelCount(baseLevel->width(), baseLevel->height())) {
Brian Salomon96b383a2019-08-13 16:55:41 -0400355 return this->createTextureProxy(std::move(baseLevel), 1, SkBudgeted::kYes,
356 SkBackingFit::kExact);
Greg Daniela4ead652018-02-07 10:21:48 -0500357 }
358
Brian Osmand29dcd12018-09-13 15:04:29 -0400359 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
Greg Daniel3fc5df42019-06-14 09:42:17 -0400360
Greg Danielce3ddaa2020-01-22 16:58:15 -0500361 GrColorType grCT = SkColorTypeToGrColorType(bitmap.info().colorType());
362 GrBackendFormat format = this->caps()->getDefaultBackendFormat(grCT, GrRenderable::kNo);
Robert Phillips0a15cc62019-07-30 12:49:10 -0400363 if (!format.isValid()) {
Greg Daniel82c6b102020-01-21 10:33:22 -0500364 return nullptr;
Greg Daniel3fc5df42019-06-14 09:42:17 -0400365 }
366
Brian Osmand29dcd12018-09-13 15:04:29 -0400367 SkPixmap pixmap;
368 SkAssertResult(baseLevel->peekPixels(&pixmap));
369 sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, nullptr));
Brian Osmanbc6b9cb2018-09-13 13:43:25 -0400370 if (!mipmaps) {
371 return nullptr;
372 }
373
Greg Danielce3ddaa2020-01-22 16:58:15 -0500374 GrSwizzle readSwizzle = this->caps()->getReadSwizzle(format, grCT);
375
Greg Daniela4ead652018-02-07 10:21:48 -0500376 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Brian Salomon4eb38b72019-08-05 12:58:39 -0400377 [desc, format, baseLevel, mipmaps](GrResourceProvider* resourceProvider) {
Brian Osman1b97f132018-09-13 17:33:48 +0000378 const int mipLevelCount = mipmaps->countLevels() + 1;
379 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
380
Greg Daniela4ead652018-02-07 10:21:48 -0500381 SkPixmap pixmap;
382 SkAssertResult(baseLevel->peekPixels(&pixmap));
383
Greg Daniela4ead652018-02-07 10:21:48 -0500384 texels[0].fPixels = pixmap.addr();
385 texels[0].fRowBytes = pixmap.rowBytes();
386
Brian Salomona90382f2019-09-17 09:01:56 -0400387 auto colorType = SkColorTypeToGrColorType(pixmap.colorType());
Greg Daniela4ead652018-02-07 10:21:48 -0500388 for (int i = 1; i < mipLevelCount; ++i) {
389 SkMipMap::Level generatedMipLevel;
390 mipmaps->getLevel(i - 1, &generatedMipLevel);
391 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
392 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
393 SkASSERT(texels[i].fPixels);
Brian Salomona90382f2019-09-17 09:01:56 -0400394 SkASSERT(generatedMipLevel.fPixmap.colorType() == pixmap.colorType());
Greg Daniela4ead652018-02-07 10:21:48 -0500395 }
Brian Salomonbeb7f522019-08-30 16:19:42 -0400396 return LazyCallbackResult(resourceProvider->createTexture(
Brian Salomona90382f2019-09-17 09:01:56 -0400397 desc, format, colorType, GrRenderable::kNo, 1, SkBudgeted::kYes,
398 GrProtected::kNo, texels.get(), mipLevelCount));
Brian Salomon2a4f9832018-03-03 22:43:43 -0500399 },
Greg Danielce3ddaa2020-01-22 16:58:15 -0500400 format, desc, readSwizzle, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin,
401 GrMipMapped::kYes, GrMipMapsStatus::kValid, GrInternalSurfaceFlags::kNone,
402 SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes);
Greg Daniela4ead652018-02-07 10:21:48 -0500403
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400404 if (!proxy) {
405 return nullptr;
406 }
407
Robert Phillipsa41c6852019-02-07 10:44:10 -0500408 GrContext* direct = fImageContext->priv().asDirectContext();
409 if (direct) {
410 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
Greg Daniela4ead652018-02-07 10:21:48 -0500411 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
412 // we're better off instantiating the proxy immediately here.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500413 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
Greg Daniela4ead652018-02-07 10:21:48 -0500414 return nullptr;
415 }
416 }
417 return proxy;
418}
419
Greg Daniel4065d452018-11-16 15:43:41 -0500420sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format,
421 const GrSurfaceDesc& desc,
Greg Daniel47c20e82020-01-21 14:29:57 -0500422 GrSwizzle readSwizzle,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400423 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400424 int renderTargetSampleCnt,
Brian Salomon2a4f9832018-03-03 22:43:43 -0500425 GrSurfaceOrigin origin,
Greg Danielf6f7b672018-02-15 13:06:26 -0500426 GrMipMapped mipMapped,
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500427 SkBackingFit fit,
428 SkBudgeted budgeted,
Brian Salomone8a766b2019-07-19 14:24:36 -0400429 GrProtected isProtected,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400430 GrInternalSurfaceFlags surfaceFlags,
431 GrSurfaceProxy::UseAllocator useAllocator) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500432 ASSERT_SINGLE_OWNER
433 if (this->isAbandoned()) {
434 return nullptr;
435 }
436
Robert Phillips8ff8bcc2019-07-29 17:03:35 -0400437 const GrCaps* caps = this->caps();
438
439 if (caps->isFormatCompressed(format)) {
Brian Salomonbb8dde82019-06-27 10:52:13 -0400440 // Deferred proxies for compressed textures are not supported.
441 return nullptr;
442 }
Robert Phillips0902c982019-07-16 07:47:56 -0400443
Greg Danielf6f7b672018-02-15 13:06:26 -0500444 if (GrMipMapped::kYes == mipMapped) {
445 // SkMipMap doesn't include the base level in the level count so we have to add 1
446 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
447 if (1 == mipCount) {
448 mipMapped = GrMipMapped::kNo;
449 }
450 }
451
Greg Daniel9a48beb2020-01-16 16:57:16 -0500452 if (!caps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, renderable,
Greg Daniel6fa62e22019-08-07 15:52:37 -0400453 renderTargetSampleCnt, mipMapped)) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500454 return nullptr;
455 }
Brian Salomon3a2cc2c2018-02-03 00:25:12 +0000456 GrSurfaceDesc copyDesc = desc;
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600457 GrMipMapsStatus mipMapsStatus = (GrMipMapped::kYes == mipMapped)
458 ? GrMipMapsStatus::kDirty
459 : GrMipMapsStatus::kNotAllocated;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400460 if (renderable == GrRenderable::kYes) {
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400461 renderTargetSampleCnt =
Greg Daniel6fa62e22019-08-07 15:52:37 -0400462 caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
463 SkASSERT(renderTargetSampleCnt);
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500464 // We know anything we instantiate later from this deferred path will be
465 // both texturable and renderable
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400466 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600467 *caps, format, copyDesc, renderTargetSampleCnt, origin, mipMapped, mipMapsStatus,
Greg Daniel14b57212019-12-17 16:18:06 -0500468 readSwizzle, fit, budgeted, isProtected, surfaceFlags, useAllocator));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500469 }
470
Brian Salomonbeb7f522019-08-30 16:19:42 -0400471 return sk_sp<GrTextureProxy>(new GrTextureProxy(format, copyDesc, origin, mipMapped,
Greg Daniel14b57212019-12-17 16:18:06 -0500472 mipMapsStatus, readSwizzle, fit, budgeted,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400473 isProtected, surfaceFlags, useAllocator));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500474}
475
Brian Salomonbb8dde82019-06-27 10:52:13 -0400476sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
Robert Phillips3a833922020-01-21 15:25:58 -0500477 SkISize dimensions, SkBudgeted budgeted, GrMipMapped mipMapped, GrProtected isProtected,
Robert Phillipse4720c62020-01-14 14:33:24 -0500478 SkImage::CompressionType compressionType, sk_sp<SkData> data) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500479 ASSERT_SINGLE_OWNER
480 if (this->isAbandoned()) {
481 return nullptr;
482 }
Brian Salomonbb8dde82019-06-27 10:52:13 -0400483
484 GrSurfaceDesc desc;
Robert Phillips9f744f72019-12-19 19:14:33 -0500485 desc.fWidth = dimensions.width();
486 desc.fHeight = dimensions.height();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400487
Robert Phillips8ff8bcc2019-07-29 17:03:35 -0400488 GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
489
Greg Daniel7bfc9132019-08-14 14:23:53 -0400490 if (!this->caps()->isFormatTexturable(format)) {
Jim Van Verthee06b332019-01-18 10:36:32 -0500491 return nullptr;
492 }
493
Robert Phillipse4720c62020-01-14 14:33:24 -0500494 GrMipMapsStatus mipMapsStatus = (GrMipMapped::kYes == mipMapped)
495 ? GrMipMapsStatus::kValid
496 : GrMipMapsStatus::kNotAllocated;
497
Jim Van Verthee06b332019-01-18 10:36:32 -0500498 sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
Robert Phillips3a833922020-01-21 15:25:58 -0500499 [dimensions, format, budgeted, mipMapped, isProtected, data]
500 (GrResourceProvider* resourceProvider) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400501 return LazyCallbackResult(resourceProvider->createCompressedTexture(
Robert Phillips3a833922020-01-21 15:25:58 -0500502 dimensions, format, budgeted, mipMapped, isProtected, data.get()));
Brian Salomonbb8dde82019-06-27 10:52:13 -0400503 },
Greg Danielce3ddaa2020-01-22 16:58:15 -0500504 format, desc, GrSwizzle(), GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, mipMapped,
Robert Phillipse4720c62020-01-14 14:33:24 -0500505 mipMapsStatus, GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400506 SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes);
Jim Van Verthee06b332019-01-18 10:36:32 -0500507
508 if (!proxy) {
509 return nullptr;
510 }
511
Robert Phillipsa41c6852019-02-07 10:44:10 -0500512 GrContext* direct = fImageContext->priv().asDirectContext();
513 if (direct) {
514 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
Jim Van Verthee06b332019-01-18 10:36:32 -0500515 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
516 // we're better off instantiating the proxy immediately here.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500517 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
Jim Van Verthee06b332019-01-18 10:36:32 -0500518 return nullptr;
519 }
520 }
521 return proxy;
522}
523
Brian Salomon7578f3e2018-03-07 14:39:54 -0500524sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400525 GrColorType grColorType,
Brian Salomon7578f3e2018-03-07 14:39:54 -0500526 GrSurfaceOrigin origin,
527 GrWrapOwnership ownership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500528 GrWrapCacheable cacheable,
Brian Salomonc67c31c2018-12-06 10:00:03 -0500529 GrIOType ioType,
Brian Salomon7578f3e2018-03-07 14:39:54 -0500530 ReleaseProc releaseProc,
531 ReleaseContext releaseCtx) {
Brian Salomonc67c31c2018-12-06 10:00:03 -0500532 SkASSERT(ioType != kWrite_GrIOType);
Robert Phillipsf9bec202018-01-16 09:21:01 -0500533 if (this->isAbandoned()) {
534 return nullptr;
535 }
536
Brian Salomonf7778972018-03-08 10:13:17 -0500537 // This is only supported on a direct GrContext.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500538 GrContext* direct = fImageContext->priv().asDirectContext();
539 if (!direct) {
Brian Salomonf7778972018-03-08 10:13:17 -0500540 return nullptr;
541 }
542
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400543 const GrCaps* caps = this->caps();
544
Robert Phillipsa41c6852019-02-07 10:44:10 -0500545 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
546
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500547 sk_sp<GrTexture> tex =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400548 resourceProvider->wrapBackendTexture(backendTex, grColorType,
549 ownership, cacheable, ioType);
Brian Salomonf7778972018-03-08 10:13:17 -0500550 if (!tex) {
551 return nullptr;
552 }
Robert Phillipsadbe1322018-01-17 13:35:46 -0500553
Greg Daniel6a0176b2018-01-30 09:28:44 -0500554 if (releaseProc) {
Brian Salomonb2c5dae2019-03-04 10:25:17 -0500555 tex->setRelease(releaseProc, releaseCtx);
Greg Daniel6a0176b2018-01-30 09:28:44 -0500556 }
557
Brian Salomonf7778972018-03-08 10:13:17 -0500558 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
559 // Make sure we match how we created the proxy with SkBudgeted::kNo
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500560 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500561
Greg Daniel14b57212019-12-17 16:18:06 -0500562 GrSwizzle readSwizzle = caps->getReadSwizzle(tex->backendFormat(), grColorType);
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400563
Brian Salomonbeb7f522019-08-30 16:19:42 -0400564 return sk_sp<GrTextureProxy>(
Greg Daniel14b57212019-12-17 16:18:06 -0500565 new GrTextureProxy(std::move(tex), origin, readSwizzle, UseAllocator::kNo));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500566}
567
Robert Phillipsead321b2019-12-19 10:16:32 -0500568sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(const GrBackendTexture& beTex,
569 GrSurfaceOrigin origin,
570 GrWrapOwnership ownership,
571 GrWrapCacheable cacheable,
572 ReleaseProc releaseProc,
573 ReleaseContext releaseCtx) {
574 if (this->isAbandoned()) {
575 return nullptr;
576 }
577
578 // This is only supported on a direct GrContext.
579 GrContext* direct = fImageContext->priv().asDirectContext();
580 if (!direct) {
581 return nullptr;
582 }
583
Robert Phillipsb0855272020-01-15 12:56:52 -0500584 const GrCaps* caps = this->caps();
585
Robert Phillipsead321b2019-12-19 10:16:32 -0500586 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
587
588 sk_sp<GrTexture> tex = resourceProvider->wrapCompressedBackendTexture(beTex, ownership,
589 cacheable);
590 if (!tex) {
591 return nullptr;
592 }
593
594 if (releaseProc) {
595 tex->setRelease(releaseProc, releaseCtx);
596 }
597
598 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
599 // Make sure we match how we created the proxy with SkBudgeted::kNo
600 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
601
Robert Phillipsb0855272020-01-15 12:56:52 -0500602 SkImage::CompressionType compressionType = caps->compressionType(beTex.getBackendFormat());
603
604 GrSwizzle texSwizzle = GrCompressionTypeIsOpaque(compressionType) ? GrSwizzle::RGB1()
605 : GrSwizzle::RGBA();
Robert Phillipsead321b2019-12-19 10:16:32 -0500606
607 return sk_sp<GrTextureProxy>(
608 new GrTextureProxy(std::move(tex), origin, texSwizzle, UseAllocator::kNo));
609}
610
Brian Salomon7578f3e2018-03-07 14:39:54 -0500611sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
Brian Salomon02bd2952018-03-07 15:20:21 -0500612 const GrBackendTexture& backendTex, GrSurfaceOrigin origin, int sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400613 GrColorType colorType, GrWrapOwnership ownership, GrWrapCacheable cacheable,
614 ReleaseProc releaseProc, ReleaseContext releaseCtx) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500615 if (this->isAbandoned()) {
616 return nullptr;
617 }
618
Brian Salomonf7778972018-03-08 10:13:17 -0500619 // This is only supported on a direct GrContext.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500620 GrContext* direct = fImageContext->priv().asDirectContext();
621 if (!direct) {
Brian Salomonf7778972018-03-08 10:13:17 -0500622 return nullptr;
623 }
624
Robert Phillips0902c982019-07-16 07:47:56 -0400625 const GrCaps* caps = this->caps();
626
Robert Phillipsa41c6852019-02-07 10:44:10 -0500627 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
628
Greg Daniel6fa62e22019-08-07 15:52:37 -0400629 // TODO: This should have been checked and validated before getting into GrProxyProvider.
630 if (!caps->isFormatAsColorTypeRenderable(colorType, backendTex.getBackendFormat(), sampleCnt)) {
Greg Danielf87651e2018-02-21 11:36:53 -0500631 return nullptr;
632 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500633
Greg Daniel6fa62e22019-08-07 15:52:37 -0400634 sampleCnt = caps->getRenderTargetSampleCount(sampleCnt, backendTex.getBackendFormat());
635 SkASSERT(sampleCnt);
636
Robert Phillipsa41c6852019-02-07 10:44:10 -0500637 sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture(backendTex, sampleCnt,
Robert Phillips0902c982019-07-16 07:47:56 -0400638 colorType, ownership,
639 cacheable);
Brian Salomonf7778972018-03-08 10:13:17 -0500640 if (!tex) {
641 return nullptr;
Greg Daniel2a303902018-02-20 10:25:54 -0500642 }
643
Greg Daniel8ce79912019-02-05 10:08:43 -0500644 if (releaseProc) {
Brian Salomonb2c5dae2019-03-04 10:25:17 -0500645 tex->setRelease(releaseProc, releaseCtx);
Greg Daniel8ce79912019-02-05 10:08:43 -0500646 }
647
Brian Salomonf7778972018-03-08 10:13:17 -0500648 SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
649 // Make sure we match how we created the proxy with SkBudgeted::kNo
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500650 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
Greg Daniel6abda432018-02-15 14:55:00 -0500651
Greg Daniel14b57212019-12-17 16:18:06 -0500652 GrSwizzle readSwizzle = caps->getReadSwizzle(tex->backendFormat(), colorType);
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400653
Greg Daniel14b57212019-12-17 16:18:06 -0500654 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin, readSwizzle,
Greg Danielbaf8d992019-10-29 14:14:32 -0400655 UseAllocator::kNo));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500656}
657
Brian Salomon7578f3e2018-03-07 14:39:54 -0500658sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400659 const GrBackendRenderTarget& backendRT, GrColorType grColorType,
660 GrSurfaceOrigin origin, ReleaseProc releaseProc, ReleaseContext releaseCtx) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500661 if (this->isAbandoned()) {
662 return nullptr;
663 }
664
Brian Salomonf7778972018-03-08 10:13:17 -0500665 // This is only supported on a direct GrContext.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500666 GrContext* direct = fImageContext->priv().asDirectContext();
667 if (!direct) {
Brian Salomonf7778972018-03-08 10:13:17 -0500668 return nullptr;
Greg Daniel2a303902018-02-20 10:25:54 -0500669 }
670
Robert Phillips62221e72019-07-24 15:07:38 -0400671 const GrCaps* caps = this->caps();
672
Robert Phillipsa41c6852019-02-07 10:44:10 -0500673 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
674
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400675 sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT, grColorType);
Brian Salomonf7778972018-03-08 10:13:17 -0500676 if (!rt) {
677 return nullptr;
Greg Daniel2a303902018-02-20 10:25:54 -0500678 }
Greg Daniel8ce79912019-02-05 10:08:43 -0500679
Greg Daniel8ce79912019-02-05 10:08:43 -0500680 if (releaseProc) {
Brian Salomon2ca31f82019-03-05 13:28:58 -0500681 rt->setRelease(releaseProc, releaseCtx);
Greg Daniel8ce79912019-02-05 10:08:43 -0500682 }
683
Brian Salomonf7778972018-03-08 10:13:17 -0500684 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
685 SkASSERT(!rt->getUniqueKey().isValid());
686 // Make sure we match how we created the proxy with SkBudgeted::kNo
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500687 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
Brian Salomonf7778972018-03-08 10:13:17 -0500688
Greg Daniel14b57212019-12-17 16:18:06 -0500689 GrSwizzle readSwizzle = caps->getReadSwizzle(rt->backendFormat(), grColorType);
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400690
Greg Daniel14b57212019-12-17 16:18:06 -0500691 return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), origin, readSwizzle,
Greg Danielbaf8d992019-10-29 14:14:32 -0400692 UseAllocator::kNo));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500693}
694
Brian Salomon7578f3e2018-03-07 14:39:54 -0500695sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400696 const GrBackendTexture& backendTex, GrColorType grColorType,
697 GrSurfaceOrigin origin, int sampleCnt) {
Robert Phillipsf9bec202018-01-16 09:21:01 -0500698 if (this->isAbandoned()) {
699 return nullptr;
700 }
701
Brian Salomonf7778972018-03-08 10:13:17 -0500702 // This is only supported on a direct GrContext.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500703 GrContext* direct = fImageContext->priv().asDirectContext();
704 if (!direct) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500705 return nullptr;
706 }
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500707
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400708 const GrCaps* caps = this->caps();
709
Robert Phillipsa41c6852019-02-07 10:44:10 -0500710 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
711
Brian Salomonf7778972018-03-08 10:13:17 -0500712 sk_sp<GrRenderTarget> rt =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400713 resourceProvider->wrapBackendTextureAsRenderTarget(backendTex, sampleCnt, grColorType);
Brian Salomonf7778972018-03-08 10:13:17 -0500714 if (!rt) {
715 return nullptr;
Greg Danielf87651e2018-02-21 11:36:53 -0500716 }
Brian Salomonf7778972018-03-08 10:13:17 -0500717 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
718 SkASSERT(!rt->getUniqueKey().isValid());
Greg Danielb46add82019-01-02 14:51:29 -0500719 // This proxy should be unbudgeted because we're just wrapping an external resource
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500720 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
Greg Danielf87651e2018-02-21 11:36:53 -0500721
Greg Daniel14b57212019-12-17 16:18:06 -0500722 GrSwizzle readSwizzle = caps->getReadSwizzle(rt->backendFormat(), grColorType);
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400723
Greg Daniel14b57212019-12-17 16:18:06 -0500724 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin, readSwizzle,
Greg Danielbaf8d992019-10-29 14:14:32 -0400725 UseAllocator::kNo));
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500726}
727
Greg Danielb46add82019-01-02 14:51:29 -0500728sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
729 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
730 if (this->isAbandoned()) {
731 return nullptr;
732 }
733
734 // This is only supported on a direct GrContext.
Robert Phillipsa41c6852019-02-07 10:44:10 -0500735 GrContext* direct = fImageContext->priv().asDirectContext();
736 if (!direct) {
Greg Danielb46add82019-01-02 14:51:29 -0500737 return nullptr;
738 }
739
Robert Phillipsa41c6852019-02-07 10:44:10 -0500740 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
Greg Danielb46add82019-01-02 14:51:29 -0500741
Robert Phillipsa41c6852019-02-07 10:44:10 -0500742 sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
743 vkInfo);
Greg Danielb46add82019-01-02 14:51:29 -0500744 if (!rt) {
745 return nullptr;
746 }
Robert Phillipsa41c6852019-02-07 10:44:10 -0500747
Greg Danielb46add82019-01-02 14:51:29 -0500748 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
749 SkASSERT(!rt->getUniqueKey().isValid());
750 // This proxy should be unbudgeted because we're just wrapping an external resource
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500751 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
Greg Danielb46add82019-01-02 14:51:29 -0500752
Brian Salomon1c53a9f2019-08-12 14:10:12 -0400753 GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType());
Greg Daniel14b57212019-12-17 16:18:06 -0500754 GrSwizzle readSwizzle = this->caps()->getReadSwizzle(rt->backendFormat(), colorType);
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400755
Brian Salomon1c53a9f2019-08-12 14:10:12 -0400756 if (!this->caps()->isFormatAsColorTypeRenderable(colorType, rt->backendFormat(),
757 rt->numSamples())) {
758 return nullptr;
759 }
760
Greg Danielb46add82019-01-02 14:51:29 -0500761 // All Vulkan surfaces uses top left origins.
Brian Salomonbeb7f522019-08-30 16:19:42 -0400762 return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
Greg Daniel14b57212019-12-17 16:18:06 -0500763 std::move(rt), kTopLeft_GrSurfaceOrigin, readSwizzle, UseAllocator::kNo,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400764 GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
Brian Salomone8a766b2019-07-19 14:24:36 -0400765}
766
767sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
768 const GrBackendFormat& format,
769 const GrSurfaceDesc& desc,
Greg Danielce3ddaa2020-01-22 16:58:15 -0500770 GrSwizzle readSwizzle,
Brian Salomone8a766b2019-07-19 14:24:36 -0400771 GrRenderable renderable,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400772 int renderTargetSampleCnt,
Brian Salomone8a766b2019-07-19 14:24:36 -0400773 GrSurfaceOrigin origin,
774 GrMipMapped mipMapped,
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600775 GrMipMapsStatus mipMapsStatus,
Brian Salomone8a766b2019-07-19 14:24:36 -0400776 GrInternalSurfaceFlags surfaceFlags,
777 SkBackingFit fit,
778 SkBudgeted budgeted,
779 GrProtected isProtected,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400780 GrSurfaceProxy::UseAllocator useAllocator) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500781 ASSERT_SINGLE_OWNER
782 if (this->isAbandoned()) {
783 return nullptr;
784 }
Robert Phillips777707b2018-01-17 11:40:14 -0500785 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
786 (desc.fWidth > 0 && desc.fHeight > 0));
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400787
Robert Phillips0a15cc62019-07-30 12:49:10 -0400788 if (!format.isValid()) {
789 return nullptr;
790 }
791
Robert Phillipsa41c6852019-02-07 10:44:10 -0500792 if (desc.fWidth > this->caps()->maxTextureSize() ||
793 desc.fHeight > this->caps()->maxTextureSize()) {
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400794 return nullptr;
795 }
796
Brian Salomonbeb7f522019-08-30 16:19:42 -0400797 if (renderable == GrRenderable::kYes) {
798 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*this->caps(),
799 std::move(callback),
800 format,
801 desc,
802 renderTargetSampleCnt,
803 origin,
804 mipMapped,
805 mipMapsStatus,
Greg Daniel14b57212019-12-17 16:18:06 -0500806 readSwizzle,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400807 fit,
808 budgeted,
809 isProtected,
810 surfaceFlags,
811 useAllocator));
812 } else {
813 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
814 format,
815 desc,
816 origin,
817 mipMapped,
818 mipMapsStatus,
Greg Daniel14b57212019-12-17 16:18:06 -0500819 readSwizzle,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400820 fit,
821 budgeted,
822 isProtected,
823 surfaceFlags,
824 useAllocator));
825 }
Robert Phillips777707b2018-01-17 11:40:14 -0500826}
827
Robert Phillipse8fabb22018-02-04 14:33:21 -0500828sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
Brian Salomonbeb7f522019-08-30 16:19:42 -0400829 LazyInstantiateCallback&& callback,
830 const GrBackendFormat& format,
831 const GrSurfaceDesc& desc,
Greg Danielce3ddaa2020-01-22 16:58:15 -0500832 GrSwizzle readSwizzle,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400833 int sampleCnt,
834 GrSurfaceOrigin origin,
835 GrInternalSurfaceFlags surfaceFlags,
836 const TextureInfo* textureInfo,
837 GrMipMapsStatus mipMapsStatus,
838 SkBackingFit fit,
839 SkBudgeted budgeted,
840 GrProtected isProtected,
841 bool wrapsVkSecondaryCB,
842 UseAllocator useAllocator) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500843 ASSERT_SINGLE_OWNER
844 if (this->isAbandoned()) {
845 return nullptr;
846 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500847 SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
848 (desc.fWidth > 0 && desc.fHeight > 0));
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400849
Robert Phillipsa41c6852019-02-07 10:44:10 -0500850 if (desc.fWidth > this->caps()->maxRenderTargetSize() ||
851 desc.fHeight > this->caps()->maxRenderTargetSize()) {
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400852 return nullptr;
853 }
854
Brian Salomon7226c232018-07-30 13:13:17 -0400855 if (textureInfo) {
Greg Danielb085fa92019-03-05 16:55:12 -0500856 // Wrapped vulkan secondary command buffers don't support texturing since we won't have an
857 // actual VkImage to texture from.
858 SkASSERT(!wrapsVkSecondaryCB);
Brian Salomon7226c232018-07-30 13:13:17 -0400859 return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
Brian Salomonbeb7f522019-08-30 16:19:42 -0400860 *this->caps(), std::move(callback), format, desc, sampleCnt, origin,
Greg Daniel14b57212019-12-17 16:18:06 -0500861 textureInfo->fMipMapped, mipMapsStatus, readSwizzle, fit, budgeted, isProtected,
Greg Danielbaf8d992019-10-29 14:14:32 -0400862 surfaceFlags, useAllocator));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500863 }
864
Greg Danielb085fa92019-03-05 16:55:12 -0500865 GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
866 wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes
867 : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo;
868
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400869 return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
Greg Daniel14b57212019-12-17 16:18:06 -0500870 std::move(callback), format, desc, sampleCnt, origin, readSwizzle, fit, budgeted,
Greg Danielbaf8d992019-10-29 14:14:32 -0400871 isProtected, surfaceFlags, useAllocator, vkSCB));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500872}
873
Brian Salomonbeb7f522019-08-30 16:19:42 -0400874sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallback&& callback,
875 const GrBackendFormat& format,
Greg Danielce3ddaa2020-01-22 16:58:15 -0500876 GrSwizzle readSwizzle,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400877 GrRenderable renderable,
878 int renderTargetSampleCnt,
879 GrProtected isProtected,
880 GrSurfaceOrigin origin,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400881 const GrCaps& caps,
882 UseAllocator useAllocator) {
Robert Phillips0a15cc62019-07-30 12:49:10 -0400883 if (!format.isValid()) {
884 return nullptr;
885 }
886
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400887 SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes);
Robert Phillips777707b2018-01-17 11:40:14 -0500888 GrSurfaceDesc desc;
Robert Phillips10d17212019-04-24 14:09:10 -0400889 GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
Robert Phillips777707b2018-01-17 11:40:14 -0500890 desc.fWidth = -1;
891 desc.fHeight = -1;
Robert Phillips777707b2018-01-17 11:40:14 -0500892
Brian Salomonbeb7f522019-08-30 16:19:42 -0400893 if (GrRenderable::kYes == renderable) {
894 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
895 caps, std::move(callback), format, desc, renderTargetSampleCnt, origin,
Greg Daniel14b57212019-12-17 16:18:06 -0500896 GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, readSwizzle,
897 SkBackingFit::kApprox, SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator));
Brian Salomonbeb7f522019-08-30 16:19:42 -0400898 } else {
899 return sk_sp<GrTextureProxy>(new GrTextureProxy(
900 std::move(callback), format, desc, origin, GrMipMapped::kNo,
Greg Daniel14b57212019-12-17 16:18:06 -0500901 GrMipMapsStatus::kNotAllocated, readSwizzle, SkBackingFit::kApprox,
902 SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator));
Brian Salomonbeb7f522019-08-30 16:19:42 -0400903 }
Robert Phillips777707b2018-01-17 11:40:14 -0500904}
905
Robert Phillips427966a2018-12-20 17:20:43 -0500906void GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
907 InvalidateGPUResource invalidateGPUResource) {
Chris Dalton2de13dd2019-01-03 15:11:59 -0700908 SkASSERT(key.isValid());
909
Robert Phillips427966a2018-12-20 17:20:43 -0500910 if (!proxy) {
911 proxy = fUniquelyKeyedProxies.find(key);
912 }
Chris Dalton2de13dd2019-01-03 15:11:59 -0700913 SkASSERT(!proxy || proxy->getUniqueKey() == key);
914
915 // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the
916 // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
917 sk_sp<GrGpuResource> invalidGpuResource;
918 if (InvalidateGPUResource::kYes == invalidateGPUResource) {
Brian Salomon01ceae92019-04-02 11:49:54 -0400919 GrContext* direct = fImageContext->priv().asDirectContext();
920 if (direct) {
921 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
922 invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
Chris Dalton2de13dd2019-01-03 15:11:59 -0700923 }
924 SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
925 }
Robert Phillips427966a2018-12-20 17:20:43 -0500926
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500927 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
928 // will not be in 'fUniquelyKeyedProxies'.
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500929 if (proxy) {
Robert Phillips427966a2018-12-20 17:20:43 -0500930 fUniquelyKeyedProxies.remove(key);
931 proxy->cacheAccess().clearUniqueKey();
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500932 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500933
Chris Dalton2de13dd2019-01-03 15:11:59 -0700934 if (invalidGpuResource) {
935 invalidGpuResource->resourcePriv().removeUniqueKey();
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500936 }
937}
938
Robert Phillipsa41c6852019-02-07 10:44:10 -0500939uint32_t GrProxyProvider::contextID() const {
940 return fImageContext->priv().contextID();
941}
942
943const GrCaps* GrProxyProvider::caps() const {
944 return fImageContext->priv().caps();
945}
946
947sk_sp<const GrCaps> GrProxyProvider::refCaps() const {
948 return fImageContext->priv().refCaps();
949}
950
Robert Phillipsa9162df2019-02-11 14:12:03 -0500951bool GrProxyProvider::isAbandoned() const {
952 return fImageContext->priv().abandoned();
953}
954
Robert Phillips0790f8a2018-09-18 13:11:03 -0400955void GrProxyProvider::orphanAllUniqueKeys() {
956 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
957 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
958 GrTextureProxy& tmp = *iter;
959
960 tmp.fProxyProvider = nullptr;
961 }
962}
963
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500964void GrProxyProvider::removeAllUniqueKeys() {
965 UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
966 for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
967 GrTextureProxy& tmp = *iter;
968
Chris Dalton2de13dd2019-01-03 15:11:59 -0700969 this->processInvalidUniqueKey(tmp.getUniqueKey(), &tmp, InvalidateGPUResource::kNo);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500970 }
971 SkASSERT(!fUniquelyKeyedProxies.count());
972}
Robert Phillipsa41c6852019-02-07 10:44:10 -0500973
974bool GrProxyProvider::renderingDirectly() const {
975 return fImageContext->priv().asDirectContext();
976}