blob: c0715a7f1f5029a9ebbef1b72e1c7965ca00e969 [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"
19#include "src/gpu/GrClip.h"
Adlai Hollera0693042020-10-14 11:23:11 -040020#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrGpu.h"
Adlai Holler302e8fb2020-09-14 11:58:06 -040022#include "src/gpu/GrImageContextPriv.h"
Brian Salomon8670c982020-12-08 16:39:32 -050023#include "src/gpu/GrProxyProvider.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/GrRecordingContextPriv.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050025#include "src/gpu/GrSurfaceDrawContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/SkGr.h"
Brian Salomond4688672021-04-28 15:42:09 -040027#include "src/gpu/effects/GrBicubicEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/gpu/effects/GrYUVtoRGBEffect.h"
29#include "src/image/SkImage_Gpu.h"
30#include "src/image/SkImage_GpuYUVA.h"
Jim Van Verthf49262d2018-10-02 12:07:20 -040031
Brian Salomon5ad6fd32019-03-21 15:30:08 -040032static constexpr auto kAssumedColorType = kRGBA_8888_SkColorType;
33
Adlai Holler302e8fb2020-09-14 11:58:06 -040034SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
Brian Salomonc505a452020-04-06 10:29:02 -040035 uint32_t uniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -050036 GrYUVATextureProxies proxies,
Greg Danielc594e622019-10-15 14:01:49 -040037 sk_sp<SkColorSpace> imageColorSpace)
Adlai Holler302e8fb2020-09-14 11:58:06 -040038 : INHERITED(std::move(context),
Brian Salomon9a56eb72021-04-20 16:52:11 -040039 SkImageInfo::Make(proxies.yuvaInfo().dimensions(),
40 kAssumedColorType,
41 // If an alpha channel is present we always use kPremul. This
42 // is because, although the planar data is always un-premul,
43 // the final interleaved RGBA sample produced in the shader
44 // is premul (and similar if flattened via asView).
45 proxies.yuvaInfo().hasAlpha() ? kPremul_SkAlphaType
46 : kOpaque_SkAlphaType,
47 std::move(imageColorSpace)),
48 uniqueID)
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),
Brian Salomon9a56eb72021-04-20 16:52:11 -040059 image->imageInfo().makeColorSpace(std::move(targetCS)),
60 kNeedNewImageUniqueID)
Brian Salomon0857bef2021-01-13 15:54:04 -050061 , fYUVAProxies(image->fYUVAProxies)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040062 // Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
63 // image->refColorSpace() into an explicit SRGB.
64 , fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050065}
66
Robert Phillips8defcc12019-03-05 15:58:59 -050067bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
68 if (!context || !fContext->priv().matches(context)) {
69 return false;
70 }
Brian Salomon69100f02020-07-21 10:49:25 -040071 if (!context->priv().caps()->mipmapSupport()) {
Brian Salomon4759dca2020-07-14 15:44:15 -040072 // We succeed in this case by doing nothing.
73 return true;
74 }
Brian Salomon0857bef2021-01-13 15:54:04 -050075 int n = fYUVAProxies.yuvaInfo().numPlanes();
76 sk_sp<GrSurfaceProxy> newProxies[4];
77 for (int i = 0; i < n; ++i) {
78 auto* t = fYUVAProxies.proxy(i)->asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -040079 if (t->mipmapped() == GrMipmapped::kNo && (t->width() > 1 || t->height() > 1)) {
Brian Salomon0857bef2021-01-13 15:54:04 -050080 auto newView = GrCopyBaseMipMapToView(context, fYUVAProxies.makeView(i));
81 if (!newView) {
Jim Van Verthf542cab2018-11-07 12:08:21 -050082 return false;
83 }
Brian Salomon0857bef2021-01-13 15:54:04 -050084 SkASSERT(newView.swizzle() == fYUVAProxies.makeView(i).swizzle());
85 newProxies[i] = newView.detachProxy();
Brian Salomon4759dca2020-07-14 15:44:15 -040086 } else {
Brian Salomon0857bef2021-01-13 15:54:04 -050087 newProxies[i] = fYUVAProxies.refProxy(i);
Jim Van Verth30e0d7f2018-11-02 13:36:42 -040088 }
89 }
Brian Salomon0857bef2021-01-13 15:54:04 -050090 fYUVAProxies = GrYUVATextureProxies(fYUVAProxies.yuvaInfo(),
91 newProxies,
92 fYUVAProxies.textureOrigin());
93 SkASSERT(fYUVAProxies.isValid());
Jim Van Verth30e0d7f2018-11-02 13:36:42 -040094 return true;
95}
96
Jim Van Verthf49262d2018-10-02 12:07:20 -040097//////////////////////////////////////////////////////////////////////////////////////////////////
Jim Van Verthf49262d2018-10-02 12:07:20 -040098
Adlai Holler40ad5fd2020-07-22 10:22:12 -040099GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const GrFlushInfo& info) {
100 if (!fContext->priv().matches(dContext) || dContext->abandoned()) {
Greg Daniel55822f12020-05-26 11:26:45 -0400101 if (info.fSubmittedProc) {
102 info.fSubmittedProc(info.fSubmittedContext, false);
103 }
104 if (info.fFinishedProc) {
105 info.fFinishedProc(info.fFinishedContext);
106 }
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400107 return GrSemaphoresSubmitted::kNo;
108 }
109
Brian Salomon0857bef2021-01-13 15:54:04 -0500110 GrSurfaceProxy* proxies[SkYUVAInfo::kMaxPlanes] = {};
Brian Salomond0f35c22021-04-16 14:52:49 -0400111 size_t numProxies = fYUVAProxies.numPlanes();
112 for (size_t i = 0; i < numProxies; ++i) {
113 proxies[i] = fYUVAProxies.proxy(i);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400114 }
Robert Phillips80bfda82020-11-12 09:23:36 -0500115 return dContext->priv().flushSurfaces({proxies, numProxies},
116 SkSurface::BackendSurfaceAccess::kNoAccess,
117 info);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400118}
119
Brian Salomond0f35c22021-04-16 14:52:49 -0400120bool SkImage_GpuYUVA::onHasMipmaps() const { return fYUVAProxies.mipmapped() == GrMipmapped::kYes; }
Brian Salomon7d2757f2021-01-26 17:46:50 -0500121
Brian Salomon650dd082021-02-11 08:59:03 -0500122size_t SkImage_GpuYUVA::onTextureSize() const {
Brian Salomon650dd082021-02-11 08:59:03 -0500123 size_t size = 0;
124 for (int i = 0; i < fYUVAProxies.numPlanes(); ++i) {
125 size += fYUVAProxies.proxy(i)->gpuMemorySize();
126 }
127 return size;
128}
129
Brian Salomond0924f32021-02-03 10:15:31 -0500130sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(SkColorType,
131 sk_sp<SkColorSpace> targetCS,
132 GrDirectContext* direct) const {
Brian Osmanf48c9962019-01-14 11:15:50 -0500133 // We explicitly ignore color type changes, for now.
134
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500135 // we may need a mutex here but for now we expect usage to be in a single thread
136 if (fOnMakeColorSpaceTarget &&
Brian Osmanf48c9962019-01-14 11:15:50 -0500137 SkColorSpace::Equals(targetCS.get(), fOnMakeColorSpaceTarget.get())) {
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500138 return fOnMakeColorSpaceResult;
139 }
Adlai Holler3a220172020-07-15 10:37:50 -0400140 sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(sk_ref_sp(direct), this, targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500141 if (result) {
Brian Osmanf48c9962019-01-14 11:15:50 -0500142 fOnMakeColorSpaceTarget = targetCS;
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500143 fOnMakeColorSpaceResult = result;
144 }
145 return result;
146}
147
Brian Osmand5148372019-08-14 16:14:51 -0400148sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Brian Salomon0857bef2021-01-13 15:54:04 -0500149 return sk_sp<SkImage>(new SkImage_GpuYUVA(fContext, this, std::move(newCS)));
Brian Osmand5148372019-08-14 16:14:51 -0400150}
151
Brian Salomond0f35c22021-04-16 14:52:49 -0400152std::tuple<GrSurfaceProxyView, GrColorType> SkImage_GpuYUVA::onAsView(
153 GrRecordingContext* context,
154 GrMipmapped mipmapped,
155 GrImageTexGenPolicy) const {
156 if (!fContext->priv().matches(context)) {
157 return {};
158 }
159 auto sfc = GrSurfaceFillContext::Make(context,
160 this->imageInfo(),
161 SkBackingFit::kExact,
162 /*sample count*/ 1,
163 mipmapped,
164 GrProtected::kNo,
165 kTopLeft_GrSurfaceOrigin,
166 SkBudgeted::kYes);
167 if (!sfc) {
Brian Salomond0924f32021-02-03 10:15:31 -0500168 return {};
169 }
170
171 const GrCaps& caps = *context->priv().caps();
Brian Salomond0f35c22021-04-16 14:52:49 -0400172 auto fp = GrYUVtoRGBEffect::Make(fYUVAProxies, GrSamplerState::Filter::kNearest, caps);
173 if (fFromColorSpace) {
Brian Salomond0924f32021-02-03 10:15:31 -0500174 fp = GrColorSpaceXformEffect::Make(std::move(fp),
Brian Salomond0f35c22021-04-16 14:52:49 -0400175 fFromColorSpace.get(), this->alphaType(),
176 this->colorSpace() , this->alphaType());
Brian Salomond0924f32021-02-03 10:15:31 -0500177 }
Brian Salomond0f35c22021-04-16 14:52:49 -0400178 sfc->fillWithFP(std::move(fp));
Brian Salomond0924f32021-02-03 10:15:31 -0500179
Robert Phillips9e42ec32021-05-17 18:01:49 -0400180 return {sfc->readSurfaceView(), sfc->colorInfo().colorType()};
Brian Salomond0924f32021-02-03 10:15:31 -0500181}
182
Brian Salomon6ef10e92021-04-20 09:11:24 -0400183std::unique_ptr<GrFragmentProcessor> SkImage_GpuYUVA::onAsFragmentProcessor(
184 GrRecordingContext* context,
185 SkSamplingOptions sampling,
186 const SkTileMode tileModes[2],
187 const SkMatrix& m,
188 const SkRect* subset,
189 const SkRect* domain) const {
190 if (!fContext->priv().matches(context)) {
191 return {};
192 }
Brian Salomon6ef10e92021-04-20 09:11:24 -0400193 auto wmx = SkTileModeToWrapMode(tileModes[0]);
194 auto wmy = SkTileModeToWrapMode(tileModes[1]);
Brian Salomon6ef10e92021-04-20 09:11:24 -0400195 GrSamplerState sampler(wmx, wmy, sampling.filter, sampling.mipmap);
Brian Salomond4688672021-04-28 15:42:09 -0400196 if (sampler.mipmapped() == GrMipmapped::kYes && !this->setupMipmapsForPlanes(context)) {
197 sampler.setMipmapMode(GrSamplerState::MipmapMode::kNone);
198 }
199
200 const auto& yuvM = sampling.useCubic ? SkMatrix::I() : m;
201 auto fp = GrYUVtoRGBEffect::Make(fYUVAProxies,
202 sampler,
203 *context->priv().caps(),
204 yuvM,
205 subset,
206 domain);
207 if (sampling.useCubic) {
208 fp = GrBicubicEffect::Make(std::move(fp),
209 this->alphaType(),
210 m,
211 sampling.cubic,
212 GrBicubicEffect::Direction::kXY);
213 }
214 if (fFromColorSpace) {
215 fp = GrColorSpaceXformEffect::Make(std::move(fp),
216 fFromColorSpace.get(), this->alphaType(),
217 this->colorSpace() , this->alphaType());
218 }
219 return fp;
Brian Salomon6ef10e92021-04-20 09:11:24 -0400220}
221
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500222//////////////////////////////////////////////////////////////////////////////////////////////////
223
Brian Salomonc1a249d2020-10-19 10:55:45 -0400224sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
225 const GrYUVABackendTextures& yuvaTextures,
226 sk_sp<SkColorSpace> imageColorSpace,
227 TextureReleaseProc textureReleaseProc,
228 ReleaseContext releaseContext) {
Brian Salomon694ff172020-11-04 16:54:28 -0500229 auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
Brian Salomonc1a249d2020-10-19 10:55:45 -0400230
Brian Salomon0857bef2021-01-13 15:54:04 -0500231 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
232 int numPlanes = yuvaTextures.yuvaInfo().numPlanes();
233 sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes];
234 for (int plane = 0; plane < numPlanes; ++plane) {
235 proxies[plane] = proxyProvider->wrapBackendTexture(yuvaTextures.texture(plane),
236 kBorrow_GrWrapOwnership,
237 GrWrapCacheable::kNo,
238 kRead_GrIOType,
239 releaseHelper);
240 if (!proxies[plane]) {
241 return {};
242 }
243 }
244 GrYUVATextureProxies yuvaProxies(yuvaTextures.yuvaInfo(),
245 proxies,
246 yuvaTextures.textureOrigin());
Brian Salomonc1a249d2020-10-19 10:55:45 -0400247
Brian Salomon0857bef2021-01-13 15:54:04 -0500248 if (!yuvaProxies.isValid()) {
Brian Salomonc1a249d2020-10-19 10:55:45 -0400249 return nullptr;
250 }
251
252 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
Brian Salomonc1a249d2020-10-19 10:55:45 -0400253 kNeedNewImageUniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -0500254 yuvaProxies,
Brian Salomonc1a249d2020-10-19 10:55:45 -0400255 imageColorSpace);
256}
257
Adlai Holler302e8fb2020-09-14 11:58:06 -0400258sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400259 const SkYUVAPixmaps& pixmaps,
Brian Salomon0857bef2021-01-13 15:54:04 -0500260 GrMipmapped buildMips,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400261 bool limitToMaxTextureSize,
262 sk_sp<SkColorSpace> imageColorSpace) {
263 if (!context) {
264 return nullptr; // until we impl this for raster backend
265 }
266
267 if (!pixmaps.isValid()) {
268 return nullptr;
269 }
270
Brian Salomonc2a9a972020-09-15 11:24:28 -0400271 if (!context->priv().caps()->mipmapSupport()) {
272 buildMips = GrMipMapped::kNo;
273 }
274
Brian Salomon0857bef2021-01-13 15:54:04 -0500275 // Resize the pixmaps if necessary.
Brian Salomonc2a9a972020-09-15 11:24:28 -0400276 int numPlanes = pixmaps.numPlanes();
277 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Salomon0857bef2021-01-13 15:54:04 -0500278 int maxDim = std::max(pixmaps.yuvaInfo().width(), pixmaps.yuvaInfo().height());
279
280 SkYUVAPixmaps tempPixmaps;
281 const SkYUVAPixmaps* pixmapsToUpload = &pixmaps;
282 // We assume no plane is larger than the image size (and at least one plane is as big).
283 if (maxDim > maxTextureSize) {
284 if (!limitToMaxTextureSize) {
Brian Salomonb6025502021-01-12 20:37:49 -0500285 return nullptr;
286 }
Brian Salomon0857bef2021-01-13 15:54:04 -0500287 float scale = static_cast<float>(maxTextureSize)/maxDim;
288 SkISize newDimensions = {
289 std::min(static_cast<int>(pixmaps.yuvaInfo().width() *scale), maxTextureSize),
290 std::min(static_cast<int>(pixmaps.yuvaInfo().height()*scale), maxTextureSize)
291 };
292 SkYUVAInfo newInfo = pixmaps.yuvaInfo().makeDimensions(newDimensions);
293 SkYUVAPixmapInfo newPixmapInfo(newInfo, pixmaps.dataType(), /*row bytes*/ nullptr);
294 tempPixmaps = SkYUVAPixmaps::Allocate(newPixmapInfo);
Mike Reed5ec22382021-01-14 21:59:01 -0500295 SkSamplingOptions sampling(SkFilterMode::kLinear);
Brian Salomon0857bef2021-01-13 15:54:04 -0500296 if (!tempPixmaps.isValid()) {
297 return nullptr;
298 }
299 for (int i = 0; i < numPlanes; ++i) {
300 if (!pixmaps.plane(i).scalePixels(tempPixmaps.plane(i), sampling)) {
301 return nullptr;
302 }
303 }
304 pixmapsToUpload = &tempPixmaps;
Brian Salomonb6025502021-01-12 20:37:49 -0500305 }
306
Brian Salomon0857bef2021-01-13 15:54:04 -0500307 // Convert to texture proxies.
308 GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
309 GrColorType pixmapColorTypes[SkYUVAInfo::kMaxPlanes];
310 for (int i = 0; i < numPlanes; ++i) {
311 // Turn the pixmap into a GrTextureProxy
312 SkBitmap bmp;
313 bmp.installPixels(pixmapsToUpload->plane(i));
Brian Salomon27c42022021-04-28 12:39:21 -0400314 std::tie(views[i], std::ignore) = GrMakeUncachedBitmapProxyView(context, bmp, buildMips);
Brian Salomon0857bef2021-01-13 15:54:04 -0500315 if (!views[i]) {
316 return nullptr;
317 }
318 pixmapColorTypes[i] = SkColorTypeToGrColorType(bmp.colorType());
319 }
320
321 GrYUVATextureProxies yuvaProxies(pixmapsToUpload->yuvaInfo(), views, pixmapColorTypes);
322 SkASSERT(yuvaProxies.isValid());
Brian Salomonc2a9a972020-09-15 11:24:28 -0400323 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
Brian Salomonc2a9a972020-09-15 11:24:28 -0400324 kNeedNewImageUniqueID,
Brian Salomon0857bef2021-01-13 15:54:04 -0500325 std::move(yuvaProxies),
Brian Salomonc2a9a972020-09-15 11:24:28 -0400326 std::move(imageColorSpace));
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500327}
328
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400329/////////////////////////////////////////////////////////////////////////////////////////////////
Brian Salomonf1432742020-11-09 15:40:27 -0500330
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500331sk_sp<SkImage> SkImage::MakePromiseYUVATexture(sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
332 const GrYUVABackendTextureInfo& backendTextureInfo,
333 sk_sp<SkColorSpace> imageColorSpace,
334 PromiseImageTextureFulfillProc textureFulfillProc,
335 PromiseImageTextureReleaseProc textureReleaseProc,
336 PromiseImageTextureContext textureContexts[]) {
337 if (!backendTextureInfo.isValid()) {
Brian Salomon98e17bf2020-11-16 10:31:49 -0500338 return nullptr;
339 }
340
341 SkISize planeDimensions[SkYUVAInfo::kMaxPlanes];
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500342 int n = backendTextureInfo.yuvaInfo().planeDimensions(planeDimensions);
Jim Van Verthf00b1622018-10-10 13:03:23 -0400343
Brian Salomonf1432742020-11-09 15:40:27 -0500344 // Our contract is that we will always call the release proc even on failure.
345 // We use the helper to convey the context, so we need to ensure make doesn't fail.
346 textureReleaseProc = textureReleaseProc ? textureReleaseProc : [](void*) {};
347 sk_sp<GrRefCntedCallback> releaseHelpers[4];
Brian Salomon98e17bf2020-11-16 10:31:49 -0500348 for (int i = 0; i < n; ++i) {
Brian Salomonf1432742020-11-09 15:40:27 -0500349 releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
350 }
351
Adlai Hollerdced31f2021-02-19 12:33:46 -0500352 if (!threadSafeProxy) {
Brian Salomonbe5a0932018-12-10 10:03:26 -0500353 return nullptr;
Jim Van Verthf00b1622018-10-10 13:03:23 -0400354 }
355
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500356 SkAlphaType at = backendTextureInfo.yuvaInfo().hasAlpha() ? kPremul_SkAlphaType
357 : kOpaque_SkAlphaType;
358 SkImageInfo info = SkImageInfo::Make(backendTextureInfo.yuvaInfo().dimensions(),
Brian Salomon98e17bf2020-11-16 10:31:49 -0500359 kAssumedColorType, at, imageColorSpace);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400360 if (!SkImageInfoIsValid(info)) {
361 return nullptr;
362 }
363
Brian Salomon98e17bf2020-11-16 10:31:49 -0500364 // Make a lazy proxy for each plane and wrap in a view.
Brian Salomon0857bef2021-01-13 15:54:04 -0500365 sk_sp<GrSurfaceProxy> proxies[4];
366 for (int i = 0; i < n; ++i) {
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500367 proxies[i] = SkImage_GpuBase::MakePromiseImageLazyProxy(threadSafeProxy.get(),
368 planeDimensions[i],
369 backendTextureInfo.planeFormat(i),
370 GrMipmapped::kNo,
371 textureFulfillProc,
372 std::move(releaseHelpers[i]));
Brian Salomon0857bef2021-01-13 15:54:04 -0500373 if (!proxies[i]) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400374 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400375 }
376 }
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500377 GrYUVATextureProxies yuvaTextureProxies(backendTextureInfo.yuvaInfo(),
Brian Salomon0857bef2021-01-13 15:54:04 -0500378 proxies,
Adlai Hollerc44e21f2021-02-22 14:08:07 -0500379 backendTextureInfo.textureOrigin());
Brian Salomon0857bef2021-01-13 15:54:04 -0500380 SkASSERT(yuvaTextureProxies.isValid());
Adlai Hollerdced31f2021-02-19 12:33:46 -0500381 sk_sp<GrImageContext> ctx(GrImageContextPriv::MakeForPromiseImage(std::move(threadSafeProxy)));
382 return sk_make_sp<SkImage_GpuYUVA>(std::move(ctx),
Brian Salomon0857bef2021-01-13 15:54:04 -0500383 kNeedNewImageUniqueID,
384 std::move(yuvaTextureProxies),
385 std::move(imageColorSpace));
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400386}