mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Impl): give the by-name texture image queries their error set
glGetTextureImage resolved a texture by name and went straight to the read, skipping every object-level rule glGetTexImage enforces through GetTexImage_State - and on DirectVulkan it skipped the level checks in CopyTextureImageToClientOrPBO_State as well, because that backend answers GetTextureImage itself. Fifteen of the sixteen conditions in direct_state_access.textures_image_query_errors went unreported. The object-level half of that error set now lives in ValidateTextureImageQuery and both entry points run it. Three rules are new rather than merely relocated: - Multisample and buffer textures are not in the accepted target list; neither has a single image to return. - The destination-size checks (bufSize, and the span written into a bound pixel pack buffer) move ahead of the read. They existed, but downstream of it, where any early bail-out - an unmapped level, a pack step that declines the format - swallowed them. Both measure the tightly packed span summed over the object's faces, which is the least a query can produce, so nothing that would have fit is rejected. - IsDepthLikeInternalFormat had no case for StencilIndex8, so a colour client format read back against a stencil-only texture looked like a matching pair. glGetCompressedTextureImage was a do-nothing stub. It validates the name and the level, then reports INVALID_OPERATION: no format MobileGL can hold is compressed, and answering GL_NO_ERROR without writing would hand the caller stale memory - the same reasoning GetCompressedTexImage_State already follows. Takes direct_state_access.textures_image_query_errors from failing to passing on both backends.
This commit is contained in:
@@ -1074,7 +1074,7 @@ DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriv, GLuint texture, GLenum pname,
|
|||||||
DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture)
|
DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BindTextureUnit, GLuint unit, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTextureUnit, unit, texture)
|
DECLARE_GL_FUNCTION_HEAD(void, BindTextureUnit, GLuint unit, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTextureUnit, unit, texture)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, GetTextureImage, GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureImage, texture, level, format, type, bufSize, pixels)
|
DECLARE_GL_FUNCTION_HEAD(void, GetTextureImage, GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureImage, texture, level, format, type, bufSize, pixels)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetCompressedTextureImage, GLuint texture, GLint level, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetCompressedTextureImage, texture, level, bufSize, pixels)
|
DECLARE_GL_FUNCTION_HEAD(void, GetCompressedTextureImage, GLuint texture, GLint level, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetCompressedTextureImage, texture, level, bufSize, pixels)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params)
|
DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameteriv, GLuint texture, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params)
|
DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameteriv, GLuint texture, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params)
|
DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params)
|
||||||
|
|||||||
@@ -3315,6 +3315,136 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add to GL_Texture.cpp
|
// Add to GL_Texture.cpp
|
||||||
|
// The half of the GetTexImage/GetTextureImage error set (GL 4.6 core 8.11) that depends on the
|
||||||
|
// resolved texture object rather than on how it was named. Shared because the by-name entry
|
||||||
|
// point does not route through GetTexImage_State and so used to enforce none of it.
|
||||||
|
Bool ValidateTextureImageQuery(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject, GLint level,
|
||||||
|
TextureInputFormat textureInputFormat, TexturePixelDataType texturePixelDataType,
|
||||||
|
GLsizei bufSize, const void* pixels, const char* caller) {
|
||||||
|
if (!TextureImpl::ValidateTextureObject(textureObject)) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller, "No valid texture bound to target"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A multisample texture has per-sample data with no single image to return, and a buffer
|
||||||
|
// texture's data lives in the buffer object - neither target is in the accepted list.
|
||||||
|
const auto target = textureObject->GetTarget();
|
||||||
|
if (target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DMultisampleArray ||
|
||||||
|
target == TextureTarget::TextureBuffer) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"Texture target has no image to read back."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level range. The by-target path would reach these again inside
|
||||||
|
// CopyTextureImageToClientOrPBO_State, but the by-name path on a backend that answers
|
||||||
|
// GetTextureImage itself never gets there.
|
||||||
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return false;
|
||||||
|
if (target == TextureTarget::TextureRectangle && level != 0) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidValue,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"Level must be zero for rectangle textures"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For a cube map this is exactly cube completeness: IsComplete() wants all six faces.
|
||||||
|
if (!textureObject->IsComplete()) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller, "Texture is incomplete"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check PBO state
|
||||||
|
const auto& pixelPackBufferObject =
|
||||||
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||||
|
|
||||||
|
if (pixelPackBufferObject) {
|
||||||
|
// Check if PBO is mapped
|
||||||
|
if (pixelPackBufferObject->IsMapped()) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller, "Pixel pack buffer is currently mapped"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check alignment
|
||||||
|
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
|
||||||
|
if (typeSize != 0 && reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"Pixel data not aligned for pixel pack buffer"));
|
||||||
|
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", caller,
|
||||||
|
"DEPTH_STENCIL readback requires a depth-stencil texture"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The destination has to be big enough. This has to happen here rather than after the read
|
||||||
|
// has been packed: any of the reasons the read can bail out early - an unmapped level, a
|
||||||
|
// pack step that declines the format - would otherwise swallow the error entirely.
|
||||||
|
if (textureObject->GetStorageType() == TextureStorageType::Mipmap) {
|
||||||
|
const auto* textureMipmapObject =
|
||||||
|
static_cast<const MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||||
|
const auto& uploadTargets = textureObject->GetUploadTargets();
|
||||||
|
if (!uploadTargets.empty() && static_cast<Uint>(level) < textureMipmapObject->GetMipmapLevelCount()) {
|
||||||
|
// Tightly packed, and summed over every face because a cube map query returns all
|
||||||
|
// six. Pack pixel-store state only ever grows this, so a request rejected here
|
||||||
|
// could not have fit under any packing.
|
||||||
|
const auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTargets[0], level);
|
||||||
|
const SizeT required = MG_Util::CalculateInputTextureImageSize(textureInputFormat,
|
||||||
|
texturePixelDataType, texelSize) *
|
||||||
|
uploadTargets.size();
|
||||||
|
|
||||||
|
if (bufSize >= 0 && static_cast<SizeT>(bufSize) < required) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller, "Destination buffer is too small."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelPackBufferObject) {
|
||||||
|
const SizeT bufferSize = pixelPackBufferObject->GetSize();
|
||||||
|
const SizeT offset = reinterpret_cast<SizeT>(pixels);
|
||||||
|
if (offset > bufferSize || required > bufferSize - offset) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"Packing would write past the end of the pixel pack buffer."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Bool GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
Bool GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
||||||
// ======================= Converting ================================
|
// ======================= Converting ================================
|
||||||
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
@@ -3363,67 +3493,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
isProxy ? TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadTarget)
|
isProxy ? TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadTarget)
|
||||||
: bindingSlot.GetBoundObject();
|
: bindingSlot.GetBoundObject();
|
||||||
|
|
||||||
if (!TextureImpl::ValidateTextureObject(textureObject)) {
|
// glGetTexImage has no bufSize argument: -1 stands for "no client-side limit".
|
||||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
|
return ValidateTextureImageQuery(textureObject, level, textureInputFormat, texturePixelDataType, -1, pixels,
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
"GetTexImage_State");
|
||||||
"No valid texture bound to target"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check texture completeness
|
|
||||||
if (!textureObject->IsComplete()) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation,
|
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check PBO state
|
|
||||||
const auto& pixelPackBufferObject =
|
|
||||||
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
|
||||||
|
|
||||||
if (pixelPackBufferObject) {
|
|
||||||
// Check if PBO is mapped
|
|
||||||
if (pixelPackBufferObject->IsMapped()) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
|
||||||
"Pixel pack buffer is currently mapped"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check alignment
|
|
||||||
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
|
|
||||||
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation,
|
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
|
||||||
"Pixel data not aligned for pixel pack buffer"));
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyTextureImageToClientOrPBO_State(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
void CopyTextureImageToClientOrPBO_State(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
||||||
@@ -4029,6 +4101,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) {
|
void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) {
|
||||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||||
if (!textureObject) return;
|
if (!textureObject) return;
|
||||||
|
if (!ValidateTextureImageQuery(textureObject, level, MG_Util::ConvertGLEnumToTextureInputFormat(format),
|
||||||
|
MG_Util::ConvertGLEnumToTexturePixelDataType(type), bufSize, pixels,
|
||||||
|
__func__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto uploadTarget = GetPrimaryUploadTarget(textureObject);
|
const auto uploadTarget = GetPrimaryUploadTarget(textureObject);
|
||||||
if (MG_Backend::pActiveBackendObject != nullptr &&
|
if (MG_Backend::pActiveBackendObject != nullptr &&
|
||||||
MG_Backend::pActiveBackendObject->GetBackendType() == BackendType::DirectVulkan &&
|
MG_Backend::pActiveBackendObject->GetBackendType() == BackendType::DirectVulkan &&
|
||||||
@@ -4041,6 +4118,22 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetCompressedTextureImage(GLuint texture, GLint level, GLsizei bufSize, void* pixels) {
|
||||||
|
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||||
|
if (!textureObject) return;
|
||||||
|
// Level first: GL 4.6 core 8.11 wants INVALID_VALUE for an out-of-range level even when the
|
||||||
|
// texture would also fail the compressed check below.
|
||||||
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
||||||
|
|
||||||
|
// No texture MobileGL holds is compressed (see IsCompressedTextureFormat), so this is the
|
||||||
|
// only outcome today. Reporting success while writing nothing would hand the caller stale
|
||||||
|
// memory with GL_NO_ERROR - the same reasoning as GetCompressedTexImage_State.
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||||
|
"Texture level is not stored in a compressed format."));
|
||||||
|
}
|
||||||
|
|
||||||
void GetTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
|
void GetTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
|
||||||
GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels) {
|
GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels) {
|
||||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
void GenerateTextureMipmap(GLuint texture);
|
void GenerateTextureMipmap(GLuint texture);
|
||||||
void BindTextureUnit(GLuint unit, GLuint texture);
|
void BindTextureUnit(GLuint unit, GLuint texture);
|
||||||
void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels);
|
void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels);
|
||||||
|
void GetCompressedTextureImage(GLuint texture, GLint level, GLsizei bufSize, void* pixels);
|
||||||
void TexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
void TexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
||||||
void TextureBuffer(GLuint texture, GLenum internalformat, GLuint buffer);
|
void TextureBuffer(GLuint texture, GLenum internalformat, GLuint buffer);
|
||||||
void TextureBufferRange(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
void TextureBufferRange(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
||||||
|
|||||||
@@ -226,6 +226,9 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
|
|||||||
case TextureInternalFormat::Depth24Stencil8:
|
case TextureInternalFormat::Depth24Stencil8:
|
||||||
case TextureInternalFormat::Depth32FStencil8:
|
case TextureInternalFormat::Depth32FStencil8:
|
||||||
case TextureInternalFormat::DepthStencil:
|
case TextureInternalFormat::DepthStencil:
|
||||||
|
// Stencil-only is not a colour format either: a colour client format read against a
|
||||||
|
// STENCIL_INDEX8 texture has to be the same INVALID_OPERATION as against a depth one.
|
||||||
|
case TextureInternalFormat::StencilIndex8:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user