diff --git a/CMakeLists.txt b/CMakeLists.txt index 2528ad2e..922ac20f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,7 @@ set(SOURCE_FILES MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp MobileGL/MG_State/GLState/TextureState/TextureObject3D.cpp + MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp MobileGL/MG_State/GLState/TextureState/TextureState.cpp MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index dfedf9be..96ffcb2f 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -750,9 +750,9 @@ namespace MobileGL::MG_Backend::DirectGLES { auto textureObject = bindingSlot.GetBoundObject(); textureObject->SetInternalFormat(mglInternalFormat); - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0}); } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index cf0168e3..594e7ad3 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -295,7 +295,7 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(baseSize.z()), 0}; switch (stateTextureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - auto* textureMipmapObject = static_cast(stateTextureObject.get()); + auto* textureMipmapObject = static_cast(stateTextureObject.get()); const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); currentTextureInfo.mipmapLevels = mipmapCount; diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index baea89f0..87b9e199 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -7,6 +7,8 @@ #include "MG_Util/Types.h" #include "Validators.h" #include "ProxyTexture.h" +#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" + #include #include #include @@ -68,9 +70,9 @@ namespace MobileGL { // Assert this for extra safety. // This should automatically compiled out in release, // so that we don't take the perf hit of dyn-cast. - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level); SizeT imageSize = 0; @@ -403,9 +405,9 @@ namespace MobileGL { reinterpret_cast(pixels); } - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); // Allocate in TextureObject @@ -442,9 +444,48 @@ namespace MobileGL { THROW_UNIMPL_EXCEPTION; } - void TexBuffer_State(GLenum target, GLenum internalformat, GLuint texture) { - // TODO: implement - THROW_UNIMPL_EXCEPTION; + void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) { + // ======================= Converting ================================ + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return; + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + // TODO: make sure `internalformat` is in one of supported format for TexBuffer + auto bufferObject = MG_State::pGLContext->GetBufferObject(buffer); + if (!bufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "`buffer` is not zero and is not the name of an existing buffer object.")); + return; + } + + // ======================= Processing ================================ + auto activeUnit = + MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto textureObject = bindingSlot.GetBoundObject(); + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (textureObject->GetStorageType() != TextureStorageType::Buffer) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared("MG_Impl/GLImpl", __func__, + "The effective target of `texture` is not `GL_TEXTURE_BUFFER`.")); + return; + } + + // ======================= Processing ================================ + // Now we can rest assured, and down-cast texture object to texture buffer + auto* texBufferObject = static_cast(textureObject.get()); + auto& bufferSlot = texBufferObject->GetBufferBindingSlot(); + bufferSlot.Bind(bufferObject); + + texBufferObject->SetInternalFormat(textureInternalFormat); } GLboolean IsTexture_State(GLuint texture) { @@ -660,7 +701,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); break; } @@ -673,7 +714,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); break; } @@ -686,7 +727,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); break; } @@ -750,7 +791,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); break; } @@ -763,7 +804,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); break; } @@ -776,7 +817,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); break; } @@ -1017,8 +1058,8 @@ namespace MobileGL { TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels); } - void TexBuffer(GLenum target, GLenum internalformat, GLuint texture) { - TexBuffer_State(target, internalformat, texture); + void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer) { + TexBuffer_State(target, internalformat, buffer); } GLboolean IsTexture(GLuint texture) { diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp index 68482117..4c88c2cf 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -52,8 +52,8 @@ namespace MobileGL { IntVec3 FramebufferAttachment::GetSize() const { if (IsTexture()) { // TODO: get correct upload target - MOBILEGL_ASSERT(nullptr != dynamic_cast(m_texture.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(m_texture.get()); + MOBILEGL_ASSERT(nullptr != dynamic_cast(m_texture.get()), "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(m_texture.get()); return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); } else if (IsRenderbuffer()) { // TODO diff --git a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h index 25d75b13..e5a3dcfe 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h @@ -38,6 +38,7 @@ namespace MobileGL { CubeMapNegativeY, CubeMapPositiveZ, CubeMapNegativeZ, + TextureBuffer, ProxyCubeMap, CubeMapArray, ProxyCubeMapArray, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index eecfefe8..236114a9 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -69,9 +69,9 @@ namespace MobileGL { UintVec2 m_levelRange = {0, 1000}; }; - class TextureMipmapObject : public TextureObjectBase { + class TextureObjectMipmap : public TextureObjectBase { public: - TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} + TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } @@ -85,10 +85,10 @@ namespace MobileGL { virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; }; - class TextureObjectWithOneMipmap : public TextureMipmapObject { + class TextureObjectWithOneMipmap : public TextureObjectMipmap { public: TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) - : TextureMipmapObject(target, externalIndex) {} + : TextureObjectMipmap(target, externalIndex) {} virtual ~TextureObjectWithOneMipmap() = default; Uint GetMipmapLevelCount() const override; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp index 6521138e..f643f539 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { TextureObject2DCube::TextureObject2DCube(Uint externalIndex) - : TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {} + : TextureObjectMipmap(TextureTarget::TextureCubeMap, externalIndex) {} Uint TextureObject2DCube::GetMipmapLevelCount() const { return m_textureStorage.GetLevelCount(); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h index 3c31b125..46c42a4a 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { - class TextureObject2DCube : public TextureMipmapObject { + class TextureObject2DCube : public TextureObjectMipmap { public: explicit TextureObject2DCube(Uint externalIndex); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp new file mode 100644 index 00000000..e96301fa --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp @@ -0,0 +1,20 @@ +#include "TextureObjectBuffer.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + TextureObjectBuffer::TextureObjectBuffer(Uint externalIndex) + : TextureObjectBase(TextureTarget::TextureBuffer, externalIndex) {} + + Uint TextureObjectBuffer::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const { + MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!"); + return 0; + } + + BindingSlot& TextureObjectBuffer::GetBufferBindingSlot(TextureUploadTarget target) { + MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!"); + return m_bufferBindingSlot; + } + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h new file mode 100644 index 00000000..29fcc21a --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h @@ -0,0 +1,23 @@ +#pragma once +#include "TextureObject.h" +#include "MG_State/GLState/BufferState/BufferObject.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class TextureObjectBuffer : public TextureObjectBase { + public: + TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; } + explicit TextureObjectBuffer(Uint externalIndex); + const Vector& GetUploadTargets() const override { return m_uploadTargets; } + BindingSlot& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer); + + protected: + Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + + BindingSlot m_bufferBindingSlot = BindingSlot(BufferTarget::Texture); + const Vector m_uploadTargets{TextureUploadTarget::TextureBuffer}; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h index 541b5be6..fad347df 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h @@ -31,8 +31,8 @@ namespace MobileGL { STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject2DMultisample, TextureTarget::Texture2DMultisample, {TextureUploadTarget::Texture2DMultisample}); - STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer, - {TextureUploadTarget::Unknown}); + // STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer, + // {TextureUploadTarget::Unknown}); STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject1DArray, TextureTarget::Texture1DArray, {TextureUploadTarget::Texture1DArray}); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index c479c7a9..aab12d87 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -6,6 +6,7 @@ #include "TextureObject2D.h" #include "TextureObject3D.h" #include "TextureObject2DCube.h" +#include "TextureObjectBuffer.h" #include "TextureObjectStubs.h" namespace MobileGL { @@ -46,6 +47,9 @@ namespace MobileGL { case TextureTarget::Texture3D: textureObject = MakeShared(index); break; + case TextureTarget::TextureBuffer: + textureObject = MakeShared(index); + break; // These texture types are stubbed: case TextureTarget::TextureRectangle: @@ -54,9 +58,6 @@ namespace MobileGL { case TextureTarget::Texture2DMultisample: textureObject = MakeShared(index); break; - case TextureTarget::TextureBuffer: - textureObject = MakeShared(index); - break; case TextureTarget::Texture1DArray: textureObject = MakeShared(index); break;