Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f01a9d9

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
Add SkImage::MakeFromYUVATexturesCopyToExternal
Updated API for creating a RGBA texture-backed image from RGBA texture planes with user-provided backing store using GrYUVABackendTextures. Ultimately we would like to remove all such APIs and have the client make a SkSurface and draw a YUVA texture image to the surface but a recent attempt to do that in Chrome caused a not yet understood perf regression. Add wacky_yuv_formats variation that tests new api. Bug: skia:10632 Change-Id: I89411216948682f13281a91a7575d5f345badda7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329956 Commit-Queue: Brian Salomon <[email protected]> Reviewed-by: Robert Phillips <[email protected]>
1 parent eb999bc commit f01a9d9

File tree

9 files changed

+225
-53
lines changed

9 files changed

+225
-53
lines changed

RELEASE_NOTES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ Milestone 88
2323
which wraps an SkYUVAInfo and compatible set of GrBackendTextures. The provides
2424
a more complete and structured specification of the planar configuration. Previous
2525
version is deprecated.
26+
Already deprecated MakeFromYUVATexturesCopyToExternal added to replace other deprecated
27+
APIs. It's not recommended that clients use this and instead use the pattern described
28+
in the API comment.
2629
https://review.skia.org/317762
30+
https://review.skia.org/329956
2731

2832
* Add field to GrContextOptions to disable mipmap support even if the backend
2933
supports it.

gm/wacky_yuv_formats.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,9 @@ class WackyYUVFormatsGM : public GM {
752752
case Type::kFromGenerator:
753753
name += "_imggen";
754754
break;
755+
case Type::kFromTexturesCopyToExternal:
756+
name += "_fromtextureswithcopy";
757+
break;
755758
}
756759

