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

Commit fea1223

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
New variant of SkImage::MakeFromYUVATextures.
Takes a new type GrYUVATextures. This a set of GrBackendTextures and SkYUVAInfo that have been pre-validated to be compatible. Bug: skia:10632 Change-Id: Id252f8662ede0f268e88fd40dc1b0b8f4ab6345f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/317762 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
1 parent 137068d commit fea1223

File tree

10 files changed

+225
-18
lines changed

10 files changed

+225
-18
lines changed

RELEASE_NOTES.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ This file includes a list of high level updates for each milestone release.
66

77
Milestone 88
88
------------
9-
109
* <insert new release notes here>
1110

11+
* New variant of SkImage::MakeFromYUVATextures. Takes a new type GrYUVATextures
12+
which wraps an SkYUVAInfo and compatible set of GrBackendTextures. The provides
13+
a more complete and structured specification of the planar configuration. Previous
14+
version is deprecated.
15+
1216
* SkTPin() removed from public API.
1317

1418
* Add new SkImageFilters::Blend factory function, in place of the now deprecated

gn/gpu.gni

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ skia_gpu_sources = [
1919
"$_include/gpu/GrDriverBugWorkarounds.h",
2020
"$_include/gpu/GrRecordingContext.h",
2121
"$_include/gpu/GrTypes.h",
22+
"$_include/gpu/GrYUVABackendTextures.h",
2223

2324
# Private includes
2425
"$_include/private/GrContext.h",
@@ -269,6 +270,7 @@ skia_gpu_sources = [
269270
"$_src/gpu/GrWindowRectsState.h",
270271
"$_src/gpu/GrXferProcessor.cpp",
271272
"$_src/gpu/GrXferProcessor.h",
273+
"$_src/gpu/GrYUVABackendTextures.cpp",
272274

273275
# Ops
274276
"$_src/gpu/effects/GrBezierEffect.cpp",

include/core/SkImage.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class GrContext;
3838
class GrDirectContext;
3939
class GrRecordingContext;
4040
class GrContextThreadSafeProxy;
41+
class GrYUVABackendTextures;
4142

4243
struct SkYUVAIndex;
4344

@@ -408,7 +409,30 @@ class SK_API SkImage : public SkRefCnt {
408409
SkAlphaType alphaType = kPremul_SkAlphaType,
409410
sk_sp<SkColorSpace> colorSpace = nullptr);
410411

411-
/** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
412+
/** Creates an SkImage from YUV[A] planar textures. This requires that the textures stay valid
413+
for the lifetime of the image. The ReleaseContext can be used to know when it is safe to
414+
either delete or overwrite the textures. If ReleaseProc is provided it is also called before
415+
return on failure.
416+
417+
@param context GPU context
418+
@param yuvaTextures A set of textures containing YUVA data and a description of the
419+
data and transformation to RGBA.
420+
@param imageColorSpace range of colors of the resulting image after conversion to RGB;
421+
may be nullptr
422+
@param textureReleaseProc called when the backend textures can be released
423+
@param releaseContext state passed to textureReleaseProc
424+
@return created SkImage, or nullptr
425+
*/
426+
static sk_sp<SkImage> MakeFromYUVATextures(GrRecordingContext* context,
427+
const GrYUVABackendTextures& yuvaTextures,
428+
sk_sp<SkColorSpace> imageColorSpace = nullptr,
429+
TextureReleaseProc textureReleaseProc = nullptr,
430+
ReleaseContext releaseContext = nullptr);
431+
432+
/**
433+
Deprecated. Use version that takes GrYUVABackendTextures.
434+
435+
Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
412436
via multitexturing.
413437
414438
When all the provided backend textures can be released 'textureReleaseProc' will be called

include/core/SkYUVAInfo.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class SK_API SkYUVAInfo {
3939
* this expands.
4040
*/
4141
enum class PlanarConfig {
42+
kUnknown,
43+
4244
kY_U_V_444, ///< Plane 0: Y, Plane 1: U, Plane 2: V
4345
kY_U_V_422, ///< Plane 0: Y, Plane 1: U, Plane 2: V
4446
kY_U_V_420, ///< Plane 0: Y, Plane 1: U, Plane 2: V
@@ -177,10 +179,12 @@ class SK_API SkYUVAInfo {
177179
bool operator==(const SkYUVAInfo& that) const;
178180
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
179181

182+
bool isValid() const { return fPlanarConfig != PlanarConfig::kUnknown; }
183+
180184
private:
181185
SkISize fDimensions = {0, 0};
182186

183-
PlanarConfig fPlanarConfig = PlanarConfig::kY_U_V_444;
187+
PlanarConfig fPlanarConfig = PlanarConfig::kUnknown;
184188

185189
SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
186190

@@ -196,6 +200,8 @@ class SK_API SkYUVAInfo {
196200

197201
constexpr int SkYUVAInfo::NumPlanes(PlanarConfig planarConfig) {
198202
switch (planarConfig) {
203+
case PlanarConfig::kUnknown: return 0;
204+
199205
case PlanarConfig::kY_U_V_444: return 3;
200206
case PlanarConfig::kY_U_V_422: return 3;
201207
case PlanarConfig::kY_U_V_420: return 3;
@@ -223,6 +229,9 @@ constexpr int SkYUVAInfo::NumPlanes(PlanarConfig planarConfig) {
223229

224230
constexpr int SkYUVAInfo::NumChannelsInPlane(PlanarConfig config, int i) {
225231
switch (config) {
232+
case PlanarConfig::kUnknown:
233+
return 0;
234+
226235
case SkYUVAInfo::PlanarConfig::kY_U_V_444:
227236
case SkYUVAInfo::PlanarConfig::kY_U_V_422:
228237
case SkYUVAInfo::PlanarConfig::kY_U_V_420:
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2020 Google LLC
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+
#ifndef GrYUVABackendTextures_DEFINED
9+
#define GrYUVABackendTextures_DEFINED
10+
11+
#include "include/core/SkYUVAInfo.h"
12+
#include "include/gpu/GrBackendSurface.h"
13+
14+
#include <tuple>
15+
16+
struct SkYUVASizeInfo;
17+
struct SkYUVAIndex;
18+
19+
/**
20+
* A set of GrBackendTextures that hold the planar data for a SkYUVAInfo.
21+
*/
22+
class SK_API GrYUVABackendTextures {
23+
public:
24+
GrYUVABackendTextures() = default;
25+
GrYUVABackendTextures(const GrYUVABackendTextures&) = delete;
26+
GrYUVABackendTextures(GrYUVABackendTextures&&) = default;
27+
28+
GrYUVABackendTextures& operator=(const GrYUVABackendTextures&) = delete;
29+
GrYUVABackendTextures& operator=(GrYUVABackendTextures&&) = default;
30+
31+
GrYUVABackendTextures(const SkYUVAInfo&,
32+
const GrBackendTexture[SkYUVAInfo::kMaxPlanes],
33+
GrSurfaceOrigin textureOrigin);
34+
35+
const std::array<GrBackendTexture, SkYUVAInfo::kMaxPlanes>& textures() const {
36+
return fTextures;
37+
}
38+
39+
GrBackendTexture texture(int i) const {
40+
SkASSERT(i >= 0 && i < SkYUVAInfo::kMaxPlanes);
41+
return fTextures[static_cast<size_t>(i)];
42+
}
43+
44+
const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
45+
46+
int numPlanes() const { return fYUVAInfo.numPlanes(); }
47+
48+
GrSurfaceOrigin textureOrigin() const { return fTextureOrigin; }
49+
50+
bool isValid() const { return fYUVAInfo.isValid(); }
51+
52+
bool toYUVAIndices(SkYUVAIndex[SkYUVAIndex::kIndexCount]) const;
53+
54+
private:
55+
SkYUVAInfo fYUVAInfo;
56+
std::array<GrBackendTexture, SkYUVAInfo::kMaxPlanes> fTextures;
57+
GrSurfaceOrigin fTextureOrigin = kTopLeft_GrSurfaceOrigin;
58+
};
59+
60+
#endif

src/core/SkYUVAInfo.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
1212
PlanarConfig planarConfig,
1313
SkEncodedOrigin origin,
14-
SkISize* planeDimensions) {
14+
SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]) {
1515
int w = imageDimensions.width();
1616
int h = imageDimensions.height();
1717
if (origin >= kLeftTop_SkEncodedOrigin) {
@@ -21,6 +21,12 @@ int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
2121
auto down2 = [](int x) { return (x + 1)/2; };
2222
auto down4 = [](int x) { return (x + 3)/4; };
2323
switch (planarConfig) {
24+
case PlanarConfig::kUnknown:
25+
planeDimensions[0] =
26+
planeDimensions[1] =
27+
planeDimensions[2] =
28+
planeDimensions[3] = {0, 0};
29+
return 0;
2430
case PlanarConfig::kY_U_V_444:
2531
planeDimensions[0] = planeDimensions[1] = planeDimensions[2] = {w, h};
2632
planeDimensions[3] = {0, 0};
@@ -125,6 +131,9 @@ bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
125131
struct Location {int plane, chanIdx;};
126132
const Location* locations = nullptr;
127133
switch (config) {
134+
case PlanarConfig::kUnknown:
135+
return false;
136+
128137
case PlanarConfig::kY_U_V_444:
129138
case PlanarConfig::kY_U_V_422:
130139
case PlanarConfig::kY_U_V_420:
@@ -210,6 +219,8 @@ bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
210219

211220
bool SkYUVAInfo::HasAlpha(PlanarConfig planarConfig) {
212221
switch (planarConfig) {
222+
case PlanarConfig::kUnknown: return false;
223+
213224
case PlanarConfig::kY_U_V_444: return false;
214225
case PlanarConfig::kY_U_V_422: return false;
215226
case PlanarConfig::kY_U_V_420: return false;
@@ -247,11 +258,20 @@ SkYUVAInfo::SkYUVAInfo(SkISize dimensions,
247258
, fYUVColorSpace(yuvColorSpace)
248259
, fOrigin(origin)
249260
, fSitingX(sitingX)
250-
, fSitingY(sitingY) {}
261+
, fSitingY(sitingY) {
262+
if (fDimensions.width() <= 0 ||
263+
fDimensions.height() <= 0 ||
264+
planarConfig == PlanarConfig::kUnknown) {
265+
*this = {};
266+
SkASSERT(!this->isValid());
267+
return;
268+
}
269+
SkASSERT(this->isValid());
270+
}
251271

252272
size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
253273
size_t planeSizes[kMaxPlanes]) const {
254-
if (fDimensions.isEmpty()) {
274+
if (!this->isValid()) {
255275
return 0;
256276
}
257277
SkSafeMath safe;

src/core/SkYUVAPixmaps.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ SkYUVAPixmapInfo::SkYUVAPixmapInfo(const SkYUVAInfo& yuvaInfo,
8080
const SkColorType colorTypes[kMaxPlanes],
8181
const size_t rowBytes[kMaxPlanes])
8282
: fYUVAInfo(yuvaInfo) {
83-
if (yuvaInfo.dimensions().isEmpty()) {
83+
if (!yuvaInfo.isValid()) {
8484
*this = {};
8585
SkASSERT(!this->isValid());
8686
return;

src/gpu/GrYUVABackendTextures.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2020 Google LLC
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 "include/gpu/GrYUVABackendTextures.h"
9+
10+
static int num_channels(const GrBackendFormat& format) {
11+
switch (format.channelMask()) {
12+
case kRed_SkColorChannelFlag : return 1;
13+
case kAlpha_SkColorChannelFlag: return 1;
14+
case kGray_SkColorChannelFlag : return 1;
15+
case kRG_SkColorChannelFlags : return 2;
16+
case kRGB_SkColorChannelFlags : return 3;
17+
case kRGBA_SkColorChannelFlags: return 4;
18+
default : return 0;
19+
}
20+
}
21+
22+
GrYUVABackendTextures::GrYUVABackendTextures(
23+
const SkYUVAInfo& yuvaInfo,
24+
const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes],
25+
GrSurfaceOrigin textureOrigin)
26+
: fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
27+
if (!fYUVAInfo.isValid()) {
28+
return;
29+
}
30+
SkISize planeDimensions[SkYUVAInfo::kMaxPlanes];
31+
int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
32+
for (int i = 0; i < numPlanes; ++i) {
33+
if (textures[i].dimensions() != planeDimensions[i]) {
34+
*this = {};
35+
return;
36+
}
37+
int numRequiredChannels = fYUVAInfo.numChannelsInPlane(i);
38+
if (!textures[i].isValid() || textures[i].backend() != textures[0].backend() ||
39+
num_channels(textures[i].getBackendFormat()) < numRequiredChannels) {
40+
*this = {};
41+
return;
42+
}
43+
fTextures[i] = textures[i];
44+
}
45+
}
46+
47+
bool GrYUVABackendTextures::toYUVAIndices(SkYUVAIndex indices[SkYUVAIndex::kIndexCount]) const {
48+
SkASSERT(indices);
49+
uint32_t channelFlags[] = {fTextures[0].getBackendFormat().channelMask(),
50+
fTextures[1].getBackendFormat().channelMask(),
51+
fTextures[2].getBackendFormat().channelMask(),
52+
fTextures[3].getBackendFormat().channelMask()};
53+
return fYUVAInfo.toYUVAIndices(channelFlags, indices);
54+
}

src/image/SkImage_GpuYUVA.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "include/core/SkYUVASizeInfo.h"
1414
#include "include/gpu/GrDirectContext.h"
1515
#include "include/gpu/GrRecordingContext.h"
16+
#include "include/gpu/GrYUVABackendTextures.h"
1617
#include "src/core/SkAutoPixmapStorage.h"
1718
#include "src/core/SkMipmap.h"
1819
#include "src/core/SkScopeExit.h"
@@ -234,6 +235,45 @@ sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newC
234235

235236
//////////////////////////////////////////////////////////////////////////////////////////////////
236237

238+
sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
239+
const GrYUVABackendTextures& yuvaTextures,
240+
sk_sp<SkColorSpace> imageColorSpace,
241+
TextureReleaseProc textureReleaseProc,
242+
ReleaseContext releaseContext) {
243+
sk_sp<GrRefCntedCallback> releaseHelper;
244+
if (textureReleaseProc) {
245+
releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
246+
}
247+
248+
SkYUVAIndex yuvaIndices[4];
249+
yuvaTextures.toYUVAIndices(yuvaIndices);
250+
int numTextures;
251+
if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
252+
return nullptr;
253+
}
254+
SkASSERT(numTextures == yuvaTextures.numPlanes());
255+
256+
GrSurfaceProxyView tempViews[4];
257+
if (!SkImage_GpuBase::MakeTempTextureProxies(context,
258+
yuvaTextures.textures().data(),
259+
numTextures,
260+
yuvaIndices,
261+
yuvaTextures.textureOrigin(),
262+
tempViews,
263+
std::move(releaseHelper))) {
264+
return nullptr;
265+
}
266+
267+
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
268+
yuvaTextures.yuvaInfo().dimensions(),
269+
kNeedNewImageUniqueID,
270+
yuvaTextures.yuvaInfo().yuvColorSpace(),
271+
tempViews,
272+
numTextures,
273+
yuvaIndices,
274+
imageColorSpace);
275+
}
276+
237277
sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
238278
SkYUVColorSpace colorSpace,
239279
const GrBackendTexture yuvaTextures[],

tools/gpu/YUVUtils.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "include/core/SkColorPriv.h"
1111
#include "include/core/SkData.h"
1212
#include "include/gpu/GrRecordingContext.h"
13+
#include "include/gpu/GrYUVABackendTextures.h"
1314
#include "src/codec/SkCodecImageGenerator.h"
1415
#include "src/core/SkYUVMath.h"
1516
#include "src/gpu/GrDirectContextPriv.h"
@@ -226,30 +227,23 @@ bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext, Type type) {
226227
if (auto direct = rContext->asDirectContext()) {
227228
sk_sp<sk_gpu_test::ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes];
228229
GrBackendTexture textures[SkYUVAInfo::kMaxPlanes];
229-
uint32_t componentFlags[SkYUVAInfo::kMaxPlanes] = {};
230230
for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
231231
mbets[i] = sk_gpu_test::ManagedBackendTexture::MakeWithData(
232232
direct, fPixmaps.plane(i), GrRenderable::kNo, GrProtected::kNo);
233233
if (mbets[i]) {
234234
textures[i] = mbets[i]->texture();
235-
componentFlags[i] = textures[i].getBackendFormat().channelMask();
236235
} else {
237236
return false;
238237
}
239238
}
240-
SkYUVAIndex indices[SkYUVAIndex::kIndexCount];
241-
if (!fPixmaps.yuvaInfo().toYUVAIndices(componentFlags, indices)) {
242-
return false;
243-
}
239+
GrYUVABackendTextures yuvaTextures(fPixmaps.yuvaInfo(),
240+
textures,
241+
kTopLeft_GrSurfaceOrigin);
244242
void* relContext =
245243
sk_gpu_test::ManagedBackendTexture::MakeYUVAReleaseContext(mbets);
246244
fYUVImage[idx] = SkImage::MakeFromYUVATextures(
247245
direct,
248-
fPixmaps.yuvaInfo().yuvColorSpace(),
249-
textures,
250-
indices,
251-
fPixmaps.yuvaInfo().dimensions(),
252-
kTopLeft_GrSurfaceOrigin,
246+
yuvaTextures,
253247
fColorSpace,
254248
sk_gpu_test::ManagedBackendTexture::ReleaseProc,
255249
relContext);

0 commit comments

Comments
 (0)