зеркало из https://github.com/AvaloniaUI/angle.git
Add YUV format utils and validation code
1. Add YuvFormatInfo struct and a few YUV format helpers 2. Update ES3 validation code to account for YUV formats Bug: angleproject:5773 Change-Id: I82ababe8bf2a065e7d5c4f868e4a512ba8c9d7d2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2947766 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Родитель
4264138a69
Коммит
669acb00b2
|
@ -597,6 +597,152 @@ void InsertFormatInfo(InternalFormatInfoMap *map, const InternalFormat &formatIn
|
|||
(*map)[formatInfo.internalFormat][formatInfo.type] = formatInfo;
|
||||
}
|
||||
|
||||
// YuvFormatInfo implementation
|
||||
YuvFormatInfo::YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent)
|
||||
{
|
||||
ASSERT(gl::IsYuvFormat(internalFormat));
|
||||
ASSERT((gl::GetPlaneCount(internalFormat) > 0) && (gl::GetPlaneCount(internalFormat) <= 3));
|
||||
|
||||
glInternalFormat = internalFormat;
|
||||
planeCount = gl::GetPlaneCount(internalFormat);
|
||||
|
||||
// Chroma planes of a YUV format can be subsampled
|
||||
int horizontalSubsampleFactor = 0;
|
||||
int verticalSubsampleFactor = 0;
|
||||
gl::GetSubSampleFactor(internalFormat, &horizontalSubsampleFactor, &verticalSubsampleFactor);
|
||||
|
||||
// Compute plane Bpp
|
||||
planeBpp[0] = gl::GetYPlaneBpp(internalFormat);
|
||||
planeBpp[1] = gl::GetChromaPlaneBpp(internalFormat);
|
||||
planeBpp[2] = (planeCount > 2) ? planeBpp[1] : 0;
|
||||
|
||||
// Compute plane extent
|
||||
planeExtent[0] = yPlaneExtent;
|
||||
planeExtent[1] = {(yPlaneExtent.width / horizontalSubsampleFactor),
|
||||
(yPlaneExtent.height / verticalSubsampleFactor), yPlaneExtent.depth};
|
||||
planeExtent[2] = (planeCount > 2) ? planeExtent[1] : Extents();
|
||||
|
||||
// Compute plane pitch
|
||||
planePitch[0] = planeExtent[0].width * planeBpp[0];
|
||||
planePitch[1] = planeExtent[1].width * planeBpp[1];
|
||||
planePitch[2] = planeExtent[2].width * planeBpp[2];
|
||||
|
||||
// Compute plane size
|
||||
planeSize[0] = planePitch[0] * planeExtent[0].height;
|
||||
planeSize[1] = planePitch[1] * planeExtent[1].height;
|
||||
planeSize[2] = planePitch[2] * planeExtent[2].height;
|
||||
|
||||
// Compute plane offset
|
||||
planeOffset[0] = 0;
|
||||
planeOffset[1] = planeSize[0];
|
||||
planeOffset[2] = planeSize[0] + planeSize[1];
|
||||
}
|
||||
|
||||
// YUV format related helpers
|
||||
bool IsYuvFormat(GLenum format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
|
||||
case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetPlaneCount(GLenum format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
|
||||
return 2;
|
||||
case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
|
||||
case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
|
||||
return 3;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetYPlaneBpp(GLenum format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
|
||||
return 1;
|
||||
case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
|
||||
return 2;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetChromaPlaneBpp(GLenum format)
|
||||
{
|
||||
// 2 plane 420 YUV formats have CbCr channels interleaved.
|
||||
// 3 plane 420 YUV formats have separate Cb and Cr planes.
|
||||
switch (format)
|
||||
{
|
||||
case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
|
||||
return 1;
|
||||
case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
|
||||
return 2;
|
||||
case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
|
||||
return 4;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GetSubSampleFactor(GLenum format, int *horizontalSubsampleFactor, int *verticalSubsampleFactor)
|
||||
{
|
||||
ASSERT(horizontalSubsampleFactor && verticalSubsampleFactor);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
|
||||
case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
|
||||
case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
|
||||
case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
|
||||
*horizontalSubsampleFactor = 2;
|
||||
*verticalSubsampleFactor = 2;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AddRGBAFormat(InternalFormatInfoMap *map,
|
||||
GLenum internalFormat,
|
||||
bool sized,
|
||||
|
|
|
@ -486,6 +486,32 @@ ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, Ver
|
|||
return ComponentType::Float;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr std::size_t kMaxYuvPlaneCount = 3;
|
||||
template <typename T>
|
||||
using YuvPlaneArray = std::array<T, kMaxYuvPlaneCount>;
|
||||
|
||||
struct YuvFormatInfo
|
||||
{
|
||||
// Sized types only.
|
||||
YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent);
|
||||
|
||||
GLenum glInternalFormat;
|
||||
uint32_t planeCount;
|
||||
YuvPlaneArray<uint32_t> planeBpp;
|
||||
YuvPlaneArray<Extents> planeExtent;
|
||||
YuvPlaneArray<uint32_t> planePitch;
|
||||
YuvPlaneArray<uint32_t> planeSize;
|
||||
YuvPlaneArray<uint32_t> planeOffset;
|
||||
};
|
||||
|
||||
bool IsYuvFormat(GLenum format);
|
||||
uint32_t GetPlaneCount(GLenum format);
|
||||
uint32_t GetYPlaneBpp(GLenum format);
|
||||
uint32_t GetChromaPlaneBpp(GLenum format);
|
||||
void GetSubSampleFactor(GLenum format,
|
||||
int *horizontalSubsampleFactor,
|
||||
int *verticalSubsampleFactor);
|
||||
} // namespace gl
|
||||
|
||||
#endif // LIBANGLE_FORMATUTILS_H_
|
||||
|
|
|
@ -285,11 +285,23 @@ static bool ValidateTexImageFormatCombination(const Context *context,
|
|||
}
|
||||
else
|
||||
{
|
||||
// The type and format are valid if any supported internal format has that type and format
|
||||
if (!ValidES3Format(format))
|
||||
// The type and format are valid if any supported internal format has that type and format.
|
||||
// ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
|
||||
if (gl::IsYuvFormat(format))
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
|
||||
return false;
|
||||
if (!context->getExtensions().yuvInternalFormatANGLE)
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ValidES3Format(format))
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ValidES3Type(type))
|
||||
|
@ -332,10 +344,22 @@ static bool ValidateTexImageFormatCombination(const Context *context,
|
|||
else
|
||||
{
|
||||
// Check if this is a valid format combination to load texture data
|
||||
if (!ValidES3FormatCombination(format, type, internalFormat))
|
||||
// ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
|
||||
if (gl::IsYuvFormat(format))
|
||||
{
|
||||
context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
|
||||
return false;
|
||||
if (type != GL_UNSIGNED_BYTE)
|
||||
{
|
||||
context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ValidES3FormatCombination(format, type, internalFormat))
|
||||
{
|
||||
context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,6 +426,29 @@ bool ValidateES3TexImageParametersBase(const Context *context,
|
|||
{
|
||||
TextureType texType = TextureTargetToType(target);
|
||||
|
||||
if (gl::IsYuvFormat(format))
|
||||
{
|
||||
// According to ANGLE_yuv_internal_format, the texture needs to be an immutable
|
||||
// texture, texture target can only be TEXTURE_2D and there is no mipmap support
|
||||
if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target != TextureTarget::_2D)
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level != 0)
|
||||
{
|
||||
context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate image size
|
||||
if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
|
||||
{
|
||||
|
@ -1211,6 +1258,29 @@ bool ValidateES3TexStorageParametersBase(const Context *context,
|
|||
return false;
|
||||
}
|
||||
|
||||
// From ANGLE_texture_external_yuv_sampling:
|
||||
// Texture target can only be TEXTURE_2D, there is no mipmap support
|
||||
if (gl::IsYuvFormat(internalformat))
|
||||
{
|
||||
if (!context->getExtensions().yuvInternalFormatANGLE)
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target != TextureType::_2D)
|
||||
{
|
||||
context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (levels != 1)
|
||||
{
|
||||
context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const Caps &caps = context->getCaps();
|
||||
|
||||
switch (target)
|
||||
|
|
Загрузка…
Ссылка в новой задаче