Add usage of SkYUVAIndex as pre-step to transfer to new YUVA API

The plan foward is to have a new API on SkImage to make from YUVA
textures which a combination of array of textures and array of
SkYUVAIndex struct indicating which texture and channel to read for
each plane. This is a pre-step to let the old API use these ideas.

Bug: skia: 7903
Change-Id: I6a696db31a574247eb2abff60f2186a74b640142
Reviewed-on: https://skia-review.googlesource.com/128601
Commit-Queue: Weiliang Chen <weiliangc@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Weiliang Chen 2018-05-22 18:44:02 -04:00 committed by Skia Commit-Bot
parent 4fa5824fa2
commit bed9d5ec3e
4 changed files with 136 additions and 33 deletions

View File

@ -1037,6 +1037,22 @@ with studio range of 16 to 235 range for components.
# ------------------------------------------------------------------------------
#Struct SkYUVAIndex
Describes which image source and which channel to read for each YUVA planes.
#Member int fIndex
Describes which image source to be reading from. The Alpha plane is optional and could be set to -1.
##
#Member SkImageSourceChannel fChannel
Describes which of the RGBA channel to read from.
##
#Struct SkYUVAIndex ##
# ------------------------------------------------------------------------------
#Struct SkImageInfo
Describes pixel dimensions and encoding. Bitmap, Image, PixMap, and Surface

View File

