diff options
-rw-r--r-- | docs/SkImageInfo_Reference.bmh | 16 | ||||
-rw-r--r-- | include/core/SkImageInfo.h | 36 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 104 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.h | 11 |
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; |