blob: 38867f28567b791f9b10601a3cc94c5e53913a78 [file] [log] [blame]
Jim Van Verthf49262d2018-10-02 12:07:20 -04001/*
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 <cstddef>
9#include <cstring>
10#include <type_traits>
11
Brian Salomonc2a9a972020-09-15 11:24:28 -040012#include "include/core/SkYUVAPixmaps.h"
Adlai Holler3a220172020-07-15 10:37:50 -040013#include "include/gpu/GrDirectContext.h"
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040014#include "include/gpu/GrRecordingContext.h"
Brian Salomonc1a249d2020-10-19 10:55:45 -040015#include "include/gpu/GrYUVABackendTextures.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkAutoPixmapStorage.h"
Mike Reed13711eb2020-07-14 17:16:32 -040017#include "src/core/SkMipmap.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/core/SkScopeExit.h"
Greg Daniel82c6b102020-01-21 10:33:22 -050019#include "src/gpu/GrBitmapTextureMaker.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrClip.h"
Adlai Hollera0693042020-10-14 11:23:11 -040021#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/gpu/GrGpu.h"
Adlai Holler302e8fb2020-09-14 11:58:06 -040023#include "src/gpu/GrImageContextPriv.h"
Brian Salomon8670c982020-12-08 16:39:32 -050024#include "src/gpu/GrProxyProvider.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrRecordingContextPriv.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050026#include "src/gpu/GrSurfaceDrawContext.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000027#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/gpu/GrTextureProducer.h"
29#include "src/gpu/SkGr.h"
30#include "src/gpu/effects/GrYUVtoRGBEffect.h"
31#include "src/image/SkImage_Gpu.h"
32#include "src/image/SkImage_GpuYUVA.h"
Jim Van Verthf49262d2018-10-02 12:07:20 -040033
Brian Salomon5ad6fd32019-03-21 15:30:08 -040034static constexpr auto kAssumedColorType = kRGBA_8888_SkColorType;
35
Adlai Holler302e8fb2020-09-14 11:58:06 -040036SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
Brian Salomonc505a452020-04-06 10:29:02 -040037 uint32_t uniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -050038 GrYUVATextureProxies proxies,
Greg Danielc594e622019-10-15 14:01:49 -040039 sk_sp<SkColorSpace> imageColorSpace)
Adlai Holler302e8fb2020-09-14 11:58:06 -040040 : INHERITED(std::move(context),
Brian Salomon0857bef2021-01-13 15:54:04 -050041 proxies.yuvaInfo().dimensions(),
Brian Salomonc505a452020-04-06 10:29:02 -040042 uniqueID,
43 kAssumedColorType,
Brian Salomon0857bef2021-01-13 15:54:04 -050044 // If an alpha channel is present we always use kPremul. This is because,
Jim Van Verth8026ccc2018-10-04 13:10:39 -040045 // although the planar data is always un-premul, the final interleaved RGB image
46 // is/would-be premul.
Brian Salomon0857bef2021-01-13 15:54:04 -050047 proxies.yuvaInfo().hasAlpha() ? kPremul_SkAlphaType : kOpaque_SkAlphaType,
Brian Salomonc505a452020-04-06 10:29:02 -040048 std::move(imageColorSpace))
Brian Salomon0857bef2021-01-13 15:54:04 -050049 , fYUVAProxies(std::move(proxies)) {
50 // The caller should have checked this, just verifying.
51 SkASSERT(fYUVAProxies.isValid());
Jim Van Verthf49262d2018-10-02 12:07:20 -040052}
53
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050054// For onMakeColorSpace()
Brian Salomon0c0b5a62021-01-11 14:40:44 -050055SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
56 const SkImage_GpuYUVA* image,
Adlai Holler3a220172020-07-15 10:37:50 -040057 sk_sp<SkColorSpace> targetCS)
Brian Salomon0c0b5a62021-01-11 14:40:44 -050058 : INHERITED(std::move(context),
59 image->dimensions(),
60 kNeedNewImageUniqueID,
Adlai Holler3a220172020-07-15 10:37:50 -040061 kAssumedColorType,
Brian Salomon0857bef2021-01-13 15:54:04 -050062 image->alphaType(),
Brian Salomon0c0b5a62021-01-11 14:40:44 -050063 std::move(targetCS))
Brian Salomon0857bef2021-01-13 15:54:04 -050064 , fYUVAProxies(image->fYUVAProxies)
65 , fRGBView(image->fRGBView)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040066 // Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
67 // image->refColorSpace() into an explicit SRGB.
68 , fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
Brian Salomon0857bef2021-01-13 15:54:04 -050069 // We should either have a RGB proxy *or* a set of YUVA proxies.
70 SkASSERT(fYUVAProxies.isValid() != SkToBool(image->fRGBView));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050071}
72
Robert Phillips8defcc12019-03-05 15:58:59 -050073bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
Brian Salomonad8efda2019-05-10 09:22:49 -040074 // We shouldn't get here if the planes were already flattened to RGBA.
Brian Salomon0857bef2021-01-13 15:54:04 -050075 SkASSERT(fYUVAProxies.isValid() && !fRGBView);
Robert Phillips8defcc12019-03-05 15:58:59 -050076 if (!context || !fContext->priv().matches(context)) {
77 return false;
78 }
Brian Salomon69100f02020-07-21 10:49:25 -040079 if (!context->priv().caps()->mipmapSupport()) {
Brian Salomon4759dca2020-07-14 15:44:15 -040080 // We succeed in this case by doing nothing.
81 return true;
82 }
Brian Salomon0857bef2021-01-13 15:54:04 -050083 int n = fYUVAProxies.yuvaInfo().numPlanes();
84 sk_sp<GrSurfaceProxy> newProxies[4];
85 for (int i = 0; i < n; ++i) {
86 auto* t = fYUVAProxies.proxy(i)->asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -040087 if (t->mipmapped() == GrMipmapped::kNo && (t->width() > 1 || t->height() > 1)) {
Brian Salomon0857bef2021-01-13 15:54:04 -050088 auto newView = GrCopyBaseMipMapToView(context, fYUVAProxies.makeView(i));
89 if (!newView) {
Jim Van Verthf542cab2018-11-07 12:08:21 -050090 return false;
91 }
Brian Salomon0857bef2021-01-13 15:54:04 -050092 SkASSERT(newView.swizzle() == fYUVAProxies.makeView(i).swizzle());
93 newProxies[i] = newView.detachProxy();
Brian Salomon4759dca2020-07-14 15:44:15 -040094 } else {
Brian Salomon0857bef2021-01-13 15:54:04 -050095 newProxies[i] = fYUVAProxies.refProxy(i);
Jim Van Verth30e0d7f2018-11-02 13:36:42 -040096 }
97 }
Brian Salomon0857bef2021-01-13 15:54:04 -050098 fYUVAProxies = GrYUVATextureProxies(fYUVAProxies.yuvaInfo(),
99 newProxies,
100 fYUVAProxies.textureOrigin());
101 SkASSERT(fYUVAProxies.isValid());
Jim Van Verth30e0d7f2018-11-02 13:36:42 -0400102 return true;
103}
104
Jim Van Verthf49262d2018-10-02 12:07:20 -0400105//////////////////////////////////////////////////////////////////////////////////////////////////
Jim Van Verthf49262d2018-10-02 12:07:20 -0400106
Adlai Holler40ad5fd2020-07-22 10:22:12 -0400107GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const GrFlushInfo& info) {
108 if (!fContext->priv().matches(dContext) || dContext->abandoned()) {
Greg Daniel55822f12020-05-26 11:26:45 -0400109 if (info.fSubmittedProc) {
110 info.fSubmittedProc(info.fSubmittedContext, false);
111 }
112 if (info.fFinishedProc) {
113 info.fFinishedProc(info.fFinishedContext);
114 }
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400115 return GrSemaphoresSubmitted::kNo;
116 }
117
Brian Salomon0857bef2021-01-13 15:54:04 -0500118 GrSurfaceProxy* proxies[SkYUVAInfo::kMaxPlanes] = {};
119 size_t numProxies;
120 if (fRGBView) {
Brian Salomonad8efda2019-05-10 09:22:49 -0400121 // Either we've already flushed the flattening draw or the flattening is unflushed. In the
Greg Daniel1a372c32019-12-17 13:53:38 -0500122 // latter case it should still be ok to just pass fRGBView proxy because it in turn depends
123 // on the planar proxies and will cause all of their work to flush as well.
124 proxies[0] = fRGBView.proxy();
Brian Salomonad8efda2019-05-10 09:22:49 -0400125 numProxies = 1;
Brian Salomon0857bef2021-01-13 15:54:04 -0500126 } else {
127 numProxies = fYUVAProxies.numPlanes();
128 for (size_t i = 0; i < numProxies; ++i) {
129 proxies[i] = fYUVAProxies.proxy(i);
130 }
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400131 }
Robert Phillips80bfda82020-11-12 09:23:36 -0500132 return dContext->priv().flushSurfaces({proxies, numProxies},
133 SkSurface::BackendSurfaceAccess::kNoAccess,
134 info);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400135}
136
Brian Salomon7d2757f2021-01-26 17:46:50 -0500137bool SkImage_GpuYUVA::onHasMipmaps() const {
138 if (fRGBView) {
139 return fRGBView.asTextureProxy()->mipmapped() == GrMipmapped::kYes;
140 }
141 return fYUVAProxies.mipmapped() == GrMipmapped::kYes;
142}
143
Brian Salomon650dd082021-02-11 08:59:03 -0500144size_t SkImage_GpuYUVA::onTextureSize() const {
145 if (fRGBView) {
146 return fRGBView.asTextureProxy()->gpuMemorySize();
147 }
148 size_t size = 0;
149 for (int i = 0; i < fYUVAProxies.numPlanes(); ++i) {
150 size += fYUVAProxies.proxy(i)->gpuMemorySize();
151 }
152 return size;
153}
154
Brian Salomond0924f32021-02-03 10:15:31 -0500155sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(SkColorType,
156 sk_sp<SkColorSpace> targetCS,
157 GrDirectContext* direct) const {
Brian Osmanf48c9962019-01-14 11:15:50 -0500158 // We explicitly ignore color type changes, for now.
159
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500160 // we may need a mutex here but for now we expect usage to be in a single thread
161 if (fOnMakeColorSpaceTarget &&
Brian Osmanf48c9962019-01-14 11:15:50 -0500162 SkColorSpace::Equals(targetCS.get(), fOnMakeColorSpaceTarget.get())) {
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500163 return fOnMakeColorSpaceResult;
164 }
Adlai Holler3a220172020-07-15 10:37:50 -0400165 sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(sk_ref_sp(direct), this, targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500166 if (result) {
Brian Osmanf48c9962019-01-14 11:15:50 -0500167 fOnMakeColorSpaceTarget = targetCS;
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500168 fOnMakeColorSpaceResult = result;
169 }
170 return result;
171}
172
Brian Osmand5148372019-08-14 16:14:51 -0400173sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Brian Salomon0857bef2021-01-13 15:54:04 -0500174 return sk_sp<SkImage>(new SkImage_GpuYUVA(fContext, this, std::move(newCS)));
Brian Osmand5148372019-08-14 16:14:51 -0400175}
176
Brian Salomond0924f32021-02-03 10:15:31 -0500177static GrSurfaceProxyView render_to_rgb(GrRecordingContext* context,
178 const SkColorInfo& colorInfo,
179 const GrYUVATextureProxies& proxies,
180 SkColorSpace* fromColorSpace,
181 GrMipmapped mipmapped,
182 SkBudgeted budgeted) {
183 GrImageInfo ii(colorInfo, proxies.yuvaInfo().dimensions());
184 auto surfaceFillContext = GrSurfaceFillContext::Make(context,
185 std::move(ii),
186 SkBackingFit::kExact,
187 /*sample count*/ 1,
188 mipmapped,
189 GrProtected::kNo,
190 kTopLeft_GrSurfaceOrigin,
191 budgeted);
192 if (!surfaceFillContext) {
193 return {};
194 }
195
196 const GrCaps& caps = *context->priv().caps();
197
198 auto fp = GrYUVtoRGBEffect::Make(proxies, GrSamplerState::Filter::kNearest, caps);
199 if (fromColorSpace) {
200 fp = GrColorSpaceXformEffect::Make(std::move(fp),
201 fromColorSpace, colorInfo.alphaType(),
202 colorInfo.colorSpace(), colorInfo.alphaType());
203 }
204
205 surfaceFillContext->fillWithFP(std::move(fp));
206
207 return surfaceFillContext->readSurfaceView();
208}
209
210bool SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context, GrMipmapped mipmapped) const {
211 if (fRGBView.proxy()) {
212 if (mipmapped == GrMipmapped::kYes &&
213 fRGBView.proxy()->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
214 GrSurfaceProxyView mippedView = GrCopyBaseMipMapToView(context, fRGBView);
215 if (!mippedView) {
216 return false;
217 }
218 fRGBView = std::move(mippedView);
219 return true;
220 }
221 return true;
222 }
223
224 if (!context || !fContext->priv().matches(context)) {
225 return false;
226 }
227
228 GrSurfaceProxyView rgbView = render_to_rgb(context,
229 this->imageInfo().colorInfo(),
230 fYUVAProxies,
231 fFromColorSpace.get(),
232 mipmapped,
233 SkBudgeted::kYes);
234 if (!rgbView) {
235 return false;
236 }
237 fRGBView = std::move(rgbView);
238 fYUVAProxies = {};
239 return true;
240}
241
242std::tuple<GrSurfaceProxyView, GrColorType> SkImage_GpuYUVA::onAsView(
243 GrRecordingContext* context,
244 GrMipmapped mipmapped,
245 GrImageTexGenPolicy policy) const {
246 if (!fContext->priv().matches(context)) {
247 return {};
248 }
249 if (policy != GrImageTexGenPolicy::kDraw) {
250 SkBudgeted budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Budgeted
251 ? SkBudgeted::kYes
252 : SkBudgeted::kNo;
253 if (fRGBView) {
254 return {CopyView(context, fRGBView, mipmapped, policy), GrColorType::kRGBA_8888};
255 }
256 auto view = render_to_rgb(context,
257 this->imageInfo().colorInfo(),
258 fYUVAProxies,
259 fFromColorSpace.get(),
260 mipmapped,
261 budgeted);
262 return {std::move(view), GrColorType::kRGBA_8888};
263 }
264 if (!this->flattenToRGB(context, mipmapped)) {
265 return {};
266 }
267 return {fRGBView, GrColorType::kRGBA_8888};
268}
269
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500270//////////////////////////////////////////////////////////////////////////////////////////////////
271
Brian Salomonc1a249d2020-10-19 10:55:45 -0400272sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
273 const GrYUVABackendTextures& yuvaTextures,
274 sk_sp<SkColorSpace> imageColorSpace,
275 TextureReleaseProc textureReleaseProc,
276 ReleaseContext releaseContext) {
Brian Salomon694ff172020-11-04 16:54:28 -0500277 auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
Brian Salomonc1a249d2020-10-19 10:55:45 -0400278
Brian Salomon0857bef2021-01-13 15:54:04 -0500279 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
280 int numPlanes = yuvaTextures.yuvaInfo().numPlanes();
281 sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes];
282 for (int plane = 0; plane < numPlanes; ++plane) {
283 proxies[plane] = proxyProvider->wrapBackendTexture(yuvaTextures.texture(plane),
284 kBorrow_GrWrapOwnership,
285 GrWrapCacheable::kNo,
286 kRead_GrIOType,
287 releaseHelper);
288 if (!proxies[plane]) {
289 return {};
290 }
291 }
292 GrYUVATextureProxies yuvaProxies(yuvaTextures.yuvaInfo(),
293 proxies,
294 yuvaTextures.textureOrigin());
Brian Salomonc1a249d2020-10-19 10:55:45 -0400295
Brian Salomon0857bef2021-01-13 15:54:04 -0500296 if (!yuvaProxies.isValid()) {
Brian Salomonc1a249d2020-10-19 10:55:45 -0400297 return nullptr;
298 }
299
300 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
Brian Salomonc1a249d2020-10-19 10:55:45 -0400301 kNeedNewImageUniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -0500302 yuvaProxies,
Brian Salomonc1a249d2020-10-19 10:55:45 -0400303 imageColorSpace);
304}
305
Adlai Holler302e8fb2020-09-14 11:58:06 -0400306sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400307 const SkYUVAPixmaps& pixmaps,
Brian Salomon0857bef2021-01-13 15:54:04 -0500308 GrMipmapped buildMips,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400309 bool limitToMaxTextureSize,
310 sk_sp<SkColorSpace> imageColorSpace) {
311 if (!context) {
312 return nullptr; // until we impl this for raster backend
313 }
314
315 if (!pixmaps.isValid()) {
316 return nullptr;
317 }
318
Brian Salomonc2a9a972020-09-15 11:24:28 -0400319 if (!context->priv().caps()->mipmapSupport()) {
320 buildMips = GrMipMapped::kNo;
321 }
322
Brian Salomon0857bef2021-01-13 15:54:04 -0500323 // Resize the pixmaps if necessary.
Brian Salomonc2a9a972020-09-15 11:24:28 -0400324 int numPlanes = pixmaps.numPlanes();
325 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Salomon0857bef2021-01-13 15:54:04 -0500326 int maxDim = std::max(pixmaps.yuvaInfo().width(), pixmaps.yuvaInfo().height());
327
328 SkYUVAPixmaps tempPixmaps;
329 const SkYUVAPixmaps* pixmapsToUpload = &pixmaps;
330 // We assume no plane is larger than the image size (and at least one plane is as big).
331 if (maxDim > maxTextureSize) {
332 if (!limitToMaxTextureSize) {
Brian Salomonb6025502021-01-12 20:37:49 -0500333 return nullptr;
334 }
Brian Salomon0857bef2021-01-13 15:54:04 -0500335 float scale = static_cast<float>(maxTextureSize)/maxDim;
336 SkISize newDimensions = {
337 std::min(static_cast<int>(pixmaps.yuvaInfo().width() *scale), maxTextureSize),
338 std::min(static_cast<int>(pixmaps.yuvaInfo().height()*scale), maxTextureSize)
339 };
340 SkYUVAInfo newInfo = pixmaps.yuvaInfo().makeDimensions(newDimensions);
341 SkYUVAPixmapInfo newPixmapInfo(newInfo, pixmaps.dataType(), /*row bytes*/ nullptr);
342 tempPixmaps = SkYUVAPixmaps::Allocate(newPixmapInfo);
Mike Reed5ec22382021-01-14 21:59:01 -0500343 SkSamplingOptions sampling(SkFilterMode::kLinear);
Brian Salomon0857bef2021-01-13 15:54:04 -0500344 if (!tempPixmaps.isValid()) {
345 return nullptr;
346 }
347 for (int i = 0; i < numPlanes; ++i) {
348 if (!pixmaps.plane(i).scalePixels(tempPixmaps.plane(i), sampling)) {
349 return nullptr;
350 }
351 }
352 pixmapsToUpload = &tempPixmaps;
Brian Salomonb6025502021-01-12 20:37:49 -0500353 }
354
Brian Salomon0857bef2021-01-13 15:54:04 -0500355 // Convert to texture proxies.
356 GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
357 GrColorType pixmapColorTypes[SkYUVAInfo::kMaxPlanes];
358 for (int i = 0; i < numPlanes; ++i) {
359 // Turn the pixmap into a GrTextureProxy
360 SkBitmap bmp;
361 bmp.installPixels(pixmapsToUpload->plane(i));
362 GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
363 views[i] = bitmapMaker.view(buildMips);
364 if (!views[i]) {
365 return nullptr;
366 }
367 pixmapColorTypes[i] = SkColorTypeToGrColorType(bmp.colorType());
368 }
369
370 GrYUVATextureProxies yuvaProxies(pixmapsToUpload->yuvaInfo(), views, pixmapColorTypes);
371 SkASSERT(yuvaProxies.isValid());
Brian Salomonc2a9a972020-09-15 11:24:28 -0400372 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
Brian Salomonc2a9a972020-09-15 11:24:28 -0400373 kNeedNewImageUniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -0500374 std::move(yuvaProxies),
Brian Salomonc2a9a972020-09-15 11:24:28 -0400375 std::move(imageColorSpace));
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500376}
377
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400378/////////////////////////////////////////////////////////////////////////////////////////////////
Brian Salomonf1432742020-11-09 15:40:27 -0500379
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500380sk_sp<SkImage> SkImage::MakePromiseYUVATexture(sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
381 const GrYUVABackendTextureInfo& backendTextureInfo,
382 sk_sp<SkColorSpace> imageColorSpace,
383 PromiseImageTextureFulfillProc textureFulfillProc,
384 PromiseImageTextureReleaseProc textureReleaseProc,
385 PromiseImageTextureContext textureContexts[]) {
386 if (!backendTextureInfo.isValid()) {
Brian Salomon98e17bf2020-11-16 10:31:49 -0500387 return nullptr;
388 }
389
390 SkISize planeDimensions[SkYUVAInfo::kMaxPlanes];
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500391 int n = backendTextureInfo.yuvaInfo().planeDimensions(planeDimensions);
Jim Van Verthf00b1622018-10-10 13:03:23 -0400392
Brian Salomonf1432742020-11-09 15:40:27 -0500393 // Our contract is that we will always call the release proc even on failure.
394 // We use the helper to convey the context, so we need to ensure make doesn't fail.
395 textureReleaseProc = textureReleaseProc ? textureReleaseProc : [](void*) {};
396 sk_sp<GrRefCntedCallback> releaseHelpers[4];
Brian Salomon98e17bf2020-11-16 10:31:49 -0500397 for (int i = 0; i < n; ++i) {
Brian Salomonf1432742020-11-09 15:40:27 -0500398 releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
399 }
400
Adlai Hollerdced31f2021-02-19 12:33:46 -0500401 if (!threadSafeProxy) {
Brian Salomonbe5a0932018-12-10 10:03:26 -0500402 return nullptr;
Jim Van Verthf00b1622018-10-10 13:03:23 -0400403 }
404
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500405 SkAlphaType at = backendTextureInfo.yuvaInfo().hasAlpha() ? kPremul_SkAlphaType
406 : kOpaque_SkAlphaType;
407 SkImageInfo info = SkImageInfo::Make(backendTextureInfo.yuvaInfo().dimensions(),
Brian Salomon98e17bf2020-11-16 10:31:49 -0500408 kAssumedColorType, at, imageColorSpace);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400409 if (!SkImageInfoIsValid(info)) {
410 return nullptr;
411 }
412
Brian Salomon98e17bf2020-11-16 10:31:49 -0500413 // Make a lazy proxy for each plane and wrap in a view.
Brian Salomon0857bef2021-01-13 15:54:04 -0500414 sk_sp<GrSurfaceProxy> proxies[4];
415 for (int i = 0; i < n; ++i) {
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500416 proxies[i] = SkImage_GpuBase::MakePromiseImageLazyProxy(threadSafeProxy.get(),
417 planeDimensions[i],
418 backendTextureInfo.planeFormat(i),
419 GrMipmapped::kNo,
420 textureFulfillProc,
421 std::move(releaseHelpers[i]));
Brian Salomon0857bef2021-01-13 15:54:04 -0500422 if (!proxies[i]) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400423 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400424 }
425 }
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500426 GrYUVATextureProxies yuvaTextureProxies(backendTextureInfo.yuvaInfo(),
Brian Salomon0857bef2021-01-13 15:54:04 -0500427 proxies,
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500428 backendTextureInfo.textureOrigin());
Brian Salomon0857bef2021-01-13 15:54:04 -0500429 SkASSERT(yuvaTextureProxies.isValid());
Adlai Hollerdced31f2021-02-19 12:33:46 -0500430 sk_sp<GrImageContext> ctx(GrImageContextPriv::MakeForPromiseImage(std::move(threadSafeProxy)));
431 return sk_make_sp<SkImage_GpuYUVA>(std::move(ctx),
Brian Salomon0857bef2021-01-13 15:54:04 -0500432 kNeedNewImageUniqueID,
433 std::move(yuvaTextureProxies),
434 std::move(imageColorSpace));
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400435}