diff --git a/CMakeLists.txt b/CMakeLists.txt index 96e5e734..004df90f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ set(SOURCE_FILES MobileGL/MG_State/GLState/TextureState/TextureObject.cpp MobileGL/MG_State/GLState/TextureState/TextureObject1D.cpp 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/TextureUnit.cpp MobileGL/MG_State/GLState/TextureState/TextureState.cpp diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 955e414d..738986ff 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -296,30 +296,44 @@ namespace MobileGL::MG_Backend::DirectGLES { GLenum glInternalFormat, glType, glFormat; TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType, &glFormat); - for (SizeT level = 0; level < mipmapCount; ++level) { - // TODO: deal with multiple upload target texture - auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level); - auto levelByteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level); - bool levelDirty = stateTextureObject->IsStorageDirty(TextureUploadTarget::Texture2D, 0); - auto* pData = (levelDirty && levelByteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr; - MGLOG_D("%s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, - level, - levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), - levelByteSize, - pData); - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); - errorLopper.Clear(); - MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - MG_External::GLES::glTexImage2D(GL_TEXTURE_2D, static_cast(level), glInternalFormat, - static_cast(levelTexelSize.x()), - static_cast(levelTexelSize.y()), 0, glFormat, glType, - pData); - // TODO: handle more texture types + const auto& uploadTargets = stateTextureObject->GetUploadTargets(); + for (auto uploadTarget: uploadTargets) { + for (SizeT level = 0; level < mipmapCount; ++level) { + auto levelTexelSize = stateTextureObject->GetMipmapTexelSize( + uploadTarget, level); + auto levelByteSize = stateTextureObject->GetMipmapByteSize( + uploadTarget, level); + bool levelDirty = stateTextureObject->IsStorageDirty( + uploadTarget, 0); + auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); + auto *pData = (levelDirty && levelByteSize != 0) + ? stateTextureObject->MapMipmapData( + uploadTarget, level) : nullptr; + MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, + MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), + level, + levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), + levelByteSize, + pData); + BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = + BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + errorLopper.Clear(); + MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + MG_External::GLES::glTexImage2D(glUploadTarget, static_cast(level), + glInternalFormat, + static_cast(levelTexelSize.x()), + static_cast(levelTexelSize.y()), 0, + glFormat, glType, + pData); - MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId); - stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false); + // TODO: handle more texture types + + MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, + m_backendTextureId); + stateTextureObject->MarkStorageDirty(uploadTarget, level, + false); + } } m_isInitialized = true; @@ -429,30 +443,41 @@ namespace MobileGL::MG_Backend::DirectGLES { GLenum glInternalFormat, glType, glFormat; TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType, &glFormat); - for (SizeT level = 0; level < mipmapCount; ++level) { - if (!stateTextureObject->IsStorageDirty(TextureUploadTarget::Texture2D, level)) { - continue; + const auto& uploadTargets = stateTextureObject->GetUploadTargets(); + for (auto uploadTarget: uploadTargets) { + for (SizeT level = 0; level < mipmapCount; ++level) { + if (!stateTextureObject->IsStorageDirty(uploadTarget, level)) { + continue; + } + + auto byteSize = stateTextureObject->GetMipmapByteSize( + uploadTarget, level); + if (byteSize == 0) { + MGLOG_W("Mipmap level %d has no data, skipping update.", level); + continue; + } + + auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); + + BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = + BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + errorLopper.Loop( + [file = __FILE__, line = __LINE__, func = __func__](GLenum err) { + MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, + MG_Util::ConvertGLEnumToString(err).c_str()); + }); + auto texelSize = stateTextureObject->GetMipmapTexelSize( + uploadTarget, level); + MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast(level), + 0, 0, + static_cast(texelSize.x()), + static_cast(texelSize.y()), + glFormat, glType, + stateTextureObject->MapMipmapData(uploadTarget, level)); + + stateTextureObject->MarkStorageDirty(uploadTarget, level, false); } - - auto byteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level); - if (byteSize == 0) { - MGLOG_W("Mipmap level %d has no data, skipping update.", level); - continue; - } - - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); - MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { - MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); - }); - auto texelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level); - MG_External::GLES::glTexSubImage2D(GL_TEXTURE_2D, static_cast(level), 0, 0, - static_cast(texelSize.x()), - static_cast(texelSize.y()), glFormat, glType, - (byteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr); - - stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false); } } errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp index e80db01a..01afca22 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp @@ -114,12 +114,10 @@ namespace MobileGL { void TextureObjectWithOneMipmap::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) { - // don't care target, index always 0 m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input); } void TextureObjectWithOneMipmap::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) { - // ditto m_textureStorage.UpdateSubData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input); } void* TextureObjectWithOneMipmap::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) { @@ -127,7 +125,6 @@ namespace MobileGL { } void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) { - // ditto m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty); } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index ba0c23bf..89860857 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -25,6 +25,7 @@ namespace MobileGL { virtual TextureInternalFormat GetFormat() const = 0; virtual TextureTarget GetTarget() const = 0; + virtual const Vector& GetUploadTargets() const = 0; virtual IntVec3 GetBaseSize() const = 0; virtual SharedPtr GetSamplerObject() const = 0; virtual void SetInternalFormat(TextureInternalFormat format) = 0; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject1D.h b/MobileGL/MG_State/GLState/TextureState/TextureObject1D.h index 0d4b733e..f930693a 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject1D.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject1D.h @@ -7,9 +7,12 @@ namespace MobileGL { class TextureObject1D : public TextureObjectWithOneMipmap { public: explicit TextureObject1D(Uint externalIndex); - + const Vector& GetUploadTargets() const override { + return m_uploadTargets; + } protected: Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + const Vector m_uploadTargets {TextureUploadTarget::Texture1D}; }; } } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h index bc573103..1cb3d040 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2D.h @@ -7,9 +7,12 @@ namespace MobileGL { class TextureObject2D : public TextureObjectWithOneMipmap { public: explicit TextureObject2D(Uint externalIndex); - + const Vector& GetUploadTargets() const override { + return m_uploadTargets; + } protected: Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + const Vector m_uploadTargets {TextureUploadTarget::Texture2D}; }; } } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp new file mode 100644 index 00000000..62e9aa14 --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp @@ -0,0 +1,59 @@ +#include "TextureObject2DCube.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + TextureObject2DCube::TextureObject2DCube(Uint externalIndex): + TextureObjectBase(TextureTarget::TextureCubeMap, externalIndex) { + + } + + Uint TextureObject2DCube::GetMipmapLevelCount() const { + return m_textureStorage.GetLevelCount(); + } + + const IntVec3 TextureObject2DCube::GetMipmapTexelSize(TextureUploadTarget target, + Uint mipmapLevel) const { + return m_textureStorage.GetTexelSize(GetIndexOfTextureUploadTarget(target), mipmapLevel); + } + + const SizeT TextureObject2DCube::GetMipmapByteSize(TextureUploadTarget target, + Uint mipmapLevel) const { + return m_textureStorage.GetByteSize(GetIndexOfTextureUploadTarget(target), mipmapLevel); + } + + void + TextureObject2DCube::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, + MipmapInput input) { + m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input); + } + + void TextureObject2DCube::UpdateMipmapSubData(TextureUploadTarget uploadTarget, + Uint mipmapLevel, DataPtr input) { + m_textureStorage.UpdateSubData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input); + } + + void * + TextureObject2DCube::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) { + return m_textureStorage.MapData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel); + } + + void TextureObject2DCube::MarkStorageDirty(TextureUploadTarget uploadTarget, + Uint mipmapLevel, bool dirty) { + m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty); + } + + bool TextureObject2DCube::IsStorageDirty(TextureUploadTarget uploadTarget, + Uint mipmapLevel) const { + return m_textureStorage.IsDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel); + } + + Uint + TextureObject2DCube::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const { + MOBILEGL_ASSERT(TextureUploadTarget::CubeMapPositiveX <= target && target <= TextureUploadTarget::ProxyCubeMap, + "Invalid TextureUploadTarget!"); + return (Uint)target - (Uint)TextureUploadTarget::CubeMapPositiveX; + } + } + } +} diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h new file mode 100644 index 00000000..138e5f0b --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h @@ -0,0 +1,37 @@ +#pragma once +#include "TextureObject.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class TextureObject2DCube : public TextureObjectBase { + public: + explicit TextureObject2DCube(Uint externalIndex); + + const Vector& GetUploadTargets() const override { + return m_uploadTargets; + } + + Uint GetMipmapLevelCount() const override; + const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const override; + const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const override; + void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override; + void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override; + void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override; + void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) override; + bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override; + protected: + Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + TextureStorage<6> m_textureStorage; + const Vector m_uploadTargets { + TextureUploadTarget::CubeMapPositiveX, + TextureUploadTarget::CubeMapNegativeX, + TextureUploadTarget::CubeMapPositiveY, + TextureUploadTarget::CubeMapNegativeY, + TextureUploadTarget::CubeMapPositiveZ, + TextureUploadTarget::CubeMapNegativeZ, + }; + }; + } + } +} diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject3D.h b/MobileGL/MG_State/GLState/TextureState/TextureObject3D.h index b81e8b56..e1a87d50 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject3D.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject3D.h @@ -7,9 +7,12 @@ namespace MobileGL { class TextureObject3D : public TextureObjectWithOneMipmap { public: explicit TextureObject3D(Uint externalIndex); - + const Vector& GetUploadTargets() const override { + return m_uploadTargets; + } protected: Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + const Vector m_uploadTargets {TextureUploadTarget::Texture3D}; }; } } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index 0e58996e..ef54482b 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -4,6 +4,7 @@ #include "MG_State/GLState/TextureState/TextureObject2D.h" #include "MG_State/GLState/TextureState/TextureObject3D.h" #include "MG_Util/Types.h" +#include "TextureObject2DCube.h" namespace MobileGL { namespace MG_State { @@ -34,7 +35,9 @@ namespace MobileGL { case TextureTarget::Texture1D: textureObject = MakeShared(index); break; - case TextureTarget::TextureCubeMap: // TODO + case TextureTarget::TextureCubeMap: + textureObject = MakeShared(index); + break; case TextureTarget::Texture2D: textureObject = MakeShared(index); break;