@ -219,6 +219,42 @@ enum SkYUVColorSpace {
kLastEnum_SkYUVColorSpace = kRec709_SkYUVColorSpace,
};
/** \enum SkImageInfo::SkImageSourceChannel
Describes different channels we could read from image source.
*/
enum SkImageSourceChannel {
/** Describes the red channel; */
kR_SkImageSourceChannel,
/** Describes the green channel; */
kG_SkImageSourceChannel,
/** Describes the blue channel; */
kB_SkImageSourceChannel,
/** Describes the alpha channel; */
kA_SkImageSourceChannel,
/** Describes the alpha channel; */
kLastEnum_SkImageSourceChannel = kA_SkImageSourceChannel,
};
/** \struct SkYUVAIndex
Describes from which image source and which channel to read each individual YUVA plane.
SkYUVAIndex contains a index for which image source to read from and a enum for which channel
to read from.
*/
struct SK_API SkYUVAIndex {
/** The index is a number between -1..3 which definies which image source to read from, where -1
* means the image source doesn't exist. The assumption is we will always have image sources for
* each of YUV planes, but optionally have image source for A plane. */
int fIndex;
/** The channel describes from which channel to read the info from. Currently we only deal with
* YUV and NV12 and channel info is ignored. */
SkImageSourceChannel fChannel;
};
/** \struct SkImageInfo
Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface
can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and

View File

@ -368,39 +368,70 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
kAdopt_GrWrapOwnership, nullptr, nullptr);
}
sk_sp<SkImage> SkImage_Gpu::MakeFromYUVTexturesCopyImpl(
GrContext* ctx, SkYUVColorSpace colorSpace, bool nv12,
const GrBackendTexture yuvBackendTexturesOrig[], GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4],
SkISize size,
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
GrBackendTexture yuvBackendTextures[]{
yuvBackendTexturesOrig[0],
yuvBackendTexturesOrig[1],
yuvBackendTexturesOrig[2],
};
// Right now this still only deals with YUV and NV12 formats. Assuming that YUV has different
// textures for U and V planes, while NV12 uses same texture for U and V planes.
bool nv12 = (yuvaIndices[1].fIndex == yuvaIndices[2].fIndex);
auto ct = nv12 ? kRGBA_8888_SkColorType : kAlpha_8_SkColorType;
for (int i = 0; i < (nv12 ? 2 : 3); ++i) {
if (!validate_backend_texture(ctx, yuvBackendTextures[i], &yuvBackendTextures[i].fConfig,
ct, kPremul_SkAlphaType, nullptr)) {
for (int i = 0; i < 4; ++i) {
// Validate that the yuvaIndices refer to valid backend textures.
SkYUVAIndex& yuvaIndex = yuvaIndices[i];
if (i == 3 && yuvaIndex.fIndex == -1) {
// Meaning the A plane isn't passed in.
continue;
}
if (yuvaIndex.fIndex == -1 || yuvaIndex.fIndex > 3) {
// Y plane, U plane, and V plane must refer to image sources being passed in. There are
// at most 4 images sources being passed in, could not have a index more than 3.
return nullptr;
}
auto texture = yuvaTextures[yuvaIndex.fIndex];
// TODO: Instead of using assumption about whether it is NV12 format to guess colorType,
// actually use channel information here.
if (!validate_backend_texture(ctx, texture, &texture.fConfig, ct, kPremul_SkAlphaType,
nullptr)) {
return nullptr;
}
}
sk_sp<GrTextureProxy> yProxy = proxyProvider->wrapBackendTexture(yuvBackendTextures[0], origin);
sk_sp<GrTextureProxy> uProxy = proxyProvider->wrapBackendTexture(yuvBackendTextures[1], origin);
sk_sp<GrTextureProxy> vProxy;
if (nv12) {
vProxy = uProxy;
} else {
vProxy = proxyProvider->wrapBackendTexture(yuvBackendTextures[2], origin);
// TODO: Check that for each plane, the channel actually exist in the image source we are
// reading from.
}
sk_sp<GrTextureProxy> tempTextureProxies[4];
for (int i = 0; i < 4; ++i) {
// Fill in tempTextureProxies to avoid duplicate texture proxies.
int textureIndex = yuvaIndices[i].fIndex;
// Safely ignore since this means we are missing the A plane.
if (textureIndex == -1) {
SkASSERT(3 == i);
continue;
}
if (!tempTextureProxies[textureIndex]) {
tempTextureProxies[textureIndex] =
proxyProvider->wrapBackendTexture(yuvaTextures[textureIndex], origin);
}
}
sk_sp<GrTextureProxy> yProxy = tempTextureProxies[yuvaIndices[0].fIndex];
sk_sp<GrTextureProxy> uProxy = tempTextureProxies[yuvaIndices[1].fIndex];
sk_sp<GrTextureProxy> vProxy = tempTextureProxies[yuvaIndices[2].fIndex];
if (!yProxy || !uProxy || !vProxy) {
return nullptr;
}
const int width = yuvBackendTextures[0].width();
const int height = yuvBackendTextures[0].height();
const int width = size.width();
const int height = size.height();
// Needs to be a render target in order to draw to it for the yuv->rgb conversion.
sk_sp<GrRenderTargetContext> renderTargetContext(
@ -413,9 +444,12 @@ sk_sp<SkImage> SkImage_Gpu::MakeFromYUVTexturesCopyImpl(
GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
SkISize sizes[] = {{yuvBackendTextures[0].width(), yuvBackendTextures[0].height()},
{yuvBackendTextures[1].width(), yuvBackendTextures[1].height()},
{yuvBackendTextures[2].width(), yuvBackendTextures[2].height()}};
// TODO: Move the sizes into GrYUVtoRGBEffect since this can just be done there.
SkISize sizes[] = {{yProxy->width(), yProxy->height()},
{uProxy->width(), uProxy->height()},
{vProxy->width(), vProxy->height()}};
// TODO: Modify the fragment processor to sample from different channel instead of taking nv12
// bool.
paint.addColorFragmentProcessor(
GrYUVtoRGBEffect::Make(yProxy, uProxy, vProxy, sizes, colorSpace, nv12));
@ -439,16 +473,30 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace
const GrBackendTexture yuvTextures[3],
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
return SkImage_Gpu::MakeFromYUVTexturesCopyImpl(ctx, colorSpace, false, yuvTextures,
origin, std::move(imageColorSpace));
// TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
SkYUVAIndex yuvaIndices[4] = {
SkYUVAIndex{0, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{2, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{-1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel}};
SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
return SkImage_Gpu::MakeFromYUVATexturesCopyImpl(ctx, colorSpace, yuvTextures, yuvaIndices,
size, origin, std::move(imageColorSpace));
}
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
const GrBackendTexture nv12Textures[2],
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
return SkImage_Gpu::MakeFromYUVTexturesCopyImpl(ctx, colorSpace, true, nv12Textures,
origin, std::move(imageColorSpace));
// TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
SkYUVAIndex yuvaIndices[4] = {
SkYUVAIndex{0, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{-1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel}};
SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
return SkImage_Gpu::MakeFromYUVATexturesCopyImpl(ctx, colorSpace, nv12Textures, yuvaIndices,
size, origin, std::move(imageColorSpace));
}
static sk_sp<SkImage> create_image_from_maker(GrContext* context, GrTextureMaker* maker,

View File

@ -125,10 +125,13 @@ public:
TextureContext textureContext);
/** Implementation of MakeFromYUVTexturesCopy and MakeFromNV12TexturesCopy */
static sk_sp<SkImage> MakeFromYUVTexturesCopyImpl(
GrContext* ctx, SkYUVColorSpace colorSpace, bool nv12,
const GrBackendTexture yuvBackendTextures[], GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace);
static sk_sp<SkImage> MakeFromYUVATexturesCopyImpl(GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4],
SkISize size,
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace);
bool onIsValid(GrContext*) const override;