blob: 99108c1e451e99edee41b02fa8af4032fe13bfc5 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkYUVASizeInfo.h"
13#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/private/GrRecordingContext.h"
15#include "src/core/SkAutoPixmapStorage.h"
16#include "src/core/SkMipMap.h"
17#include "src/core/SkScopeExit.h"
Greg Daniel82c6b102020-01-21 10:33:22 -050018#include "src/gpu/GrBitmapTextureMaker.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/GrClip.h"
20#include "src/gpu/GrContextPriv.h"
21#include "src/gpu/GrGpu.h"
22#include "src/gpu/GrRecordingContextPriv.h"
23#include "src/gpu/GrRenderTargetContext.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000024#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrTextureProducer.h"
26#include "src/gpu/SkGr.h"
27#include "src/gpu/effects/GrYUVtoRGBEffect.h"
28#include "src/image/SkImage_Gpu.h"
29#include "src/image/SkImage_GpuYUVA.h"
Jim Van Verthf49262d2018-10-02 12:07:20 -040030
Brian Salomon5ad6fd32019-03-21 15:30:08 -040031static constexpr auto kAssumedColorType = kRGBA_8888_SkColorType;
32
Brian Salomon9f2b86c2019-10-22 10:37:46 -040033SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, SkISize size, uint32_t uniqueID,
Greg Danielc7672092020-02-06 14:32:54 -050034 SkYUVColorSpace colorSpace, GrSurfaceProxyView views[],
35 GrColorType proxyColorTypes[], int numViews,
Greg Danielc594e622019-10-15 14:01:49 -040036 const SkYUVAIndex yuvaIndices[4], GrSurfaceOrigin origin,
37 sk_sp<SkColorSpace> imageColorSpace)
Brian Salomon9f2b86c2019-10-22 10:37:46 -040038 : INHERITED(std::move(context), size, uniqueID, kAssumedColorType,
Jim Van Verth8026ccc2018-10-04 13:10:39 -040039 // If an alpha channel is present we always switch to kPremul. This is because,
40 // although the planar data is always un-premul, the final interleaved RGB image
41 // is/would-be premul.
Brian Salomon5ad6fd32019-03-21 15:30:08 -040042 GetAlphaTypeFromYUVAIndices(yuvaIndices), std::move(imageColorSpace))
Greg Danielc7672092020-02-06 14:32:54 -050043 , fNumViews(numViews)
Jim Van Verth8026ccc2018-10-04 13:10:39 -040044 , fYUVColorSpace(colorSpace)
45 , fOrigin(origin) {
Jim Van Verth0e671942018-11-09 12:03:57 -050046 // The caller should have done this work, just verifying
47 SkDEBUGCODE(int textureCount;)
48 SkASSERT(SkYUVAIndex::AreValidIndices(yuvaIndices, &textureCount));
Greg Danielc7672092020-02-06 14:32:54 -050049 SkASSERT(textureCount == fNumViews);
Jim Van Verth0e671942018-11-09 12:03:57 -050050
Greg Danielc7672092020-02-06 14:32:54 -050051 for (int i = 0; i < numViews; ++i) {
52 fViews[i] = std::move(views[i]);
Greg Danielc594e622019-10-15 14:01:49 -040053 fProxyColorTypes[i] = proxyColorTypes[i];
Jim Van Verthf49262d2018-10-02 12:07:20 -040054 }
Greg Danielc7672092020-02-06 14:32:54 -050055 memcpy(fYUVAIndices, yuvaIndices, 4 * sizeof(SkYUVAIndex));
Jim Van Verthf49262d2018-10-02 12:07:20 -040056}
57
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050058// For onMakeColorSpace()
59SkImage_GpuYUVA::SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace> targetCS)
Brian Salomon9f2b86c2019-10-22 10:37:46 -040060 : INHERITED(image->fContext, image->dimensions(), kNeedNewImageUniqueID, kAssumedColorType,
Brian Salomon5ad6fd32019-03-21 15:30:08 -040061 // If an alpha channel is present we always switch to kPremul. This is because,
62 // although the planar data is always un-premul, the final interleaved RGB image
63 // is/would-be premul.
64 GetAlphaTypeFromYUVAIndices(image->fYUVAIndices), std::move(targetCS))
Greg Danielc7672092020-02-06 14:32:54 -050065 , fNumViews(image->fNumViews)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040066 , fYUVColorSpace(image->fYUVColorSpace)
67 , fOrigin(image->fOrigin)
68 // Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
69 // image->refColorSpace() into an explicit SRGB.
70 , fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
71 // The caller should have done this work, just verifying
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050072 SkDEBUGCODE(int textureCount;)
Greg Danielc7672092020-02-06 14:32:54 -050073 SkASSERT(SkYUVAIndex::AreValidIndices(image->fYUVAIndices, &textureCount));
74 SkASSERT(textureCount == fNumViews);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050075
Greg Daniel1a372c32019-12-17 13:53:38 -050076 if (image->fRGBView.proxy()) {
77 fRGBView = image->fRGBView; // we ref in this case, not move
Brian Salomonad8efda2019-05-10 09:22:49 -040078 } else {
Greg Danielc7672092020-02-06 14:32:54 -050079 for (int i = 0; i < fNumViews; ++i) {
80 fViews[i] = image->fViews[i]; // we ref in this case, not move
Greg Danielc594e622019-10-15 14:01:49 -040081 fProxyColorTypes[i] = image->fProxyColorTypes[i];
Brian Salomonad8efda2019-05-10 09:22:49 -040082 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050083 }
84 memcpy(fYUVAIndices, image->fYUVAIndices, 4 * sizeof(SkYUVAIndex));
85}
86
Robert Phillips8defcc12019-03-05 15:58:59 -050087bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
Brian Salomonad8efda2019-05-10 09:22:49 -040088 // We shouldn't get here if the planes were already flattened to RGBA.
Greg Danielc7672092020-02-06 14:32:54 -050089 SkASSERT(fViews[0].proxy() && !fRGBView.proxy());
Robert Phillips8defcc12019-03-05 15:58:59 -050090 if (!context || !fContext->priv().matches(context)) {
91 return false;
92 }
93
Greg Danielc7672092020-02-06 14:32:54 -050094 for (int i = 0; i < fNumViews; ++i) {
Greg Danielc7672092020-02-06 14:32:54 -050095 int mipCount = SkMipMap::ComputeLevelCount(fViews[i].proxy()->width(),
96 fViews[i].proxy()->height());
Robert Phillips9da87e02019-02-04 13:26:26 -050097 if (mipCount && GrGpu::IsACopyNeededForMips(fContext->priv().caps(),
Greg Danielc7672092020-02-06 14:32:54 -050098 fViews[i].asTextureProxy(),
Brian Salomonc8d092a2020-02-24 10:14:21 -050099 GrSamplerState::Filter::kMipMap)) {
Greg Danielc7672092020-02-06 14:32:54 -0500100 auto mippedView = GrCopyBaseMipMapToTextureProxy(context, fViews[i].asTextureProxy(),
101 fOrigin, fProxyColorTypes[i]);
Greg Danielcc104db2020-02-03 14:17:08 -0500102 if (!mippedView.proxy()) {
Jim Van Verthf542cab2018-11-07 12:08:21 -0500103 return false;
104 }
Greg Danielc7672092020-02-06 14:32:54 -0500105 fViews[i] = std::move(mippedView);
Jim Van Verth30e0d7f2018-11-02 13:36:42 -0400106 }
107 }
108 return true;
109}
110
Jim Van Verthf49262d2018-10-02 12:07:20 -0400111//////////////////////////////////////////////////////////////////////////////////////////////////
Jim Van Verthf49262d2018-10-02 12:07:20 -0400112
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400113GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrContext* context, const GrFlushInfo& info) {
114 if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
115 return GrSemaphoresSubmitted::kNo;
116 }
117
Greg Danielc7672092020-02-06 14:32:54 -0500118 GrSurfaceProxy* proxies[4] = {fViews[0].proxy(), fViews[1].proxy(), fViews[2].proxy(),
119 fViews[3].proxy()};
120 int numProxies = fNumViews;
Greg Daniel1a372c32019-12-17 13:53:38 -0500121 if (fRGBView.proxy()) {
Brian Salomonad8efda2019-05-10 09:22:49 -0400122 // Either we've already flushed the flattening draw or the flattening is unflushed. In the
Greg Daniel1a372c32019-12-17 13:53:38 -0500123 // latter case it should still be ok to just pass fRGBView proxy because it in turn depends
124 // on the planar proxies and will cause all of their work to flush as well.
125 proxies[0] = fRGBView.proxy();
Brian Salomonad8efda2019-05-10 09:22:49 -0400126 numProxies = 1;
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400127 }
Greg Daniel55f040b2020-02-13 15:38:32 +0000128 return context->priv().flushSurfaces(proxies, numProxies, info);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400129}
130
Greg Danielc7672092020-02-06 14:32:54 -0500131GrTextureProxy* SkImage_GpuYUVA::peekProxy() const { return fRGBView.asTextureProxy(); }
Robert Phillips193c4212019-03-04 12:18:53 -0500132
Greg Daniel1a372c32019-12-17 13:53:38 -0500133void SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context) const {
134 if (fRGBView.proxy()) {
135 return;
Jim Van Verthf49262d2018-10-02 12:07:20 -0400136 }
137
Robert Phillips6603a172019-03-05 12:35:44 -0500138 if (!context || !fContext->priv().matches(context)) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500139 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500140 }
141
Robert Phillips6603a172019-03-05 12:35:44 -0500142 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
Greg Daniele20fcad2020-01-08 11:52:34 -0500143 auto renderTargetContext = GrRenderTargetContext::Make(
144 context, GrColorType::kRGBA_8888, this->refColorSpace(), SkBackingFit::kExact,
145 this->dimensions(), 1, GrMipMapped::kNo, GrProtected::kNo, fOrigin);
Robert Phillips6603a172019-03-05 12:35:44 -0500146 if (!renderTargetContext) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500147 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500148 }
149
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400150 sk_sp<GrColorSpaceXform> colorSpaceXform;
151 if (fFromColorSpace) {
152 colorSpaceXform = GrColorSpaceXform::Make(fFromColorSpace.get(), this->alphaType(),
153 this->colorSpace(), this->alphaType());
154 }
Robert Phillips6603a172019-03-05 12:35:44 -0500155 const SkRect rect = SkRect::MakeIWH(this->width(), this->height());
156 if (!RenderYUVAToRGBA(fContext.get(), renderTargetContext.get(), rect, fYUVColorSpace,
Greg Danielc7672092020-02-06 14:32:54 -0500157 std::move(colorSpaceXform), fViews, fYUVAIndices)) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500158 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500159 }
160
Greg Daniel1a372c32019-12-17 13:53:38 -0500161 fRGBView = renderTargetContext->readSurfaceView();
162 SkASSERT(fRGBView.origin() == fOrigin);
163 SkASSERT(fRGBView.swizzle() == GrSwizzle());
Greg Danielc7672092020-02-06 14:32:54 -0500164 for (auto& v : fViews) {
165 v.reset();
Brian Salomonad8efda2019-05-10 09:22:49 -0400166 }
Greg Daniel1a372c32019-12-17 13:53:38 -0500167}
168
Greg Daniel37c127f2020-02-05 10:37:27 -0500169GrSurfaceProxyView SkImage_GpuYUVA::refMippedView(GrRecordingContext* context) const {
Jim Van Verth803a5022018-11-05 15:55:53 -0500170 // if invalid or already has miplevels
Greg Daniel1a372c32019-12-17 13:53:38 -0500171 this->flattenToRGB(context);
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500172 if (!fRGBView || fRGBView.asTextureProxy()->mipMapped() == GrMipMapped::kYes) {
Greg Danielcc104db2020-02-03 14:17:08 -0500173 return fRGBView;
Jim Van Verth803a5022018-11-05 15:55:53 -0500174 }
175
176 // need to generate mips for the proxy
Greg Danielc594e622019-10-15 14:01:49 -0400177 GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
Greg Danielc7672092020-02-06 14:32:54 -0500178 GrSurfaceProxyView mippedView = GrCopyBaseMipMapToTextureProxy(context, fRGBView.proxy(),
179 fRGBView.origin(), srcColorType);
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500180 if (mippedView) {
Greg Danielcc104db2020-02-03 14:17:08 -0500181 fRGBView = std::move(mippedView);
182 return fRGBView;
Jim Van Verth803a5022018-11-05 15:55:53 -0500183 }
184
185 // failed to generate mips
Greg Danielcc104db2020-02-03 14:17:08 -0500186 return {};
Jim Van Verth803a5022018-11-05 15:55:53 -0500187}
188
Greg Daniel37c127f2020-02-05 10:37:27 -0500189const GrSurfaceProxyView* SkImage_GpuYUVA::view(GrRecordingContext* context) const {
Greg Daniel1a372c32019-12-17 13:53:38 -0500190 this->flattenToRGB(context);
Greg Daniel37c127f2020-02-05 10:37:27 -0500191 if (!fRGBView.proxy()) {
192 return nullptr;
193 }
194 return &fRGBView;
Greg Daniel81b98972019-12-13 11:09:43 -0500195}
196
Jim Van Verth9bf81202018-10-30 15:53:36 -0400197//////////////////////////////////////////////////////////////////////////////////////////////////
198
Greg Danielc7672092020-02-06 14:32:54 -0500199sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(
200 GrRecordingContext*, SkColorType, sk_sp<SkColorSpace> targetCS) const {
Brian Osmanf48c9962019-01-14 11:15:50 -0500201 // We explicitly ignore color type changes, for now.
202
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500203 // we may need a mutex here but for now we expect usage to be in a single thread
204 if (fOnMakeColorSpaceTarget &&
Brian Osmanf48c9962019-01-14 11:15:50 -0500205 SkColorSpace::Equals(targetCS.get(), fOnMakeColorSpaceTarget.get())) {
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500206 return fOnMakeColorSpaceResult;
207 }
Brian Osmanf48c9962019-01-14 11:15:50 -0500208 sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(this, targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500209 if (result) {
Brian Osmanf48c9962019-01-14 11:15:50 -0500210 fOnMakeColorSpaceTarget = targetCS;
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500211 fOnMakeColorSpaceResult = result;
212 }
213 return result;
214}
215
Brian Osmand5148372019-08-14 16:14:51 -0400216sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400217 return sk_make_sp<SkImage_GpuYUVA>(fContext, this->dimensions(), kNeedNewImageUniqueID,
Greg Danielc7672092020-02-06 14:32:54 -0500218 fYUVColorSpace, fViews, fProxyColorTypes, fNumViews,
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400219 fYUVAIndices, fOrigin, std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400220}
221
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500222//////////////////////////////////////////////////////////////////////////////////////////////////
223
Jim Van Verth9bf81202018-10-30 15:53:36 -0400224sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
225 SkYUVColorSpace colorSpace,
226 const GrBackendTexture yuvaTextures[],
227 const SkYUVAIndex yuvaIndices[4],
228 SkISize imageSize,
229 GrSurfaceOrigin imageOrigin,
230 sk_sp<SkColorSpace> imageColorSpace) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500231 int numTextures;
232 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
233 return nullptr;
Jim Van Verth9bf81202018-10-30 15:53:36 -0400234 }
235
Greg Danielc7672092020-02-06 14:32:54 -0500236 GrSurfaceProxyView tempViews[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500237 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
Greg Danielc7672092020-02-06 14:32:54 -0500238 imageOrigin, tempViews)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500239 return nullptr;
Jim Van Verth9bf81202018-10-30 15:53:36 -0400240 }
Greg Danielc594e622019-10-15 14:01:49 -0400241 GrColorType proxyColorTypes[4];
242 for (int i = 0; i < numTextures; ++i) {
243 proxyColorTypes[i] = ctx->priv().caps()->getYUVAColorTypeFromBackendFormat(
244 yuvaTextures[i].getBackendFormat(), yuvaIndices[3].fIndex == i);
245 }
Jim Van Verth9bf81202018-10-30 15:53:36 -0400246
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400247 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(ctx), imageSize, kNeedNewImageUniqueID, colorSpace,
Greg Danielc7672092020-02-06 14:32:54 -0500248 tempViews, proxyColorTypes, numTextures, yuvaIndices,
249 imageOrigin, imageColorSpace);
Jim Van Verth9bf81202018-10-30 15:53:36 -0400250}
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500251
Greg Danielc7672092020-02-06 14:32:54 -0500252sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrContext* context, SkYUVColorSpace yuvColorSpace,
253 const SkPixmap yuvaPixmaps[],
254 const SkYUVAIndex yuvaIndices[4], SkISize imageSize,
255 GrSurfaceOrigin imageOrigin, bool buildMips,
256 bool limitToMaxTextureSize,
257 sk_sp<SkColorSpace> imageColorSpace) {
Mike Reed6a5f7e22019-05-23 15:30:07 -0400258 if (!context) {
Greg Danielc7672092020-02-06 14:32:54 -0500259 return nullptr; // until we impl this for raster backend
Mike Reed6a5f7e22019-05-23 15:30:07 -0400260 }
261
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500262 int numPixmaps;
263 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numPixmaps)) {
264 return nullptr;
265 }
266
Brian Osman7dcc6162019-03-25 10:12:57 -0400267 if (!context->priv().caps()->mipMapSupport()) {
268 buildMips = false;
269 }
270
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500271 // Make proxies
Greg Danielc7672092020-02-06 14:32:54 -0500272 GrSurfaceProxyView tempViews[4];
Greg Danielc594e622019-10-15 14:01:49 -0400273 GrColorType proxyColorTypes[4];
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500274 for (int i = 0; i < numPixmaps; ++i) {
275 const SkPixmap* pixmap = &yuvaPixmaps[i];
276 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500277 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman788b9162020-02-07 10:36:46 -0500278 int maxDim = std::max(yuvaPixmaps[i].width(), yuvaPixmaps[i].height());
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500279 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
280 float scale = static_cast<float>(maxTextureSize) / maxDim;
Brian Osman788b9162020-02-07 10:36:46 -0500281 int newWidth = std::min(static_cast<int>(yuvaPixmaps[i].width() * scale), maxTextureSize);
Greg Danielc7672092020-02-06 14:32:54 -0500282 int newHeight =
Brian Osman788b9162020-02-07 10:36:46 -0500283 std::min(static_cast<int>(yuvaPixmaps[i].height() * scale), maxTextureSize);
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500284 SkImageInfo info = yuvaPixmaps[i].info().makeWH(newWidth, newHeight);
285 if (!resized.tryAlloc(info) ||
286 !yuvaPixmaps[i].scalePixels(resized, kLow_SkFilterQuality)) {
287 return nullptr;
288 }
289 pixmap = &resized;
290 }
291 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400292 SkBitmap bmp;
293 bmp.installPixels(*pixmap);
Brian Salomonbc074a62020-03-18 10:06:13 -0400294 GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
Brian Osman7dcc6162019-03-25 10:12:57 -0400295 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
Greg Danielcc104db2020-02-03 14:17:08 -0500296 GrSurfaceProxyView view;
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500297 tempViews[i] = bitmapMaker.view(mipMapped);
Greg Danielc7672092020-02-06 14:32:54 -0500298 if (!tempViews[i]) {
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500299 return nullptr;
300 }
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500301 proxyColorTypes[i] = bitmapMaker.colorType();
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500302 }
303
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400304 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageSize, kNeedNewImageUniqueID,
Greg Danielc7672092020-02-06 14:32:54 -0500305 yuvColorSpace, tempViews, proxyColorTypes, numPixmaps,
306 yuvaIndices, imageOrigin, imageColorSpace);
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500307}
308
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400309/////////////////////////////////////////////////////////////////////////////////////////////////
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500310sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
311 GrContext* context,
312 SkYUVColorSpace yuvColorSpace,
313 const GrBackendFormat yuvaFormats[],
314 const SkISize yuvaSizes[],
315 const SkYUVAIndex yuvaIndices[4],
316 int imageWidth,
317 int imageHeight,
318 GrSurfaceOrigin imageOrigin,
319 sk_sp<SkColorSpace> imageColorSpace,
320 PromiseImageTextureFulfillProc textureFulfillProc,
321 PromiseImageTextureReleaseProc textureReleaseProc,
322 PromiseImageTextureDoneProc promiseDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500323 PromiseImageTextureContext textureContexts[],
324 PromiseImageApiVersion version) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400325 int numTextures;
326 bool valid = SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures);
327
Brian Salomonbe5a0932018-12-10 10:03:26 -0500328 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
329 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
330 // responsibility for calling the done proc.
331 if (!promiseDoneProc) {
332 return nullptr;
Jim Van Verthf00b1622018-10-10 13:03:23 -0400333 }
Brian Salomonbe5a0932018-12-10 10:03:26 -0500334 int proxiesCreated = 0;
335 SkScopeExit callDone([promiseDoneProc, textureContexts, numTextures, &proxiesCreated]() {
336 for (int i = proxiesCreated; i < numTextures; ++i) {
337 promiseDoneProc(textureContexts[i]);
338 }
339 });
Jim Van Verthf00b1622018-10-10 13:03:23 -0400340
341 if (!valid) {
342 return nullptr;
343 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400344
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400345 if (!context) {
346 return nullptr;
347 }
348
Greg Kaiser9a2169e2019-02-10 17:29:46 -0800349 if (imageWidth <= 0 || imageHeight <= 0) {
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400350 return nullptr;
351 }
352
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400353 SkAlphaType at = (-1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex) ? kPremul_SkAlphaType
354 : kOpaque_SkAlphaType;
Greg Danielc7672092020-02-06 14:32:54 -0500355 SkImageInfo info =
356 SkImageInfo::Make(imageWidth, imageHeight, kAssumedColorType, at, imageColorSpace);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400357 if (!SkImageInfoIsValid(info)) {
358 return nullptr;
359 }
360
Jim Van Verthf9f07352018-10-24 10:32:20 -0400361 // verify sizes with expected texture count
Jim Van Verth8f11e432018-10-18 14:36:59 -0400362 for (int i = 0; i < numTextures; ++i) {
Jim Van Verthf9f07352018-10-24 10:32:20 -0400363 if (yuvaSizes[i].isEmpty()) {
Jim Van Verth8f11e432018-10-18 14:36:59 -0400364 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400365 }
366 }
Jim Van Verthe24b5872018-10-29 16:26:02 -0400367 for (int i = numTextures; i < SkYUVASizeInfo::kMaxCount; ++i) {
Jim Van Verthf9f07352018-10-24 10:32:20 -0400368 if (!yuvaSizes[i].isEmpty()) {
Jim Van Verth8f11e432018-10-18 14:36:59 -0400369 return nullptr;
370 }
Jim Van Verthf99a6742018-10-18 16:13:18 +0000371 }
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400372
373 // Get lazy proxies
Greg Danielc7672092020-02-06 14:32:54 -0500374 GrSurfaceProxyView views[4];
Greg Danielc594e622019-10-15 14:01:49 -0400375 GrColorType proxyColorTypes[4];
Jim Van Verthf00b1622018-10-10 13:03:23 -0400376 for (int texIdx = 0; texIdx < numTextures; ++texIdx) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400377 GrColorType colorType = context->priv().caps()->getYUVAColorTypeFromBackendFormat(
Greg Danielc7672092020-02-06 14:32:54 -0500378 yuvaFormats[texIdx], yuvaIndices[3].fIndex == texIdx);
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400379 if (GrColorType::kUnknown == colorType) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400380 return nullptr;
381 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400382
Greg Danielc7672092020-02-06 14:32:54 -0500383 auto proxy = MakePromiseImageLazyProxy(
Greg Daniel3a365112020-02-14 10:47:18 -0500384 context, yuvaSizes[texIdx].width(), yuvaSizes[texIdx].height(), colorType,
385 yuvaFormats[texIdx], GrMipMapped::kNo, textureFulfillProc, textureReleaseProc,
386 promiseDoneProc, textureContexts[texIdx], version);
Brian Salomonbe5a0932018-12-10 10:03:26 -0500387 ++proxiesCreated;
Greg Danielc7672092020-02-06 14:32:54 -0500388 if (!proxy) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400389 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400390 }
Greg Danielc7672092020-02-06 14:32:54 -0500391 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(),
392 colorType);
393 views[texIdx] = GrSurfaceProxyView(std::move(proxy), imageOrigin, swizzle);
Greg Danielc594e622019-10-15 14:01:49 -0400394 proxyColorTypes[texIdx] = colorType;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400395 }
396
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400397 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), SkISize{imageWidth, imageHeight},
Greg Danielc7672092020-02-06 14:32:54 -0500398 kNeedNewImageUniqueID, yuvColorSpace, views,
Greg Danielc594e622019-10-15 14:01:49 -0400399 proxyColorTypes, numTextures, yuvaIndices, imageOrigin,
400 std::move(imageColorSpace));
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400401}