Revert "Revert "New variant of SkImage::MakeFromYUVATextures.""

This reverts commit be8004d2fb.

Bug: skia:10632
Change-Id: I52dd36ae167623563c7554c40092442a3822ee3c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/327760
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-10-19 10:55:45 -04:00 committed by Skia Commit-Bot
parent bcd1fc030a
commit c1a249d1dc
10 changed files with 224 additions and 15 deletions

View File

@ -9,6 +9,11 @@ Milestone 88
* <insert new release notes here>
* New variant of SkImage::MakeFromYUVATextures. Takes a new type GrYUVATextures
which wraps an SkYUVAInfo and compatible set of GrBackendTextures. The provides
a more complete and structured specification of the planar configuration. Previous
version is deprecated.
* Add field to GrContextOptions to disable mipmap support even if the backend
supports it.

View File

@ -19,6 +19,7 @@ skia_gpu_sources = [
"$_include/gpu/GrDriverBugWorkarounds.h",
"$_include/gpu/GrRecordingContext.h",
"$_include/gpu/GrTypes.h",
"$_include/gpu/GrYUVABackendTextures.h",
# Private includes
"$_include/private/GrContext.h",
@ -269,6 +270,7 @@ skia_gpu_sources = [
"$_src/gpu/GrWindowRectsState.h",
"$_src/gpu/GrXferProcessor.cpp",
"$_src/gpu/GrXferProcessor.h",
"$_src/gpu/GrYUVABackendTextures.cpp",
# Ops
"$_src/gpu/effects/GrBezierEffect.cpp",

View File

@ -38,6 +38,7 @@ class GrContext;
class GrDirectContext;
class GrRecordingContext;
class GrContextThreadSafeProxy;
class GrYUVABackendTextures;
struct SkYUVAIndex;
@ -408,7 +409,30 @@ public:
SkAlphaType alphaType = kPremul_SkAlphaType,
sk_sp<SkColorSpace> colorSpace = nullptr);
/** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
/** Creates an SkImage from YUV[A] planar textures. This requires that the textures stay valid
for the lifetime of the image. The ReleaseContext can be used to know when it is safe to
either delete or overwrite the textures. If ReleaseProc is provided it is also called before
return on failure.
@param context GPU context
@param yuvaTextures A set of textures containing YUVA data and a description of the
data and transformation to RGBA.
@param imageColorSpace range of colors of the resulting image after conversion to RGB;
may be nullptr
@param textureReleaseProc called when the backend textures can be released
@param releaseContext state passed to textureReleaseProc
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromYUVATextures(GrRecordingContext* context,
const GrYUVABackendTextures& yuvaTextures,
sk_sp<SkColorSpace> imageColorSpace = nullptr,
TextureReleaseProc textureReleaseProc = nullptr,
ReleaseContext releaseContext = nullptr);
/**
Deprecated. Use version that takes GrYUVABackendTextures.
Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
via multitexturing.
When all the provided backend textures can be released 'textureReleaseProc' will be called

View File

@ -39,6 +39,8 @@ public:
* this expands.
*/
enum class PlanarConfig {
kUnknown,
kY_U_V_444, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_422, ///< Plane 0: Y, Plane 1: U, Plane 2: V
kY_U_V_420, ///< Plane 0: Y, Plane 1: U, Plane 2: V
@ -177,10 +179,12 @@ public:
bool operator==(const SkYUVAInfo& that) const;
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
bool isValid() const { return fPlanarConfig != PlanarConfig::kUnknown; }
private:
SkISize fDimensions = {0, 0};
PlanarConfig fPlanarConfig = PlanarConfig::kY_U_V_444;
PlanarConfig fPlanarConfig = PlanarConfig::kUnknown;
SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
@ -196,6 +200,8 @@ private:
constexpr int SkYUVAInfo::NumPlanes(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kUnknown: return 0;
case PlanarConfig::kY_U_V_444: return 3;
case PlanarConfig::kY_U_V_422: return 3;
case PlanarConfig::kY_U_V_420: return 3;
@ -223,6 +229,9 @@ constexpr int SkYUVAInfo::NumPlanes(PlanarConfig planarConfig) {
constexpr int SkYUVAInfo::NumChannelsInPlane(PlanarConfig config, int i) {
switch (config) {
case PlanarConfig::kUnknown:
return 0;
case SkYUVAInfo::PlanarConfig::kY_U_V_444:
case SkYUVAInfo::PlanarConfig::kY_U_V_422:
case SkYUVAInfo::PlanarConfig::kY_U_V_420:

View File

@ -0,0 +1,60 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrYUVABackendTextures_DEFINED
#define GrYUVABackendTextures_DEFINED
#include "include/core/SkYUVAInfo.h"
#include "include/gpu/GrBackendSurface.h"
#include <tuple>
struct SkYUVASizeInfo;
struct SkYUVAIndex;
/**
* A set of GrBackendTextures that hold the planar data for a SkYUVAInfo.
*/
class SK_API GrYUVABackendTextures {
public:
GrYUVABackendTextures() = default;
GrYUVABackendTextures(const GrYUVABackendTextures&) = delete;
GrYUVABackendTextures(GrYUVABackendTextures&&) = default;
GrYUVABackendTextures& operator=(const GrYUVABackendTextures&) = delete;
GrYUVABackendTextures& operator=(GrYUVABackendTextures&&) = default;
GrYUVABackendTextures(const SkYUVAInfo&,
const GrBackendTexture[SkYUVAInfo::kMaxPlanes],
GrSurfaceOrigin textureOrigin);
const std::array<GrBackendTexture, SkYUVAInfo::kMaxPlanes>& textures() const {
return fTextures;
}
GrBackendTexture texture(int i) const {
SkASSERT(i >= 0 && i < SkYUVAInfo::kMaxPlanes);
return fTextures[static_cast<size_t>(i)];
}
const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
int numPlanes() const { return fYUVAInfo.numPlanes(); }
GrSurfaceOrigin textureOrigin() const { return fTextureOrigin; }
bool isValid() const { return fYUVAInfo.isValid(); }
bool toYUVAIndices(SkYUVAIndex[SkYUVAIndex::kIndexCount]) const;
private:
SkYUVAInfo fYUVAInfo;
std::array<GrBackendTexture, SkYUVAInfo::kMaxPlanes> fTextures;
GrSurfaceOrigin fTextureOrigin = kTopLeft_GrSurfaceOrigin;
};
#endif

View File

@ -11,7 +11,7 @@
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
PlanarConfig planarConfig,
SkEncodedOrigin origin,
SkISize* planeDimensions) {
SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]) {
int w = imageDimensions.width();
int h = imageDimensions.height();
if (origin >= kLeftTop_SkEncodedOrigin) {
@ -21,6 +21,12 @@ int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
auto down2 = [](int x) { return (x + 1)/2; };
auto down4 = [](int x) { return (x + 3)/4; };
switch (planarConfig) {
case PlanarConfig::kUnknown:
planeDimensions[0] =
planeDimensions[1] =
planeDimensions[2] =
planeDimensions[3] = {0, 0};
return 0;
case PlanarConfig::kY_U_V_444:
planeDimensions[0] = planeDimensions[1] = planeDimensions[2] = {w, h};
planeDimensions[3] = {0, 0};
@ -125,6 +131,9 @@ bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
struct Location {int plane, chanIdx;};
const Location* locations = nullptr;
switch (config) {
case PlanarConfig::kUnknown:
return false;
case PlanarConfig::kY_U_V_444:
case PlanarConfig::kY_U_V_422:
case PlanarConfig::kY_U_V_420:
@ -210,6 +219,8 @@ bool SkYUVAInfo::GetYUVAIndices(PlanarConfig config,
bool SkYUVAInfo::HasAlpha(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kUnknown: return false;
case PlanarConfig::kY_U_V_444: return false;
case PlanarConfig::kY_U_V_422: return false;
case PlanarConfig::kY_U_V_420: return false;
@ -247,11 +258,20 @@ SkYUVAInfo::SkYUVAInfo(SkISize dimensions,
, fYUVColorSpace(yuvColorSpace)
, fOrigin(origin)
, fSitingX(sitingX)
, fSitingY(sitingY) {}
, fSitingY(sitingY) {
if (fDimensions.width() <= 0 ||
fDimensions.height() <= 0 ||
planarConfig == PlanarConfig::kUnknown) {
*this = {};
SkASSERT(!this->isValid());
return;
}
SkASSERT(this->isValid());
}
size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
size_t planeSizes[kMaxPlanes]) const {
if (fDimensions.isEmpty()) {
if (!this->isValid()) {
return 0;
}
SkSafeMath safe;

View File

@ -80,7 +80,7 @@ SkYUVAPixmapInfo::SkYUVAPixmapInfo(const SkYUVAInfo& yuvaInfo,
const SkColorType colorTypes[kMaxPlanes],
const size_t rowBytes[kMaxPlanes])
: fYUVAInfo(yuvaInfo) {
if (yuvaInfo.dimensions().isEmpty()) {
if (!yuvaInfo.isValid()) {
*this = {};
SkASSERT(!this->isValid());
return;

View File

@ -0,0 +1,52 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/GrYUVABackendTextures.h"
static int num_channels(const GrBackendFormat& format) {
switch (format.channelMask()) {
case kRed_SkColorChannelFlag : return 1;
case kAlpha_SkColorChannelFlag: return 1;
case kGray_SkColorChannelFlag : return 1;
case kRG_SkColorChannelFlags : return 2;
case kRGB_SkColorChannelFlags : return 3;
case kRGBA_SkColorChannelFlags: return 4;
default : return 0;
}
}
GrYUVABackendTextures::GrYUVABackendTextures(
const SkYUVAInfo& yuvaInfo,
const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes],
GrSurfaceOrigin textureOrigin)
: fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
if (!fYUVAInfo.isValid()) {
return;
}
SkISize planeDimensions[SkYUVAInfo::kMaxPlanes];
int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
for (int i = 0; i < numPlanes; ++i) {
int numRequiredChannels = fYUVAInfo.numChannelsInPlane(i);
if (!textures[i].isValid() ||
textures[i].dimensions() != planeDimensions[i] ||
textures[i].backend() != textures[0].backend() ||
num_channels(textures[i].getBackendFormat()) < numRequiredChannels) {
*this = {};
return;
}
fTextures[i] = textures[i];
}
}
bool GrYUVABackendTextures::toYUVAIndices(SkYUVAIndex indices[SkYUVAIndex::kIndexCount]) const {
SkASSERT(indices);
uint32_t channelFlags[] = {fTextures[0].getBackendFormat().channelMask(),
fTextures[1].getBackendFormat().channelMask(),
fTextures[2].getBackendFormat().channelMask(),
fTextures[3].getBackendFormat().channelMask()};
return fYUVAInfo.toYUVAIndices(channelFlags, indices);
}

View File

@ -13,6 +13,7 @@
#include "include/core/SkYUVASizeInfo.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/GrYUVABackendTextures.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkMipmap.h"
#include "src/core/SkScopeExit.h"
@ -234,6 +235,45 @@ sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newC
//////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
const GrYUVABackendTextures& yuvaTextures,
sk_sp<SkColorSpace> imageColorSpace,
TextureReleaseProc textureReleaseProc,
ReleaseContext releaseContext) {
sk_sp<GrRefCntedCallback> releaseHelper;
if (textureReleaseProc) {
releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
}
SkYUVAIndex yuvaIndices[4];
int numTextures;
if (!yuvaTextures.toYUVAIndices(yuvaIndices) ||
!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
return nullptr;
}
SkASSERT(numTextures == yuvaTextures.numPlanes());
GrSurfaceProxyView tempViews[4];
if (!SkImage_GpuBase::MakeTempTextureProxies(context,
yuvaTextures.textures().data(),
numTextures,
yuvaIndices,
yuvaTextures.textureOrigin(),
tempViews,
std::move(releaseHelper))) {
return nullptr;
}
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
yuvaTextures.yuvaInfo().dimensions(),
kNeedNewImageUniqueID,
yuvaTextures.yuvaInfo().yuvColorSpace(),
tempViews,
numTextures,
yuvaIndices,
imageColorSpace);
}
sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],

View File

@ -10,6 +10,7 @@
#include "include/core/SkColorPriv.h"
#include "include/core/SkData.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/GrYUVABackendTextures.h"
#include "src/codec/SkCodecImageGenerator.h"
#include "src/core/SkYUVMath.h"
#include "src/gpu/GrDirectContextPriv.h"
@ -226,30 +227,26 @@ bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext, Type type) {
if (auto direct = rContext->asDirectContext()) {
sk_sp<sk_gpu_test::ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes];
GrBackendTexture textures[SkYUVAInfo::kMaxPlanes];
uint32_t componentFlags[SkYUVAInfo::kMaxPlanes] = {};
for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
mbets[i] = sk_gpu_test::ManagedBackendTexture::MakeWithData(
direct, fPixmaps.plane(i), GrRenderable::kNo, GrProtected::kNo);
if (mbets[i]) {
textures[i] = mbets[i]->texture();
componentFlags[i] = textures[i].getBackendFormat().channelMask();
} else {
return false;
}
}
SkYUVAIndex indices[SkYUVAIndex::kIndexCount];
if (!fPixmaps.yuvaInfo().toYUVAIndices(componentFlags, indices)) {
GrYUVABackendTextures yuvaTextures(fPixmaps.yuvaInfo(),
textures,
kTopLeft_GrSurfaceOrigin);
if (!yuvaTextures.isValid()) {
return false;
}
void* relContext =
sk_gpu_test::ManagedBackendTexture::MakeYUVAReleaseContext(mbets);
fYUVImage[idx] = SkImage::MakeFromYUVATextures(
direct,
fPixmaps.yuvaInfo().yuvColorSpace(),
textures,
indices,
fPixmaps.yuvaInfo().dimensions(),
kTopLeft_GrSurfaceOrigin,
yuvaTextures,
fColorSpace,
sk_gpu_test::ManagedBackendTexture::ReleaseProc,
relContext);