757760
return name;
@@ -943,6 +946,9 @@ DEF_GM(return new WackyYUVFormatsGM(/* target cs */ false,
943946
DEF_GM(return new WackyYUVFormatsGM(/* target cs */ false,
944947
/* subset */ false,
945948
WackyYUVFormatsGM::Type::kFromPixmaps);)
949+
DEF_GM(return new WackyYUVFormatsGM(/* target cs */ false,
950+
/* subset */ false,
951+
WackyYUVFormatsGM::Type::kFromTexturesCopyToExternal);)
946952

947953
class YUVMakeColorSpaceGM : public GpuGM {
948954
public:

include/core/SkImage.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,46 @@ class SK_API SkImage : public SkRefCnt {
428428
TextureReleaseProc textureReleaseProc = nullptr,
429429
ReleaseContext releaseContext = nullptr);
430430

431+
/** Deprecated.
432+
Creates an SkImage from YUV[A] planar textures by copying them to another caller-provided
433+
texture and retaining that result texture in the SkImage. This should be preferred over
434+
MakeFromYUVTexturesCopyWithExternalBackend and MakeFromNV12TexturesCopyWithExternalBackend.
435+
However, this is deprecated and instead clients should make a SkSurface from
436+
'rgbaResultTexture` using SkSurface::MakeFromBackendTexture, make an image from the planes
437+
using MakeFromYUVATextures, and finally draw the image to the surface.
438+
439+
Note that the draw that converts to RGBA is not issued to the underlying API until a flush/
440+
submit occurs so the YUVA textures are not safe to delete or overwrite until yuvaReleaseProc
441+
is called.
442+
443+
The dimensions of the result RGBA texture must match the dimensions of the YUVA planar data.
444+
445+
@param context GPU context
446+
@param yuvaTextures A set of textures containing YUVA data and a description of the
447+
data and transformation to RGBA.
448+
@param rgbaResultTexture The renderable texture that will hold the result of the conversion
449+
to RGBA and be retained in the resulting SkImage.
450+
@param colorType colorType of the result as stored in rgbaResultTexture. Must be
451+
compatible with the texture's format.
452+
@param imageColorSpace range of colors of the resulting image after conversion to RGB;
453+
may be nullptr
454+
@param yuvaReleaseProc called when the backend textures in 'yuvaTextures' can be released
455+
@param yuvaReleaseContext state passed to yuvaReleaseProc
456+
@param rgbaReleaseProc called when the 'rgbaResultTexture' can be released
457+
@param rgbaReleaseContext state passed to rgbaReleaseProc
458+
@return created SkImage, or nullptr
459+
*/
460+
static sk_sp<SkImage> MakeFromYUVATexturesCopyToExternal(
461+
GrRecordingContext* context,
462+
const GrYUVABackendTextures& yuvaTextures,
463+
const GrBackendTexture& rgbaResultTexture,
464+
SkColorType colorType,
465+
sk_sp<SkColorSpace> imageColorSpace = nullptr,
466+
TextureReleaseProc yuvaReleaseProc = nullptr,
467+
ReleaseContext yuvaReleaseContext = nullptr,
468+
TextureReleaseProc rgbaReleaseProc = nullptr,
469+
ReleaseContext rgbaReleaseContext = nullptr);
470+
431471
/**
432472
Deprecated. Use version that takes GrYUVABackendTextures.
433473

include/core/SkYUVAPixmaps.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,11 @@ class SK_API SkYUVAPixmapInfo {
171171
*/
172172
class SK_API SkYUVAPixmaps {
173173
public:
174+
using DataType = SkYUVAPixmapInfo::DataType;
174175
static constexpr auto kMaxPlanes = SkYUVAPixmapInfo::kMaxPlanes;
175176

177+
static SkColorType RecommendedRGBAColorType(DataType);
178+
176179
/** Allocate space for pixmaps' pixels in the SkYUVAPixmaps. */
177180
static SkYUVAPixmaps Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo);
178181

@@ -217,6 +220,8 @@ class SK_API SkYUVAPixmaps {
217220

218221
const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
219222

223+
DataType dataType() const { return fDataType; }
224+
220225
SkYUVAPixmapInfo pixmapsInfo() const;
221226

222227
/** Number of pixmap planes or 0 if this SkYUVAPixmaps is invalid. */
@@ -250,11 +255,12 @@ class SK_API SkYUVAPixmaps {
250255

251256
private:
252257
SkYUVAPixmaps(const SkYUVAPixmapInfo&, sk_sp<SkData>);
253-
SkYUVAPixmaps(const SkYUVAInfo&, const SkPixmap[kMaxPlanes]);
258+
SkYUVAPixmaps(const SkYUVAInfo&, DataType, const SkPixmap[kMaxPlanes]);
254259

255-
SkYUVAInfo fYUVAInfo;
256260
std::array<SkPixmap, kMaxPlanes> fPlanes = {};
257261
sk_sp<SkData> fData;
262+
SkYUVAInfo fYUVAInfo;
263+
DataType fDataType;
258264
};
259265

260266
//////////////////////////////////////////////////////////////////////////////

src/core/SkYUVAPixmaps.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ bool SkYUVAPixmapInfo::isSupported(const SupportedDataTypes& supportedDataTypes)
177177

178178
//////////////////////////////////////////////////////////////////////////////
179179

180+
SkColorType SkYUVAPixmaps::RecommendedRGBAColorType(DataType dataType) {
181+
switch (dataType) {
182+
case DataType::kUnorm8: return kRGBA_8888_SkColorType;
183+
// F16 has better GPU support than 16 bit unorm. Often "16" bit unorm values are actually
184+
// lower precision.
185+
case DataType::kUnorm16: return kRGBA_F16_SkColorType;
186+
case DataType::kFloat16: return kRGBA_F16_SkColorType;
187+
case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
188+
}
189+
SkUNREACHABLE;
190+
}
191+
180192
SkYUVAPixmaps SkYUVAPixmaps::Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo) {
181193
if (!yuvaPixmapInfo.isValid()) {
182194
return {};
@@ -223,7 +235,7 @@ SkYUVAPixmaps SkYUVAPixmaps::FromExternalMemory(const SkYUVAPixmapInfo& yuvaPixm
223235
}
224236
SkPixmap pixmaps[kMaxPlanes];
225237
yuvaPixmapInfo.initPixmapsFromSingleAllocation(memory, pixmaps);
226-
return SkYUVAPixmaps(yuvaPixmapInfo.yuvaInfo(), pixmaps);
238+
return SkYUVAPixmaps(yuvaPixmapInfo.yuvaInfo(), yuvaPixmapInfo.dataType(), pixmaps);
227239
}
228240

229241
SkYUVAPixmaps SkYUVAPixmaps::FromExternalPixmaps(const SkYUVAInfo& yuvaInfo,
@@ -235,23 +247,27 @@ SkYUVAPixmaps SkYUVAPixmaps::FromExternalPixmaps(const SkYUVAInfo& yuvaInfo,
235247
colorTypes[i] = pixmaps[i].colorType();
236248
rowBytes[i] = pixmaps[i].rowBytes();
237249
}
238-
if (!SkYUVAPixmapInfo(yuvaInfo, colorTypes, rowBytes).isValid()) {
250+
SkYUVAPixmapInfo yuvaPixmapInfo(yuvaInfo, colorTypes, rowBytes);
251+
if (!yuvaPixmapInfo.isValid()) {
239252
return {};
240253
}
241-
return SkYUVAPixmaps(yuvaInfo, pixmaps);
254+
return SkYUVAPixmaps(yuvaInfo, yuvaPixmapInfo.dataType(), pixmaps);
242255
}
243256

244257
SkYUVAPixmaps::SkYUVAPixmaps(const SkYUVAPixmapInfo& yuvaPixmapInfo, sk_sp<SkData> data)
245-
: fYUVAInfo(yuvaPixmapInfo.yuvaInfo())
246-
, fData(std::move(data)) {
258+
: fData(std::move(data))
259+
, fYUVAInfo(yuvaPixmapInfo.yuvaInfo())
260+
, fDataType(yuvaPixmapInfo.dataType()) {
247261
SkASSERT(yuvaPixmapInfo.isValid());
248262
SkASSERT(yuvaPixmapInfo.computeTotalBytes() <= fData->size());
249263
SkAssertResult(yuvaPixmapInfo.initPixmapsFromSingleAllocation(fData->writable_data(),
250264
fPlanes.data()));
251265
}
252266

253-
SkYUVAPixmaps::SkYUVAPixmaps(const SkYUVAInfo& yuvaInfo, const SkPixmap pixmaps[kMaxPlanes])
254-
: fYUVAInfo(yuvaInfo) {
267+
SkYUVAPixmaps::SkYUVAPixmaps(const SkYUVAInfo& yuvaInfo,
268+
DataType dataType,
269+
const SkPixmap pixmaps[kMaxPlanes])
270+
: fYUVAInfo(yuvaInfo), fDataType(dataType) {
255271
std::copy_n(pixmaps, yuvaInfo.numPlanes(), fPlanes.data());
256272
}
257273

src/image/SkImage_Gpu.cpp

Lines changed: 89 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
* found in the LICENSE file.
66
*/
77

8-
#include <cstddef>
9-
#include <cstring>
10-
#include <type_traits>
8+
#include "src/image/SkImage_Gpu.h"
119

1210
#include "include/core/SkCanvas.h"
1311
#include "include/gpu/GrBackendSurface.h"
1412
#include "include/gpu/GrDirectContext.h"
1513
#include "include/gpu/GrRecordingContext.h"
14+
#include "include/gpu/GrYUVABackendTextures.h"
1615
#include "include/private/SkImageInfoPriv.h"
1716
#include "src/core/SkAutoPixmapStorage.h"
1817
#include "src/core/SkBitmapCache.h"
@@ -42,7 +41,10 @@
4241
#include "src/gpu/GrTextureProxyPriv.h"
4342
#include "src/gpu/SkGr.h"
4443
#include "src/gpu/gl/GrGLTexture.h"
45-
#include "src/image/SkImage_Gpu.h"
44+
45+
#include <cstddef>
46+
#include <cstring>
47+
#include <type_traits>
4648

4749
SkImage_Gpu::SkImage_Gpu(sk_sp<GrImageContext> context, uint32_t uniqueID, GrSurfaceProxyView view,
4850
SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> colorSpace)
@@ -325,9 +327,11 @@ sk_sp<SkImage> SkImage::MakeTextureFromCompressed(GrDirectContext* direct, sk_sp
325327
sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrRecordingContext* rContext,
326328
SkYUVColorSpace yuvColorSpace,
327329
const GrBackendTexture yuvaTextures[],
328-
const SkYUVAIndex yuvaIndices[4], SkISize size,
330+
const SkYUVAIndex yuvaIndices[4],
331+
SkISize size,
329332
GrSurfaceOrigin origin,
330-
GrRenderTargetContext* renderTargetContext) {
333+
GrRenderTargetContext* renderTargetContext,
334+
sk_sp<GrRefCntedCallback> releaseHelper) {
331335
SkASSERT(renderTargetContext);
332336

333337
int numTextures;
@@ -337,7 +341,7 @@ sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrRecordingContext* rContex
337341

338342
GrSurfaceProxyView tempViews[4];
339343
if (!SkImage_GpuBase::MakeTempTextureProxies(rContext, yuvaTextures, numTextures, yuvaIndices,
340-
origin, tempViews, nullptr)) {
344+
origin, tempViews, std::move(releaseHelper))) {
341345
return nullptr;
342346
}
343347

@@ -364,39 +368,29 @@ static sk_sp<SkImage> make_flattened_image_with_external_backend(
364368
SkISize imageSize,
365369
GrSurfaceOrigin imageOrigin,
366370
const GrBackendTexture& backendTexture,
371+
GrColorType colorType,
367372
sk_sp<SkColorSpace> imageColorSpace,
368-
SkImage::TextureReleaseProc textureReleaseProc,
369-
SkImage::ReleaseContext releaseContext) {
373+
sk_sp<GrRefCntedCallback> yuvaReleaseHelper,
374+
sk_sp<GrRefCntedCallback> rgbaReleaseHelper) {
370375
const GrCaps* caps = rContext->priv().caps();
371-
372-
sk_sp<GrRefCntedCallback> releaseHelper;
373-
if (textureReleaseProc) {
374-
releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
375-
}
376-
377-
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
378-
backendTexture.getBackendFormat());
379-
if (GrColorType::kUnknown == grColorType) {
380-
return nullptr;
381-
}
382-
383376
SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
384-
if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
377+
if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, colorType,
385378
kRGBA_8888_SkColorType, at, nullptr)) {
386379
return nullptr;
387380
}
388381

389382
// Needs to create a render target with external texture
390383
// in order to draw to it for the yuv->rgb conversion.
391384
auto renderTargetContext = GrRenderTargetContext::MakeFromBackendTexture(
392-
rContext, grColorType, std::move(imageColorSpace), backendTexture, 1, imageOrigin,
393-
nullptr, std::move(releaseHelper));
385+
rContext, colorType, std::move(imageColorSpace), backendTexture, 1, imageOrigin,
386+
nullptr, std::move(rgbaReleaseHelper));
394387
if (!renderTargetContext) {
395388
return nullptr;
396389
}
397390

398391
return SkImage_Gpu::ConvertYUVATexturesToRGB(rContext, yuvColorSpace, yuvaTextures, yuvaIndices,
399-
imageSize, imageOrigin, renderTargetContext.get());
392+
imageSize, imageOrigin, renderTargetContext.get(),
393+
std::move(yuvaReleaseHelper));
400394
}
401395

402396
// Some YUVA factories infer the YUVAIndices. This helper identifies the channel to use for single
@@ -413,6 +407,48 @@ static SkColorChannel get_single_channel(const GrBackendTexture& tex) {
413407
}
414408
}
415409

410+
sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyToExternal(
411+
GrRecordingContext* context,
412+
const GrYUVABackendTextures& yuvaTextures,
413+
const GrBackendTexture& rgbaResultTexture,
414+
SkColorType colorType,
415+
sk_sp<SkColorSpace> imageColorSpace,
416+
TextureReleaseProc yuvaReleaseProc,
417+
ReleaseContext yuvaReleaseContext,
418+
TextureReleaseProc rgbaReleaseProc,
419+
ReleaseContext rgbaReleaseContext) {
420+
sk_sp<GrRefCntedCallback> yuvaReleaseHelper;
421+
if (yuvaReleaseProc) {
422+
yuvaReleaseHelper.reset(new GrRefCntedCallback(yuvaReleaseProc, yuvaReleaseContext));
423+
}
424+
sk_sp<GrRefCntedCallback> rgbaReleaseHelper;
425+
if (rgbaReleaseProc) {
426+
rgbaReleaseHelper.reset(new GrRefCntedCallback(rgbaReleaseProc, rgbaReleaseContext));
427+
}
428+
429+
SkYUVAIndex yuvaIndices[4];
430+
int numTextures;
431+
if (!yuvaTextures.toYUVAIndices(yuvaIndices) ||
432+
!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
433+
return nullptr;
434+
}
435+
SkASSERT(numTextures == yuvaTextures.numPlanes());
436+
if (rgbaResultTexture.dimensions() != yuvaTextures.yuvaInfo().dimensions()) {
437+
return nullptr;
438+
}
439+
return make_flattened_image_with_external_backend(context,
440+
yuvaTextures.yuvaInfo().yuvColorSpace(),
441+
yuvaTextures.textures().data(),
442+
yuvaIndices,
443+
rgbaResultTexture.dimensions(),
444+
yuvaTextures.textureOrigin(),
445+
rgbaResultTexture,
446+
SkColorTypeToGrColorType(colorType),
447+
std::move(imageColorSpace),
448+
std::move(yuvaReleaseHelper),
449+
std::move(rgbaReleaseHelper));
450+
}
451+
416452
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
417453
GrRecordingContext* ctx, SkYUVColorSpace yuvColorSpace,
418454
const GrBackendTexture yuvTextures[3], GrSurfaceOrigin imageOrigin,
@@ -422,9 +458,17 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
422458
SkYUVAIndex{1, get_single_channel(yuvTextures[1])},
423459
SkYUVAIndex{2, get_single_channel(yuvTextures[2])},
424460
SkYUVAIndex{-1, SkColorChannel::kA}};
425-
return make_flattened_image_with_external_backend(
426-
ctx, yuvColorSpace, yuvTextures, yuvaIndices, yuvTextures[0].dimensions(), imageOrigin,
427-
backendTexture, std::move(imageColorSpace), nullptr, nullptr);
461+
return make_flattened_image_with_external_backend(ctx,
462+
yuvColorSpace,
463+
yuvTextures,
464+
yuvaIndices,
465+
yuvTextures[0].dimensions(),
466+
imageOrigin,
467+
backendTexture,
468+
GrColorType::kRGBA_8888,
469+
std::move(imageColorSpace),
470+
nullptr,
471+
nullptr);
428472
}
429473

