aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/SkImageInfo_Reference.bmh16
-rw-r--r--include/core/SkImageInfo.h36
-rw-r--r--src/image/SkImage_Gpu.cpp104
-rw-r--r--src/image/SkImage_Gpu.h11
4 files changed, 135 insertions, 32 deletions
diff --git a/docs/SkImageInfo_Reference.bmh b/docs/SkImageInfo_Reference.bmh
index c477d4f752..c877f7ff30 100644
--- a/docs/SkImageInfo_Reference.bmh
+++ b/docs/SkImageInfo_Reference.bmh
@@ -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
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index eb96f19723..cb0e6dbbee 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -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
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 40e055e520..d3500e4f4e 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -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;
}
+
+ // TODO: Check that for each plane, the channel actually exist in the image source we are
+ // reading from.
}
- 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);
+ 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,
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index cb9a7c7a9f..b0c2785ece 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -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;