blob: aabafd953b5941bd632c2b5a0205ea339dcf3b77 [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkYUVASizeInfo.h"
Adlai Holler3a220172020-07-15 10:37:50 -040014#include "include/gpu/GrDirectContext.h"
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040015#include "include/gpu/GrRecordingContext.h"
Brian Salomonc1a249d2020-10-19 10:55:45 -040016#include "include/gpu/GrYUVABackendTextures.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/core/SkAutoPixmapStorage.h"
Mike Reed13711eb2020-07-14 17:16:32 -040018#include "src/core/SkMipmap.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/core/SkScopeExit.h"
Greg Daniel82c6b102020-01-21 10:33:22 -050020#include "src/gpu/GrBitmapTextureMaker.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrClip.h"
Adlai Hollera0693042020-10-14 11:23:11 -040022#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/GrGpu.h"
Adlai Holler302e8fb2020-09-14 11:58:06 -040024#include "src/gpu/GrImageContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrRecordingContextPriv.h"
26#include "src/gpu/GrRenderTargetContext.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 SkISize size,
38 uint32_t uniqueID,
39 SkYUVColorSpace colorSpace,
40 GrSurfaceProxyView views[],
41 int numViews,
42 const SkYUVAIndex yuvaIndices[4],
Greg Danielc594e622019-10-15 14:01:49 -040043 sk_sp<SkColorSpace> imageColorSpace)
Adlai Holler302e8fb2020-09-14 11:58:06 -040044 : INHERITED(std::move(context),
Brian Salomonc505a452020-04-06 10:29:02 -040045 size,
46 uniqueID,
47 kAssumedColorType,
Jim Van Verth8026ccc2018-10-04 13:10:39 -040048 // If an alpha channel is present we always switch to kPremul. This is because,
49 // although the planar data is always un-premul, the final interleaved RGB image
50 // is/would-be premul.
Brian Salomonc505a452020-04-06 10:29:02 -040051 GetAlphaTypeFromYUVAIndices(yuvaIndices),
52 std::move(imageColorSpace))
Greg Danielc7672092020-02-06 14:32:54 -050053 , fNumViews(numViews)
Brian Salomon8e5cf442020-10-05 16:05:23 -040054 , fYUVColorSpace(colorSpace) {
Jim Van Verth0e671942018-11-09 12:03:57 -050055 // The caller should have done this work, just verifying
56 SkDEBUGCODE(int textureCount;)
57 SkASSERT(SkYUVAIndex::AreValidIndices(yuvaIndices, &textureCount));
Greg Danielc7672092020-02-06 14:32:54 -050058 SkASSERT(textureCount == fNumViews);
Jim Van Verth0e671942018-11-09 12:03:57 -050059
Greg Danielc7672092020-02-06 14:32:54 -050060 for (int i = 0; i < numViews; ++i) {
61 fViews[i] = std::move(views[i]);
Jim Van Verthf49262d2018-10-02 12:07:20 -040062 }
Greg Danielc7672092020-02-06 14:32:54 -050063 memcpy(fYUVAIndices, yuvaIndices, 4 * sizeof(SkYUVAIndex));
Jim Van Verthf49262d2018-10-02 12:07:20 -040064}
65
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050066// For onMakeColorSpace()
Adlai Holler302e8fb2020-09-14 11:58:06 -040067SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context, const SkImage_GpuYUVA* image,
Adlai Holler3a220172020-07-15 10:37:50 -040068 sk_sp<SkColorSpace> targetCS)
69 : INHERITED(std::move(context), image->dimensions(), kNeedNewImageUniqueID,
70 kAssumedColorType,
Brian Salomon5ad6fd32019-03-21 15:30:08 -040071 // If an alpha channel is present we always switch to kPremul. This is because,
72 // although the planar data is always un-premul, the final interleaved RGB image
73 // is/would-be premul.
74 GetAlphaTypeFromYUVAIndices(image->fYUVAIndices), std::move(targetCS))
Greg Danielc7672092020-02-06 14:32:54 -050075 , fNumViews(image->fNumViews)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040076 , fYUVColorSpace(image->fYUVColorSpace)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040077 // Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
78 // image->refColorSpace() into an explicit SRGB.
79 , fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
80 // The caller should have done this work, just verifying
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050081 SkDEBUGCODE(int textureCount;)
Greg Danielc7672092020-02-06 14:32:54 -050082 SkASSERT(SkYUVAIndex::AreValidIndices(image->fYUVAIndices, &textureCount));
83 SkASSERT(textureCount == fNumViews);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050084
Greg Daniel1a372c32019-12-17 13:53:38 -050085 if (image->fRGBView.proxy()) {
86 fRGBView = image->fRGBView; // we ref in this case, not move
Brian Salomonad8efda2019-05-10 09:22:49 -040087 } else {
Greg Danielc7672092020-02-06 14:32:54 -050088 for (int i = 0; i < fNumViews; ++i) {
89 fViews[i] = image->fViews[i]; // we ref in this case, not move
Brian Salomonad8efda2019-05-10 09:22:49 -040090 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050091 }
92 memcpy(fYUVAIndices, image->fYUVAIndices, 4 * sizeof(SkYUVAIndex));
93}
94
Robert Phillips8defcc12019-03-05 15:58:59 -050095bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
Brian Salomonad8efda2019-05-10 09:22:49 -040096 // We shouldn't get here if the planes were already flattened to RGBA.
Greg Danielc7672092020-02-06 14:32:54 -050097 SkASSERT(fViews[0].proxy() && !fRGBView.proxy());
Robert Phillips8defcc12019-03-05 15:58:59 -050098 if (!context || !fContext->priv().matches(context)) {
99 return false;
100 }
Brian Salomon4759dca2020-07-14 15:44:15 -0400101 GrSurfaceProxyView newViews[4];
Brian Salomon69100f02020-07-21 10:49:25 -0400102 if (!context->priv().caps()->mipmapSupport()) {
Brian Salomon4759dca2020-07-14 15:44:15 -0400103 // We succeed in this case by doing nothing.
104 return true;
105 }
Greg Danielc7672092020-02-06 14:32:54 -0500106 for (int i = 0; i < fNumViews; ++i) {
Brian Salomon4759dca2020-07-14 15:44:15 -0400107 auto* t = fViews[i].asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -0400108 if (t->mipmapped() == GrMipmapped::kNo && (t->width() > 1 || t->height() > 1)) {
Brian Salomon4759dca2020-07-14 15:44:15 -0400109 if (!(newViews[i] = GrCopyBaseMipMapToView(context, fViews[i]))) {
Jim Van Verthf542cab2018-11-07 12:08:21 -0500110 return false;
111 }
Brian Salomon4759dca2020-07-14 15:44:15 -0400112 } else {
113 newViews[i] = fViews[i];
Jim Van Verth30e0d7f2018-11-02 13:36:42 -0400114 }
115 }
Brian Salomon4759dca2020-07-14 15:44:15 -0400116 for (int i = 0; i < fNumViews; ++i) {
117 fViews[i] = std::move(newViews[i]);
118 }
Jim Van Verth30e0d7f2018-11-02 13:36:42 -0400119 return true;
120}
121
Jim Van Verthf49262d2018-10-02 12:07:20 -0400122//////////////////////////////////////////////////////////////////////////////////////////////////
Jim Van Verthf49262d2018-10-02 12:07:20 -0400123
Adlai Holler40ad5fd2020-07-22 10:22:12 -0400124GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const GrFlushInfo& info) {
125 if (!fContext->priv().matches(dContext) || dContext->abandoned()) {
Greg Daniel55822f12020-05-26 11:26:45 -0400126 if (info.fSubmittedProc) {
127 info.fSubmittedProc(info.fSubmittedContext, false);
128 }
129 if (info.fFinishedProc) {
130 info.fFinishedProc(info.fFinishedContext);
131 }
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400132 return GrSemaphoresSubmitted::kNo;
133 }
134
Greg Danielc7672092020-02-06 14:32:54 -0500135 GrSurfaceProxy* proxies[4] = {fViews[0].proxy(), fViews[1].proxy(), fViews[2].proxy(),
136 fViews[3].proxy()};
Adlai Hollerc2bfcff2020-11-06 15:39:36 -0500137 size_t numProxies = fNumViews;
Greg Daniel1a372c32019-12-17 13:53:38 -0500138 if (fRGBView.proxy()) {
Brian Salomonad8efda2019-05-10 09:22:49 -0400139 // Either we've already flushed the flattening draw or the flattening is unflushed. In the
Greg Daniel1a372c32019-12-17 13:53:38 -0500140 // latter case it should still be ok to just pass fRGBView proxy because it in turn depends
141 // on the planar proxies and will cause all of their work to flush as well.
142 proxies[0] = fRGBView.proxy();
Brian Salomonad8efda2019-05-10 09:22:49 -0400143 numProxies = 1;
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400144 }
Robert Phillips80bfda82020-11-12 09:23:36 -0500145 return dContext->priv().flushSurfaces({proxies, numProxies},
146 SkSurface::BackendSurfaceAccess::kNoAccess,
147 info);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400148}
149
Greg Danielc7672092020-02-06 14:32:54 -0500150GrTextureProxy* SkImage_GpuYUVA::peekProxy() const { return fRGBView.asTextureProxy(); }
Robert Phillips193c4212019-03-04 12:18:53 -0500151
Greg Daniel1a372c32019-12-17 13:53:38 -0500152void SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context) const {
153 if (fRGBView.proxy()) {
154 return;
Jim Van Verthf49262d2018-10-02 12:07:20 -0400155 }
156
Robert Phillips6603a172019-03-05 12:35:44 -0500157 if (!context || !fContext->priv().matches(context)) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500158 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500159 }
160
Robert Phillips6603a172019-03-05 12:35:44 -0500161 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
Greg Daniele20fcad2020-01-08 11:52:34 -0500162 auto renderTargetContext = GrRenderTargetContext::Make(
163 context, GrColorType::kRGBA_8888, this->refColorSpace(), SkBackingFit::kExact,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400164 this->dimensions(), 1, GrMipmapped::kNo, GrProtected::kNo);
Robert Phillips6603a172019-03-05 12:35:44 -0500165 if (!renderTargetContext) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500166 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500167 }
168
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400169 sk_sp<GrColorSpaceXform> colorSpaceXform;
170 if (fFromColorSpace) {
171 colorSpaceXform = GrColorSpaceXform::Make(fFromColorSpace.get(), this->alphaType(),
172 this->colorSpace(), this->alphaType());
173 }
Robert Phillips6603a172019-03-05 12:35:44 -0500174 const SkRect rect = SkRect::MakeIWH(this->width(), this->height());
Adlai Holler52ea5772020-07-28 15:23:33 -0400175 const GrCaps& caps = *context->priv().caps();
176 if (!RenderYUVAToRGBA(caps, renderTargetContext.get(), rect, fYUVColorSpace,
Greg Danielc7672092020-02-06 14:32:54 -0500177 std::move(colorSpaceXform), fViews, fYUVAIndices)) {
Greg Daniel1a372c32019-12-17 13:53:38 -0500178 return;
Robert Phillips6603a172019-03-05 12:35:44 -0500179 }
180
Greg Daniel1a372c32019-12-17 13:53:38 -0500181 fRGBView = renderTargetContext->readSurfaceView();
Greg Daniel1a372c32019-12-17 13:53:38 -0500182 SkASSERT(fRGBView.swizzle() == GrSwizzle());
Greg Danielc7672092020-02-06 14:32:54 -0500183 for (auto& v : fViews) {
184 v.reset();
Brian Salomonad8efda2019-05-10 09:22:49 -0400185 }
Greg Daniel1a372c32019-12-17 13:53:38 -0500186}
187
Greg Daniel37c127f2020-02-05 10:37:27 -0500188GrSurfaceProxyView SkImage_GpuYUVA::refMippedView(GrRecordingContext* context) const {
Jim Van Verth803a5022018-11-05 15:55:53 -0500189 // if invalid or already has miplevels
Greg Daniel1a372c32019-12-17 13:53:38 -0500190 this->flattenToRGB(context);
Brian Salomon8c82a872020-07-21 12:09:58 -0400191 if (!fRGBView || fRGBView.asTextureProxy()->mipmapped() == GrMipmapped::kYes) {
Greg Danielcc104db2020-02-03 14:17:08 -0500192 return fRGBView;
Jim Van Verth803a5022018-11-05 15:55:53 -0500193 }
194
195 // need to generate mips for the proxy
Brian Salomonc5243782020-04-02 12:50:34 -0400196 auto mippedView = GrCopyBaseMipMapToView(context, fRGBView);
197 if (!mippedView) {
198 return {};
Jim Van Verth803a5022018-11-05 15:55:53 -0500199 }
200
Brian Salomonc5243782020-04-02 12:50:34 -0400201 fRGBView = std::move(mippedView);
202 return fRGBView;
Jim Van Verth803a5022018-11-05 15:55:53 -0500203}
204
Greg Daniel37c127f2020-02-05 10:37:27 -0500205const GrSurfaceProxyView* SkImage_GpuYUVA::view(GrRecordingContext* context) const {
Greg Daniel1a372c32019-12-17 13:53:38 -0500206 this->flattenToRGB(context);
Greg Daniel37c127f2020-02-05 10:37:27 -0500207 if (!fRGBView.proxy()) {
208 return nullptr;
209 }
210 return &fRGBView;
Greg Daniel81b98972019-12-13 11:09:43 -0500211}
212
Jim Van Verth9bf81202018-10-30 15:53:36 -0400213//////////////////////////////////////////////////////////////////////////////////////////////////
214
Greg Danielc7672092020-02-06 14:32:54 -0500215sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(
Adlai Holler3a220172020-07-15 10:37:50 -0400216 SkColorType, sk_sp<SkColorSpace> targetCS, GrDirectContext* direct) const {
Brian Osmanf48c9962019-01-14 11:15:50 -0500217 // We explicitly ignore color type changes, for now.
218
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500219 // we may need a mutex here but for now we expect usage to be in a single thread
220 if (fOnMakeColorSpaceTarget &&
Brian Osmanf48c9962019-01-14 11:15:50 -0500221 SkColorSpace::Equals(targetCS.get(), fOnMakeColorSpaceTarget.get())) {
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500222 return fOnMakeColorSpaceResult;
223 }
Adlai Holler3a220172020-07-15 10:37:50 -0400224 sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(sk_ref_sp(direct), this, targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500225 if (result) {
Brian Osmanf48c9962019-01-14 11:15:50 -0500226 fOnMakeColorSpaceTarget = targetCS;
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500227 fOnMakeColorSpaceResult = result;
228 }
229 return result;
230}
231
Brian Osmand5148372019-08-14 16:14:51 -0400232sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400233 return sk_make_sp<SkImage_GpuYUVA>(fContext, this->dimensions(), kNeedNewImageUniqueID,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400234 fYUVColorSpace, fViews, fNumViews, fYUVAIndices,
Brian Salomonc505a452020-04-06 10:29:02 -0400235 std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400236}
237
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500238//////////////////////////////////////////////////////////////////////////////////////////////////
239
Brian Salomonc1a249d2020-10-19 10:55:45 -0400240sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
241 const GrYUVABackendTextures& yuvaTextures,
242 sk_sp<SkColorSpace> imageColorSpace,
243 TextureReleaseProc textureReleaseProc,
244 ReleaseContext releaseContext) {
Brian Salomon694ff172020-11-04 16:54:28 -0500245 auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
Brian Salomonc1a249d2020-10-19 10:55:45 -0400246
247 SkYUVAIndex yuvaIndices[4];
248 int numTextures;
249 if (!yuvaTextures.toYUVAIndices(yuvaIndices) ||
250 !SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
251 return nullptr;
252 }
253 SkASSERT(numTextures == yuvaTextures.numPlanes());
254
255 GrSurfaceProxyView tempViews[4];
256 if (!SkImage_GpuBase::MakeTempTextureProxies(context,
257 yuvaTextures.textures().data(),
258 numTextures,
259 yuvaIndices,
260 yuvaTextures.textureOrigin(),
261 tempViews,
262 std::move(releaseHelper))) {
263 return nullptr;
264 }
265
266 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
267 yuvaTextures.yuvaInfo().dimensions(),
268 kNeedNewImageUniqueID,
269 yuvaTextures.yuvaInfo().yuvColorSpace(),
270 tempViews,
271 numTextures,
272 yuvaIndices,
273 imageColorSpace);
274}
275
Adlai Hollerb2705682020-10-20 10:11:53 -0400276sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* ctx,
Jim Van Verth9bf81202018-10-30 15:53:36 -0400277 SkYUVColorSpace colorSpace,
278 const GrBackendTexture yuvaTextures[],
279 const SkYUVAIndex yuvaIndices[4],
280 SkISize imageSize,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400281 GrSurfaceOrigin textureOrigin,
Robert Phillipse22c5ca2020-06-19 12:29:57 -0400282 sk_sp<SkColorSpace> imageColorSpace,
283 TextureReleaseProc textureReleaseProc,
284 ReleaseContext releaseContext) {
Brian Salomon694ff172020-11-04 16:54:28 -0500285 auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
Robert Phillipse22c5ca2020-06-19 12:29:57 -0400286
Jim Van Verth0e671942018-11-09 12:03:57 -0500287 int numTextures;
288 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
289 return nullptr;
Jim Van Verth9bf81202018-10-30 15:53:36 -0400290 }
291
Greg Danielc7672092020-02-06 14:32:54 -0500292 GrSurfaceProxyView tempViews[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500293 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400294 textureOrigin, tempViews,
Robert Phillipse22c5ca2020-06-19 12:29:57 -0400295 std::move(releaseHelper))) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500296 return nullptr;
Jim Van Verth9bf81202018-10-30 15:53:36 -0400297 }
298
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400299 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(ctx), imageSize, kNeedNewImageUniqueID, colorSpace,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400300 tempViews, numTextures, yuvaIndices, imageColorSpace);
Jim Van Verth9bf81202018-10-30 15:53:36 -0400301}
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500302
Adlai Holler302e8fb2020-09-14 11:58:06 -0400303sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400304 const SkYUVAPixmaps& pixmaps,
305 GrMipMapped buildMips,
306 bool limitToMaxTextureSize,
307 sk_sp<SkColorSpace> imageColorSpace) {
308 if (!context) {
309 return nullptr; // until we impl this for raster backend
310 }
311
312 if (!pixmaps.isValid()) {
313 return nullptr;
314 }
315
316 SkYUVAIndex yuvaIndices[4];
317 if (!pixmaps.toLegacy(nullptr, yuvaIndices)) {
318 return nullptr;
319 }
320
321 // SkImage_GpuYUVA doesn't yet support different encoded origins.
322 if (pixmaps.yuvaInfo().origin() != kTopLeft_SkEncodedOrigin) {
323 return nullptr;
324 }
325
326 if (!context->priv().caps()->mipmapSupport()) {
327 buildMips = GrMipMapped::kNo;
328 }
329
330 // Make proxies
331 GrSurfaceProxyView tempViews[4];
332 int numPlanes = pixmaps.numPlanes();
333 int maxTextureSize = context->priv().caps()->maxTextureSize();
334 for (int i = 0; i < numPlanes; ++i) {
335 const SkPixmap* pixmap = &pixmaps.plane(i);
336 SkAutoPixmapStorage resized;
337 int maxDim = std::max(pixmap->width(), pixmap->height());
338 if (maxDim > maxTextureSize) {
339 if (!limitToMaxTextureSize) {
340 return nullptr;
341 }
342 float scale = static_cast<float>(maxTextureSize)/maxDim;
343 int newWidth = std::min(static_cast<int>(pixmap->width() *scale), maxTextureSize);
344 int newHeight = std::min(static_cast<int>(pixmap->height()*scale), maxTextureSize);
345 SkImageInfo info = pixmap->info().makeWH(newWidth, newHeight);
346 if (!resized.tryAlloc(info) || !pixmap->scalePixels(resized, kLow_SkFilterQuality)) {
347 return nullptr;
348 }
349 pixmap = &resized;
350 }
351 // Turn the pixmap into a GrTextureProxy
352 SkBitmap bmp;
353 bmp.installPixels(*pixmap);
354 GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
355 tempViews[i] = bitmapMaker.view(buildMips);
356 if (!tempViews[i]) {
357 return nullptr;
358 }
359 }
360
361 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
362 pixmaps.yuvaInfo().dimensions(),
363 kNeedNewImageUniqueID,
364 pixmaps.yuvaInfo().yuvColorSpace(),
365 tempViews,
366 numPlanes,
367 yuvaIndices,
Brian Salomonc2a9a972020-09-15 11:24:28 -0400368 std::move(imageColorSpace));
Jim Van Verthc8429ad2018-11-20 11:12:37 -0500369}
370
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400371/////////////////////////////////////////////////////////////////////////////////////////////////
Brian Salomonf1432742020-11-09 15:40:27 -0500372
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500373sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
Robert Phillips07531a02020-07-15 15:11:09 -0400374 GrRecordingContext* context,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500375 SkYUVColorSpace yuvColorSpace,
376 const GrBackendFormat yuvaFormats[],
377 const SkISize yuvaSizes[],
378 const SkYUVAIndex yuvaIndices[4],
379 int imageWidth,
380 int imageHeight,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400381 GrSurfaceOrigin textureOrigin,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500382 sk_sp<SkColorSpace> imageColorSpace,
383 PromiseImageTextureFulfillProc textureFulfillProc,
384 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf1432742020-11-09 15:40:27 -0500385 PromiseImageTextureContext textureContexts[]) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400386 int numTextures;
387 bool valid = SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures);
388
Brian Salomonf1432742020-11-09 15:40:27 -0500389 // Our contract is that we will always call the release proc even on failure.
390 // We use the helper to convey the context, so we need to ensure make doesn't fail.
391 textureReleaseProc = textureReleaseProc ? textureReleaseProc : [](void*) {};
392 sk_sp<GrRefCntedCallback> releaseHelpers[4];
393 for (int i = 0; i < numTextures; ++i) {
394 releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
395 }
396
397 if (!context) {
Brian Salomonbe5a0932018-12-10 10:03:26 -0500398 return nullptr;
Jim Van Verthf00b1622018-10-10 13:03:23 -0400399 }
400
401 if (!valid) {
402 return nullptr;
403 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400404
Greg Kaiser9a2169e2019-02-10 17:29:46 -0800405 if (imageWidth <= 0 || imageHeight <= 0) {
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400406 return nullptr;
407 }
408
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400409 SkAlphaType at = (-1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex) ? kPremul_SkAlphaType
410 : kOpaque_SkAlphaType;
Greg Danielc7672092020-02-06 14:32:54 -0500411 SkImageInfo info =
412 SkImageInfo::Make(imageWidth, imageHeight, kAssumedColorType, at, imageColorSpace);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400413 if (!SkImageInfoIsValid(info)) {
414 return nullptr;
415 }
416
Jim Van Verthf9f07352018-10-24 10:32:20 -0400417 // verify sizes with expected texture count
Jim Van Verth8f11e432018-10-18 14:36:59 -0400418 for (int i = 0; i < numTextures; ++i) {
Jim Van Verthf9f07352018-10-24 10:32:20 -0400419 if (yuvaSizes[i].isEmpty()) {
Jim Van Verth8f11e432018-10-18 14:36:59 -0400420 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400421 }
422 }
Jim Van Verthe24b5872018-10-29 16:26:02 -0400423 for (int i = numTextures; i < SkYUVASizeInfo::kMaxCount; ++i) {
Jim Van Verthf9f07352018-10-24 10:32:20 -0400424 if (!yuvaSizes[i].isEmpty()) {
Jim Van Verth8f11e432018-10-18 14:36:59 -0400425 return nullptr;
426 }
Jim Van Verthf99a6742018-10-18 16:13:18 +0000427 }
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400428
429 // Get lazy proxies
Greg Danielc7672092020-02-06 14:32:54 -0500430 GrSurfaceProxyView views[4];
Jim Van Verthf00b1622018-10-10 13:03:23 -0400431 for (int texIdx = 0; texIdx < numTextures; ++texIdx) {
Brian Salomonf1432742020-11-09 15:40:27 -0500432 auto proxy = MakePromiseImageLazyProxy(context,
433 yuvaSizes[texIdx],
434 yuvaFormats[texIdx],
435 GrMipmapped::kNo,
436 textureFulfillProc,
437 std::move(releaseHelpers[texIdx]));
Greg Danielc7672092020-02-06 14:32:54 -0500438 if (!proxy) {
Jim Van Verthf00b1622018-10-10 13:03:23 -0400439 return nullptr;
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400440 }
Brian Salomon8e5cf442020-10-05 16:05:23 -0400441 views[texIdx] = GrSurfaceProxyView(std::move(proxy), textureOrigin, GrSwizzle("rgba"));
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400442 }
443
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400444 return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), SkISize{imageWidth, imageHeight},
Brian Salomonc505a452020-04-06 10:29:02 -0400445 kNeedNewImageUniqueID, yuvColorSpace, views, numTextures,
Brian Salomon8e5cf442020-10-05 16:05:23 -0400446 yuvaIndices, std::move(imageColorSpace));
Jim Van Verth8bbce0e2018-10-08 14:34:52 -0400447}