mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 12:18:30 +09:00
[Fix] (MG_Impl/GLImpl, MG_State, MG_Backend/DirectGLES): eliminate packed_pixels SIGTRAPs - complete TexImage format/type/internalformat validation matrix (depth-stencil family, integer-ness, packed-type pairing, 3D depth rejection), fix inverted UpdateSubData assert with clamped copy, demote unimplemented readback asserts to logged no-ops
This commit is contained in:
@@ -3266,17 +3266,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MGLOG_D("ReadPixels: x=%d y=%d w=%d h=%d format=%s type=%s pixels=%p", x, y, width, height,
|
||||
MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
|
||||
|
||||
MOBILEGL_ASSERT(format == GL_RGBA || format == GL_RGBA_INTEGER || format == GL_RED ||
|
||||
format == GL_RED_INTEGER || format == GL_DEPTH_COMPONENT || format == GL_STENCIL_INDEX,
|
||||
"Only GL_RGBA, GL_RGBA_INTEGER, GL_RED, GL_RED_INTEGER, GL_DEPTH_COMPONENT and "
|
||||
"GL_STENCIL_INDEX are supported currently, "
|
||||
"while requested %s.",
|
||||
MG_Util::ConvertGLEnumToString(format).c_str());
|
||||
MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV ||
|
||||
type == GL_INT || type == GL_FLOAT,
|
||||
"Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, "
|
||||
"GL_INT and GL_FLOAT are supported currently, while requested %s.",
|
||||
MG_Util::ConvertGLEnumToString(type).c_str());
|
||||
// Unimplemented readback formats degrade to a logged no-op instead of killing the process;
|
||||
// spec-invalid combinations are already rejected with GL errors at the state layer.
|
||||
if (format != GL_RGBA && format != GL_RGBA_INTEGER && format != GL_RED && format != GL_RED_INTEGER &&
|
||||
format != GL_DEPTH_COMPONENT && format != GL_STENCIL_INDEX) {
|
||||
MGLOG_E("ReadPixels: format %s is not implemented yet, skipping readback",
|
||||
MG_Util::ConvertGLEnumToString(format).c_str());
|
||||
return;
|
||||
}
|
||||
if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_INT && type != GL_UNSIGNED_INT_2_10_10_10_REV &&
|
||||
type != GL_INT && type != GL_FLOAT) {
|
||||
MGLOG_E("ReadPixels: type %s is not implemented yet, skipping readback",
|
||||
MG_Util::ConvertGLEnumToString(type).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
MGLOG_D("ReadPixels: SyncNeccessaryTextures()");
|
||||
TextureImpl::SyncNeccessaryTextures();
|
||||
@@ -3362,16 +3365,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::ConvertGLEnumToString(target).c_str(), level, MG_Util::ConvertGLEnumToString(format).c_str(),
|
||||
MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
|
||||
|
||||
MOBILEGL_ASSERT(format == GL_RGBA || format == GL_RGBA_INTEGER || format == GL_BGRA,
|
||||
"Only GL_RGBA, GL_RGBA_INTEGER and GL_BGRA are supported currently, while requested %s.",
|
||||
MG_Util::ConvertGLEnumToString(format).c_str());
|
||||
MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV ||
|
||||
type == GL_INT || type == GL_FLOAT || type == GL_UNSIGNED_INT_8_8_8_8 ||
|
||||
type == GL_UNSIGNED_INT_8_8_8_8_REV || type == GL_HALF_FLOAT,
|
||||
"Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, "
|
||||
"GL_INT, GL_FLOAT, GL_HALF_FLOAT, GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_INT_8_8_8_8_REV "
|
||||
"are supported currently, while requested %s.",
|
||||
MG_Util::ConvertGLEnumToString(type).c_str());
|
||||
// Unimplemented readback formats degrade to a logged no-op instead of killing the process;
|
||||
// spec-invalid combinations are already rejected with GL errors at the state layer.
|
||||
if (format != GL_RGBA && format != GL_RGBA_INTEGER && format != GL_BGRA) {
|
||||
MGLOG_E("GetTexImage: format %s is not implemented yet, skipping readback",
|
||||
MG_Util::ConvertGLEnumToString(format).c_str());
|
||||
return;
|
||||
}
|
||||
if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_INT && type != GL_UNSIGNED_INT_2_10_10_10_REV &&
|
||||
type != GL_INT && type != GL_FLOAT && type != GL_UNSIGNED_INT_8_8_8_8 &&
|
||||
type != GL_UNSIGNED_INT_8_8_8_8_REV && type != GL_HALF_FLOAT) {
|
||||
MGLOG_E("GetTexImage: type %s is not implemented yet, skipping readback",
|
||||
MG_Util::ConvertGLEnumToString(type).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum esFormat = format, esType = type;
|
||||
if (esFormat == GL_BGRA) esFormat = GL_RGBA;
|
||||
|
||||
@@ -1357,6 +1357,18 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return;
|
||||
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadTarget, level)) return;
|
||||
|
||||
// Depth and depth-stencil formats are not three-dimensional in core GL (2D-array targets are fine).
|
||||
if ((textureUploadTarget == TextureUploadTarget::Texture3D ||
|
||||
textureUploadTarget == TextureUploadTarget::ProxyTexture3D) &&
|
||||
(textureInputFormat == TextureInputFormat::DepthComponent ||
|
||||
textureInputFormat == TextureInputFormat::DepthStencil)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"Depth formats are invalid for 3D texture targets"));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the
|
||||
// GL_PIXEL_UNPACK_BUFFER target and the buffer object's data store is currently mapped.
|
||||
// GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
|
||||
@@ -2648,17 +2660,25 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for depth/stencil
|
||||
if (textureInputFormat == TextureInputFormat::StencilIndex) {
|
||||
if (textureObject->GetFormat() != TextureInternalFormat::DepthStencil &&
|
||||
textureObject->GetFormat() != TextureInternalFormat::Depth24Stencil8 &&
|
||||
textureObject->GetFormat() != TextureInternalFormat::Depth32FStencil8) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"No stencil buffer for stencil index format"));
|
||||
return false;
|
||||
}
|
||||
// Shared format/type/internal-format matrix (packed-type pairing, depth-vs-color mismatch,
|
||||
// integer-ness). Also rejects STENCIL_INDEX readback, which needs GL_ARB_texture_stencil8
|
||||
// (not advertised by MobileGL).
|
||||
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(
|
||||
textureInputFormat, textureObject->GetFormat(), texturePixelDataType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// GetTexImage-specific: DEPTH_STENCIL readback needs a depth-stencil texture (a depth-only
|
||||
// texture has no stencil data to return).
|
||||
if (textureInputFormat == TextureInputFormat::DepthStencil &&
|
||||
textureObject->GetFormat() != TextureInternalFormat::DepthStencil &&
|
||||
textureObject->GetFormat() != TextureInternalFormat::Depth24Stencil8 &&
|
||||
textureObject->GetFormat() != TextureInternalFormat::Depth32FStencil8) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"DEPTH_STENCIL readback requires a depth-stencil texture"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -175,61 +175,132 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
|
||||
return true;
|
||||
}
|
||||
|
||||
static Bool IsIntegerColorInputFormat(TextureInputFormat format) {
|
||||
return format == TextureInputFormat::RInteger || format == TextureInputFormat::RGInteger ||
|
||||
format == TextureInputFormat::RGBInteger || format == TextureInputFormat::BGRInteger ||
|
||||
format == TextureInputFormat::RGBAInteger || format == TextureInputFormat::BGRAInteger;
|
||||
}
|
||||
|
||||
static Bool IsIntegerColorInternalFormat(TextureInternalFormat internalFormat) {
|
||||
switch (internalFormat) {
|
||||
case TextureInternalFormat::R8I:
|
||||
case TextureInternalFormat::R8UI:
|
||||
case TextureInternalFormat::R16I:
|
||||
case TextureInternalFormat::R16UI:
|
||||
case TextureInternalFormat::R32I:
|
||||
case TextureInternalFormat::R32UI:
|
||||
case TextureInternalFormat::RG8I:
|
||||
case TextureInternalFormat::RG8UI:
|
||||
case TextureInternalFormat::RG16I:
|
||||
case TextureInternalFormat::RG16UI:
|
||||
case TextureInternalFormat::RG32I:
|
||||
case TextureInternalFormat::RG32UI:
|
||||
case TextureInternalFormat::RGB8I:
|
||||
case TextureInternalFormat::RGB8UI:
|
||||
case TextureInternalFormat::RGB16I:
|
||||
case TextureInternalFormat::RGB16UI:
|
||||
case TextureInternalFormat::RGB32I:
|
||||
case TextureInternalFormat::RGB32UI:
|
||||
case TextureInternalFormat::RGBA8I:
|
||||
case TextureInternalFormat::RGBA8UI:
|
||||
case TextureInternalFormat::RGBA16I:
|
||||
case TextureInternalFormat::RGBA16UI:
|
||||
case TextureInternalFormat::RGBA32I:
|
||||
case TextureInternalFormat::RGBA32UI:
|
||||
case TextureInternalFormat::RGB10A2UI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Bool IsDepthLikeInternalFormat(TextureInternalFormat internalFormat) {
|
||||
switch (internalFormat) {
|
||||
case TextureInternalFormat::DepthComponent:
|
||||
case TextureInternalFormat::DepthComponent16:
|
||||
case TextureInternalFormat::DepthComponent24:
|
||||
case TextureInternalFormat::DepthComponent32: // not core, kept for Minecraft 1.21.5+
|
||||
case TextureInternalFormat::DepthComponent32F:
|
||||
case TextureInternalFormat::Depth24Stencil8:
|
||||
case TextureInternalFormat::Depth32FStencil8:
|
||||
case TextureInternalFormat::DepthStencil:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Bool IsDepthLikeInputFormat(TextureInputFormat format) {
|
||||
return format == TextureInputFormat::DepthComponent || format == TextureInputFormat::DepthStencil ||
|
||||
format == TextureInputFormat::StencilIndex;
|
||||
}
|
||||
|
||||
// Mirrors the desktop-GL validity matrix used by GL CTS packed_pixels (glcPackedPixelsTests
|
||||
// isFormatValid, INPUT_TEXIMAGE): packed-type/format pairing, depth-vs-color mismatch, and
|
||||
// integer-ness matching all raise GL_INVALID_OPERATION instead of reaching the upload path.
|
||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
|
||||
TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type) {
|
||||
const auto recordInvalidOperation = [](const char* message) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
message));
|
||||
return false;
|
||||
};
|
||||
|
||||
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
|
||||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
|
||||
type == TexturePixelDataType::UnsignedInt101111Rev) {
|
||||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev) {
|
||||
if (format != TextureInputFormat::RGB && format != TextureInputFormat::RGBInteger) {
|
||||
return recordInvalidOperation("Packed RGB type requires RGB or RGB_INTEGER format");
|
||||
}
|
||||
}
|
||||
|
||||
if (type == TexturePixelDataType::UnsignedInt101111Rev || type == TexturePixelDataType::UnsignedInt5999Rev) {
|
||||
if (format != TextureInputFormat::RGB) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for the given type"));
|
||||
return false;
|
||||
return recordInvalidOperation("Packed float RGB type requires RGB format");
|
||||
}
|
||||
}
|
||||
|
||||
if (type == TexturePixelDataType::UnsignedShort4444 || type == TexturePixelDataType::UnsignedShort4444Rev ||
|
||||
type == TexturePixelDataType::UnsignedShort5551 || type == TexturePixelDataType::UnsignedShort1555Rev ||
|
||||
type == TexturePixelDataType::UnsignedInt8888 || type == TexturePixelDataType::UnsignedInt8888Rev ||
|
||||
type == TexturePixelDataType::UnsignedInt1010102 || type == TexturePixelDataType::UnsignedInt2101010Rev ||
|
||||
type == TexturePixelDataType::UnsignedInt5999Rev) {
|
||||
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for the given type"));
|
||||
return false;
|
||||
type == TexturePixelDataType::UnsignedInt1010102 || type == TexturePixelDataType::UnsignedInt2101010Rev) {
|
||||
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA &&
|
||||
format != TextureInputFormat::RGBAInteger && format != TextureInputFormat::BGRAInteger) {
|
||||
return recordInvalidOperation("Packed RGBA type requires RGBA/BGRA (integer) format");
|
||||
}
|
||||
}
|
||||
|
||||
if (internalFormat == TextureInternalFormat::DepthComponent ||
|
||||
internalFormat == TextureInternalFormat::DepthComponent16 ||
|
||||
internalFormat == TextureInternalFormat::DepthComponent24 ||
|
||||
internalFormat == TextureInternalFormat::DepthComponent32F) {
|
||||
if (format != TextureInputFormat::DepthComponent) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for depth component internal format"));
|
||||
return false;
|
||||
if (type == TexturePixelDataType::UnsignedInt248 || type == TexturePixelDataType::Float32UnsignedInt248Rev) {
|
||||
if (format != TextureInputFormat::DepthStencil) {
|
||||
return recordInvalidOperation("Packed depth-stencil type requires DEPTH_STENCIL format");
|
||||
}
|
||||
}
|
||||
|
||||
if (format == TextureInputFormat::DepthComponent &&
|
||||
(internalFormat != TextureInternalFormat::DepthComponent &&
|
||||
internalFormat != TextureInternalFormat::DepthComponent16 &&
|
||||
internalFormat != TextureInternalFormat::DepthComponent24 &&
|
||||
internalFormat != TextureInternalFormat::DepthComponent32F &&
|
||||
internalFormat != TextureInternalFormat::DepthComponent32 // workaround for Minecraft 1.21.5+
|
||||
)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid internal format for depth component format"));
|
||||
return false;
|
||||
if (format == TextureInputFormat::DepthStencil && type != TexturePixelDataType::UnsignedInt248 &&
|
||||
type != TexturePixelDataType::Float32UnsignedInt248Rev) {
|
||||
return recordInvalidOperation("DEPTH_STENCIL format requires a packed depth-stencil type");
|
||||
}
|
||||
|
||||
if (IsIntegerColorInputFormat(format) &&
|
||||
(type == TexturePixelDataType::Float || type == TexturePixelDataType::HalfFloat)) {
|
||||
return recordInvalidOperation("Integer format cannot be used with a floating-point type");
|
||||
}
|
||||
|
||||
// TexImage in core 3.3 has no stencil-only upload path (that arrived with GL 4.4).
|
||||
if (format == TextureInputFormat::StencilIndex) {
|
||||
return recordInvalidOperation("STENCIL_INDEX is not a valid texture upload format");
|
||||
}
|
||||
|
||||
if (IsDepthLikeInputFormat(format) != IsDepthLikeInternalFormat(internalFormat)) {
|
||||
return recordInvalidOperation("Depth/stencil-ness of format and internal format must match");
|
||||
}
|
||||
|
||||
if (IsIntegerColorInputFormat(format) != IsIntegerColorInternalFormat(internalFormat)) {
|
||||
return recordInvalidOperation("Integer-ness of format and internal format must match");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,11 +31,12 @@ namespace MobileGL {
|
||||
auto& targetData = m_data;
|
||||
MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range");
|
||||
auto& levelData = targetData[level];
|
||||
MOBILEGL_ASSERT(levelData.size() <= input.size, "UpdateSubData: input data larger than allocated");
|
||||
MOBILEGL_ASSERT(input.size <= levelData.size(), "UpdateSubData: input data larger than allocated");
|
||||
|
||||
if (input.data && input.size > 0) {
|
||||
const Uint8* src = static_cast<const Uint8*>(input.data);
|
||||
Memcpy(levelData.data(), src, input.size);
|
||||
// Clamp so a size mismatch can never write past the allocation.
|
||||
Memcpy(levelData.data(), src, std::min(input.size, levelData.size()));
|
||||
m_isDirty[level] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +257,94 @@ TEST_F(TextureTest, BoundTexImage2DUnpacksPackedBgra8888ToRgba8WithPixelStoreSki
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// GL CTS packed_pixels feeds every format/type/internalformat combination to TexImage and expects
|
||||
// GL_INVALID_OPERATION for the invalid ones; these used to slip through validation and SIGTRAP in
|
||||
// the shadow-storage upload path.
|
||||
TEST_F(TextureTest, TexImage2DRejectsMismatchedFormatCombinations) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// Depth-stencil internal format with a color format.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_BGR, GL_UNSIGNED_BYTE, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// Color internal format with a depth format.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// Stencil-only uploads do not exist in core 3.3.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// Packed depth-stencil type with a color format.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_INT_24_8, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// DEPTH_STENCIL format requires one of the two packed depth-stencil types.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// Integer-ness of format and internal format must match (both directions).
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// Integer formats cannot be paired with floating-point types.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 2, 2, 0, GL_RGBA_INTEGER, GL_FLOAT, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// UNSIGNED_INT_5_9_9_9_REV pairs with RGB only.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGBA, GL_UNSIGNED_INT_5_9_9_9_REV, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, TexImage2DAcceptsSpecCompliantFormatCombinations) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_DEPTH_STENCIL,
|
||||
GL_UNSIGNED_INT_24_8, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// Depth-component internal format accepts DEPTH_STENCIL input (stencil bits are dropped).
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2, 2, 0, GL_DEPTH_STENCIL,
|
||||
GL_UNSIGNED_INT_24_8, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// Packed RGB types allow the integer variant of the RGB format.
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 2, 2, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE_3_3_2,
|
||||
nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, TexImage3DRejectsDepthFormatsForThreeDimensionalTarget) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_3D, texture);
|
||||
MG_Impl::GLImpl::TexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH24_STENCIL8, 2, 2, 2, 0, GL_DEPTH_STENCIL,
|
||||
GL_UNSIGNED_INT_24_8, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_OPERATION);
|
||||
|
||||
// 2D-array targets remain valid for depth formats.
|
||||
GLuint arrayTexture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &arrayTexture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
|
||||
MG_Impl::GLImpl::TexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, 2, 2, 2, 0, GL_DEPTH_STENCIL,
|
||||
GL_UNSIGNED_INT_24_8, nullptr);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, BoundTexSubImage2DUnpacksPackedBgra8888RevToRgba8) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
|
||||
Reference in New Issue
Block a user