mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (MG_State/GLState, MG_Impl/GLImpl): track immutable texture storage [skip ci]
This commit is contained in:
@@ -99,6 +99,44 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
MG_Util::ConvertGLEnumToTexturePixelDataType(realType));
|
MG_Util::ConvertGLEnumToTexturePixelDataType(realType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool IsSizedTextureStorageInternalFormat(TextureInternalFormat textureInternalFormat) {
|
||||||
|
switch (textureInternalFormat) {
|
||||||
|
case TextureInternalFormat::Red:
|
||||||
|
case TextureInternalFormat::RG:
|
||||||
|
case TextureInternalFormat::RGB:
|
||||||
|
case TextureInternalFormat::RGBA:
|
||||||
|
case TextureInternalFormat::DepthComponent:
|
||||||
|
case TextureInternalFormat::DepthStencil:
|
||||||
|
case TextureInternalFormat::Unknown:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool ValidateTextureStorageInternalFormat(TextureInternalFormat textureInternalFormat, const char* caller) {
|
||||||
|
// TODO: Replace this sized-format filter with the full ARB_texture_storage legal-format table.
|
||||||
|
if (!IsSizedTextureStorageInternalFormat(textureInternalFormat)) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidEnum,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"TexStorage requires a sized internal format."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return TextureImpl::ValidateTextureInternalFormat(textureInternalFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool ValidateTextureMutable(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
||||||
|
const char* caller) {
|
||||||
|
if (!textureObject || !textureObject->IsImmutable()) return true;
|
||||||
|
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||||
|
"Immutable texture storage cannot be redefined."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
GLint GetTextureComponentType(TextureInternalFormat textureInternalFormat, GLint size, Bool depthComponent,
|
GLint GetTextureComponentType(TextureInternalFormat textureInternalFormat, GLint size, Bool depthComponent,
|
||||||
Bool stencilComponent) {
|
Bool stencilComponent) {
|
||||||
if (size <= 0) return GL_NONE;
|
if (size <= 0) return GL_NONE;
|
||||||
@@ -529,6 +567,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
case GL_TEXTURE_MAX_LEVEL:
|
case GL_TEXTURE_MAX_LEVEL:
|
||||||
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
|
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
|
||||||
break;
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||||
|
*params = textureObject->IsImmutable() ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||||
|
*params = static_cast<GLint>(textureObject->GetImmutableLevels());
|
||||||
|
break;
|
||||||
case GL_TEXTURE_WRAP_S:
|
case GL_TEXTURE_WRAP_S:
|
||||||
*params = (GLint)MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
|
*params = (GLint)MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
|
||||||
break;
|
break;
|
||||||
@@ -720,6 +764,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
||||||
"Texture object here should always be an object with mipmap");
|
"Texture object here should always be an object with mipmap");
|
||||||
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||||
|
if (static_cast<Uint>(level) >= textureMipmapObject->GetMipmapLevelCount()) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidValue,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture level is out of range."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level);
|
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level);
|
||||||
|
|
||||||
SizeT inputSize = 0;
|
SizeT inputSize = 0;
|
||||||
@@ -1206,6 +1256,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
// ===================== Error Checking ==============================
|
// ===================== Error Checking ==============================
|
||||||
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
// ======================= Processing ================================
|
// ======================= Processing ================================
|
||||||
if (internalformat == GL_ALPHA || format == GL_ALPHA) {
|
if (internalformat == GL_ALPHA || format == GL_ALPHA) {
|
||||||
@@ -1319,6 +1370,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
// ===================== Error Checking ==============================
|
// ===================== Error Checking ==============================
|
||||||
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
// ======================= Processing ================================
|
// ======================= Processing ================================
|
||||||
if (internalformat == GL_ALPHA || format == GL_ALPHA) {
|
if (internalformat == GL_ALPHA || format == GL_ALPHA) {
|
||||||
@@ -1422,6 +1474,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
isProxy ? TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadTarget)
|
isProxy ? TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadTarget)
|
||||||
: bindingSlot.GetBoundObject();
|
: bindingSlot.GetBoundObject();
|
||||||
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
if (internalFormat == GL_ALPHA || format == GL_ALPHA) {
|
if (internalFormat == GL_ALPHA || format == GL_ALPHA) {
|
||||||
textureObject->SetSwizzleParamRGBA({TextureSwizzleParam::Zero, TextureSwizzleParam::Zero,
|
textureObject->SetSwizzleParamRGBA({TextureSwizzleParam::Zero, TextureSwizzleParam::Zero,
|
||||||
@@ -1620,6 +1673,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
|
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||||
|
if (params) {
|
||||||
|
*params = textureObject->IsImmutable() ? GL_TRUE : GL_FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||||
|
if (params) {
|
||||||
|
*params = static_cast<GLint>(textureObject->GetImmutableLevels());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GL_TEXTURE_BORDER_COLOR:
|
case GL_TEXTURE_BORDER_COLOR:
|
||||||
if (params) {
|
if (params) {
|
||||||
const auto& borderColor = textureObject->GetBorderColor();
|
const auto& borderColor = textureObject->GetBorderColor();
|
||||||
@@ -1748,6 +1811,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
*params = static_cast<GLfloat>(textureObject->GetLevelRange().y());
|
*params = static_cast<GLfloat>(textureObject->GetLevelRange().y());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||||
|
if (params) {
|
||||||
|
*params = textureObject->IsImmutable() ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||||
|
if (params) {
|
||||||
|
*params = static_cast<GLfloat>(textureObject->GetImmutableLevels());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GL_TEXTURE_BORDER_COLOR:
|
case GL_TEXTURE_BORDER_COLOR:
|
||||||
if (params) {
|
if (params) {
|
||||||
const auto& borderColor = textureObject->GetBorderColor();
|
const auto& borderColor = textureObject->GetBorderColor();
|
||||||
@@ -2165,9 +2238,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
// TODO: implement
|
// TODO: implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
Bool CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||||
GLsizei height, GLint border) {
|
GLsizei height, GLint border) {
|
||||||
auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||||
|
const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
|
const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||||
|
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return false;
|
||||||
|
|
||||||
const auto& currentReadFBO =
|
const auto& currentReadFBO =
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||||
if (!currentReadFBO) {
|
if (!currentReadFBO) {
|
||||||
@@ -2175,7 +2253,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State",
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State",
|
||||||
"No framebuffer is currently bound to the GL_READ_FRAMEBUFFER target."));
|
"No framebuffer is currently bound to the GL_READ_FRAMEBUFFER target."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool isDepth = MG_Util::IsDepthFormatInternalFormat(internalFormat);
|
Bool isDepth = MG_Util::IsDepthFormatInternalFormat(internalFormat);
|
||||||
@@ -2194,7 +2272,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
ErrorCode::InvalidOperation, \
|
ErrorCode::InvalidOperation, \
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State", \
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State", \
|
||||||
"The attachment specified by the read buffer is incomplete.")); \
|
"The attachment specified by the read buffer is incomplete.")); \
|
||||||
return; \
|
return false; \
|
||||||
}
|
}
|
||||||
if (isDepth) {
|
if (isDepth) {
|
||||||
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Depth);
|
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Depth);
|
||||||
@@ -2217,6 +2295,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
||||||
TexImage2D_State(target, level, (GLint)realInternalFormat, width, height, border, format, type, nullptr);
|
TexImage2D_State(target, level, (GLint)realInternalFormat, width, height, border, format, type, nullptr);
|
||||||
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject);
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyTexImage2D_Backend(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
void CopyTexImage2D_Backend(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||||
@@ -2252,18 +2331,33 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
void CompressedTexImage3D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
void CompressedTexImage3D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
|
GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
|
||||||
|
const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
|
const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||||
|
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
THROW_UNIMPL_EXCEPTION;
|
THROW_UNIMPL_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
void CompressedTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
GLint border, GLsizei imageSize, const void* data) {
|
GLint border, GLsizei imageSize, const void* data) {
|
||||||
|
const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
|
const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||||
|
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
THROW_UNIMPL_EXCEPTION;
|
THROW_UNIMPL_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
|
void CompressedTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
|
||||||
GLsizei imageSize, const void* data) {
|
GLsizei imageSize, const void* data) {
|
||||||
|
const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
|
const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||||
|
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
THROW_UNIMPL_EXCEPTION;
|
THROW_UNIMPL_EXCEPTION;
|
||||||
}
|
}
|
||||||
@@ -2567,15 +2661,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (!TextureImpl::ValidateTextureSizeRange(width, 1, 1)) return;
|
if (!TextureImpl::ValidateTextureSizeRange(width, 1, 1)) return;
|
||||||
|
|
||||||
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||||
textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA,
|
if (!ValidateTextureStorageInternalFormat(textureInternalFormat, __func__)) return;
|
||||||
TexturePixelDataType::UnsignedByte);
|
|
||||||
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
|
||||||
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
|
||||||
const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
||||||
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
||||||
@@ -2588,6 +2681,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{levelWidth, 1, 1}, byteSize});
|
textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{levelWidth, 1, 1}, byteSize});
|
||||||
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
||||||
}
|
}
|
||||||
|
textureObject->SetImmutableLevels(static_cast<Uint>(levels));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
|
void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
|
||||||
@@ -2602,15 +2696,21 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (!TextureImpl::ValidateTextureSizeRange(width, height, 1)) return;
|
if (!TextureImpl::ValidateTextureSizeRange(width, height, 1)) return;
|
||||||
|
|
||||||
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||||
textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA,
|
if (!ValidateTextureStorageInternalFormat(textureInternalFormat, __func__)) return;
|
||||||
TexturePixelDataType::UnsignedByte);
|
|
||||||
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
|
||||||
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
if (textureObject->GetTarget() == TextureTarget::TextureCubeMap && width != height) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidValue,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||||
|
"Cube map immutable storage must be square."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
||||||
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
||||||
@@ -2633,6 +2733,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{levelWidth, levelHeight, 1}, byteSize});
|
textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{levelWidth, levelHeight, 1}, byteSize});
|
||||||
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
||||||
}
|
}
|
||||||
|
textureObject->SetImmutableLevels(static_cast<Uint>(levels));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
@@ -2648,15 +2749,23 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (!TextureImpl::ValidateTextureSizeRange(width, height, depth)) return;
|
if (!TextureImpl::ValidateTextureSizeRange(width, height, depth)) return;
|
||||||
|
|
||||||
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||||
textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA,
|
if (!ValidateTextureStorageInternalFormat(textureInternalFormat, __func__)) return;
|
||||||
TexturePixelDataType::UnsignedByte);
|
|
||||||
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
|
||||||
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
if (textureObject->GetStorageType() != TextureStorageType::Mipmap) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!ValidateTextureMutable(textureObject, __func__)) return;
|
||||||
|
if (textureObject->GetTarget() == TextureTarget::TextureCubeMapArray &&
|
||||||
|
(width != height || depth % 6 != 0)) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidValue,
|
||||||
|
MakeUnique<GenericErrorInfo>(
|
||||||
|
"MG_Impl/GLImpl", __func__,
|
||||||
|
"Cube map array immutable storage must be square with depth multiple of 6."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject);
|
||||||
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
|
||||||
@@ -2673,6 +2782,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
{{levelWidth, levelHeight, levelDepth}, byteSize});
|
{{levelWidth, levelHeight, levelDepth}, byteSize});
|
||||||
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false);
|
||||||
}
|
}
|
||||||
|
textureObject->SetImmutableLevels(static_cast<Uint>(levels));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureStorage2DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width,
|
void TextureStorage2DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width,
|
||||||
@@ -3415,7 +3525,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||||
GLsizei height, GLint border) {
|
GLsizei height, GLint border) {
|
||||||
CopyTexImage2D_State(target, level, internalformat, x, y, width, height, border);
|
if (!CopyTexImage2D_State(target, level, internalformat, x, y, width, height, border)) return;
|
||||||
CopyTexImage2D_Backend(target, level, internalformat, x, y, width, height, border);
|
CopyTexImage2D_Backend(target, level, internalformat, x, y, width, height, border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,19 +162,47 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
|
void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
|
||||||
|
if (IsImmutable() && m_immutableLevels > 0) {
|
||||||
|
baseLevel = std::min(baseLevel, m_immutableLevels - 1);
|
||||||
|
}
|
||||||
if (baseLevel == m_levelRange.x()) return;
|
if (baseLevel == m_levelRange.x()) return;
|
||||||
|
|
||||||
m_levelRange.x() = baseLevel;
|
m_levelRange.x() = baseLevel;
|
||||||
|
if (IsImmutable() && m_levelRange.y() < m_levelRange.x()) {
|
||||||
|
m_levelRange.y() = m_levelRange.x();
|
||||||
|
}
|
||||||
++m_textureParamsVersion;
|
++m_textureParamsVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
|
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
|
||||||
|
if (IsImmutable() && m_immutableLevels > 0) {
|
||||||
|
maxLevel = std::min(std::max(maxLevel, m_levelRange.x()), m_immutableLevels - 1);
|
||||||
|
}
|
||||||
if (maxLevel == m_levelRange.y()) return;
|
if (maxLevel == m_levelRange.y()) return;
|
||||||
|
|
||||||
m_levelRange.y() = maxLevel;
|
m_levelRange.y() = maxLevel;
|
||||||
++m_textureParamsVersion;
|
++m_textureParamsVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool TextureObjectBase::IsImmutable() const {
|
||||||
|
return m_immutableLevels > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint TextureObjectBase::GetImmutableLevels() const {
|
||||||
|
return m_immutableLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureObjectBase::SetImmutableLevels(Uint levels) {
|
||||||
|
if (m_immutableLevels == levels) return;
|
||||||
|
|
||||||
|
m_immutableLevels = levels;
|
||||||
|
if (m_immutableLevels > 0) {
|
||||||
|
m_levelRange.x() = std::min(m_levelRange.x(), m_immutableLevels - 1);
|
||||||
|
m_levelRange.y() = std::min(std::max(m_levelRange.y(), m_levelRange.x()), m_immutableLevels - 1);
|
||||||
|
}
|
||||||
|
++m_textureParamsVersion;
|
||||||
|
}
|
||||||
|
|
||||||
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
|
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
|
||||||
return m_textureParamsVersion;
|
return m_textureParamsVersion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
virtual const UintVec2& GetLevelRange() const = 0;
|
virtual const UintVec2& GetLevelRange() const = 0;
|
||||||
virtual void SetBaseLevel(Uint baseLevel) = 0;
|
virtual void SetBaseLevel(Uint baseLevel) = 0;
|
||||||
virtual void SetMaxLevel(Uint maxLevel) = 0;
|
virtual void SetMaxLevel(Uint maxLevel) = 0;
|
||||||
|
virtual Bool IsImmutable() const = 0;
|
||||||
|
virtual Uint GetImmutableLevels() const = 0;
|
||||||
|
virtual void SetImmutableLevels(Uint levels) = 0;
|
||||||
virtual Uint16 GetTextureParamsVersion() const = 0;
|
virtual Uint16 GetTextureParamsVersion() const = 0;
|
||||||
virtual Int GetSamples() const = 0;
|
virtual Int GetSamples() const = 0;
|
||||||
virtual void SetSamples(Int samples) = 0;
|
virtual void SetSamples(Int samples) = 0;
|
||||||
@@ -79,6 +82,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
const UintVec2& GetLevelRange() const override;
|
const UintVec2& GetLevelRange() const override;
|
||||||
void SetBaseLevel(Uint baseLevel) override;
|
void SetBaseLevel(Uint baseLevel) override;
|
||||||
void SetMaxLevel(Uint maxLevel) override;
|
void SetMaxLevel(Uint maxLevel) override;
|
||||||
|
Bool IsImmutable() const override;
|
||||||
|
Uint GetImmutableLevels() const override;
|
||||||
|
void SetImmutableLevels(Uint levels) override;
|
||||||
Uint16 GetTextureParamsVersion() const override;
|
Uint16 GetTextureParamsVersion() const override;
|
||||||
Int GetSamples() const override;
|
Int GetSamples() const override;
|
||||||
void SetSamples(Int samples) override;
|
void SetSamples(Int samples) override;
|
||||||
@@ -100,6 +106,7 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
||||||
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
|
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
|
||||||
UintVec2 m_levelRange = {0, 1000};
|
UintVec2 m_levelRange = {0, 1000};
|
||||||
|
Uint m_immutableLevels = 0;
|
||||||
Uint16 m_textureParamsVersion = 0;
|
Uint16 m_textureParamsVersion = 0;
|
||||||
Int m_samples = 0;
|
Int m_samples = 0;
|
||||||
Bool m_fixedSampleLocations = true;
|
Bool m_fixedSampleLocations = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user