430474
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
@@ -436,15 +480,29 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
436480
sk_sp<SkColorSpace> imageColorSpace,
437481
TextureReleaseProc textureReleaseProc,
438482
ReleaseContext releaseContext) {
483+
sk_sp<GrRefCntedCallback> releaseHelper;
484+
if (textureReleaseProc) {
485+
releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
486+
}
487+
439488
SkYUVAIndex yuvaIndices[4] = {
440489
SkYUVAIndex{0, get_single_channel(nv12Textures[0])},
441490
SkYUVAIndex{1, SkColorChannel::kR},
442491
SkYUVAIndex{1, SkColorChannel::kG},
443492
SkYUVAIndex{-1, SkColorChannel::kA}};
444493
SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
445-
return make_flattened_image_with_external_backend(
446-
ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
447-
std::move(imageColorSpace), textureReleaseProc, releaseContext);
494+
495+
return make_flattened_image_with_external_backend(ctx,
496+
yuvColorSpace,
497+
nv12Textures,
498+
yuvaIndices,
499+
size,
500+
imageOrigin,
501+
backendTexture,
502+
GrColorType::kRGBA_8888,
503+
std::move(imageColorSpace),
504+
/* plane release helper*/ nullptr,
505+
std::move(releaseHelper));
448506
}
449507

450508
static sk_sp<SkImage> create_image_from_producer(GrRecordingContext* context,

0 commit comments

Comments
 (0)