[Feat] (MG_State/Texture): separate mipmap from TextureObjectBase

This commit is contained in:
2025-12-09 10:57:10 +08:00
parent 56f45499e1
commit 0a89ad4f30
8 changed files with 189 additions and 116 deletions
@@ -750,7 +750,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto textureObject = bindingSlot.GetBoundObject(); auto textureObject = bindingSlot.GetBoundObject();
textureObject->SetInternalFormat(mglInternalFormat); textureObject->SetInternalFormat(mglInternalFormat);
textureObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0}); MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0});
} }
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
+85 -77
View File
@@ -289,58 +289,103 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { 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()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
const auto mipmapCount = stateTextureObject->GetMipmapLevelCount();
const auto baseSize = stateTextureObject->GetBaseSize(); const auto baseSize = stateTextureObject->GetBaseSize();
StateTextureBasicInfo currentTextureInfo = { StateTextureBasicInfo currentTextureInfo = {
stateTextureObject->GetFormat(), static_cast<SizeT>(baseSize.x()), static_cast<SizeT>(baseSize.y()), stateTextureObject->GetFormat(), static_cast<SizeT>(baseSize.x()), static_cast<SizeT>(baseSize.y()),
static_cast<SizeT>(baseSize.z()), mipmapCount}; static_cast<SizeT>(baseSize.z()), 0};
switch (stateTextureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(stateTextureObject.get());
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
currentTextureInfo.mipmapLevels = mipmapCount;
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo); Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(), MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(),
baseSize.z(), mipmapCount, baseSize.z(), mipmapCount,
MG_Util::ConvertTextureInternalFormatToString(stateTextureObject->GetFormat()).c_str()); MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str());
if (needsRegeneration) { if (needsRegeneration) {
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u", MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u",
m_backendTextureId); m_backendTextureId);
// Regenerate all mipmap levels // Regenerate all mipmap levels
GLenum glInternalFormat, glType, glFormat; GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType, TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
&glFormat); &glFormat);
const auto& uploadTargets = stateTextureObject->GetUploadTargets(); const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
for (auto uploadTarget : uploadTargets) { for (auto uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) { for (SizeT level = 0; level < mipmapCount; ++level) {
auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(uploadTarget, level); auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
auto levelByteSize = stateTextureObject->GetMipmapByteSize(uploadTarget, level); auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
bool levelDirty = stateTextureObject->IsStorageDirty(uploadTarget, 0); bool levelDirty = textureMipmapObject->IsStorageDirty(uploadTarget, 0);
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
auto* pData = (levelDirty && levelByteSize != 0) auto* pData = (levelDirty && levelByteSize != 0)
? stateTextureObject->MapMipmapData(uploadTarget, level) ? textureMipmapObject->MapMipmapData(uploadTarget, level)
: nullptr; : nullptr;
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__,
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level,
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData); levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData);
BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = BufferImpl::BackendBufferBindingProtector pixelUnpackProtector =
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
errorLopper.Clear(); errorLopper.Clear();
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat, MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.x()),
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType, static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType,
pData); pData);
// TODO: handle more texture types // TODO: handle more texture types
MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId); MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId);
stateTextureObject->MarkStorageDirty(uploadTarget, level, false); textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
}
}
m_isInitialized = true;
} }
}
m_isInitialized = true; { // Update all dirty mipmap levels
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
&glFormat);
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
for (auto uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) {
if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) {
continue;
}
auto byteSize = textureMipmapObject->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 = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
textureMipmapObject->MapMipmapData(uploadTarget, level));
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
}
}
}
break;
}
default: THROW_UNIMPL_EXCEPTION;
} }
{ // Update built-in sampler parameters { // Update built-in sampler parameters
@@ -448,43 +493,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
{ // Update all dirty mipmap levels
const auto mipmapCount = stateTextureObject->GetMipmapLevelCount();
GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
&glFormat);
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<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
stateTextureObject->MapMipmapData(uploadTarget, level));
stateTextureObject->MarkStorageDirty(uploadTarget, level, false);
}
}
}
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { 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()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
+71 -14
View File
@@ -64,9 +64,14 @@ namespace MobileGL {
if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return; if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return;
// ======================= Processing ================================ // ======================= Processing ================================
// auto& mipmap = textureObject->GetMipmap(level); // Texture object here should always be an object with mipmap
// Vector<Uint8>& data = mipmap.data; // Assert this for extra safety.
auto texelSize = textureObject->GetMipmapTexelSize(textureUploadingTarget, level); // This should automatically compiled out in release,
// so that we don't take the perf hit of dyn-cast.
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
SizeT imageSize = 0; SizeT imageSize = 0;
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType); const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
@@ -107,7 +112,7 @@ namespace MobileGL {
} }
const auto* srcData = static_cast<const Uint8*>(processedPixels); const auto* srcData = static_cast<const Uint8*>(processedPixels);
Uint8* destData = (Uint8*)textureObject->MapMipmapData(textureUploadingTarget, level); Uint8* destData = (Uint8*)textureMipmapObject->MapMipmapData(textureUploadingTarget, level);
// No allocation should be done here // No allocation should be done here
// if (data.empty()) { // if (data.empty()) {
// SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel; // SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel;
@@ -122,7 +127,7 @@ namespace MobileGL {
free(processedPixels); free(processedPixels);
textureObject->MarkStorageDirty(textureUploadingTarget, level, true); textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
// mipmap.dirty = true; // mipmap.dirty = true;
// mipmap.hasData = true; // mipmap.hasData = true;
} }
@@ -398,8 +403,13 @@ namespace MobileGL {
reinterpret_cast<SizeT>(pixels); reinterpret_cast<SizeT>(pixels);
} }
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
// Allocate in TextureObject // Allocate in TextureObject
textureObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, totalBytes}); textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, totalBytes});
if (!originalPixels) { if (!originalPixels) {
MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer"); MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer");
@@ -420,7 +430,7 @@ namespace MobileGL {
const SizeT copySize = std::min(imageSize, totalBytes); const SizeT copySize = std::min(imageSize, totalBytes);
DataPtr texelInput{processedPixels, copySize}; DataPtr texelInput{processedPixels, copySize};
textureObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput); textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
} }
free(processedPixels); free(processedPixels);
@@ -648,17 +658,41 @@ namespace MobileGL {
switch (pname) { switch (pname) {
case GL_TEXTURE_WIDTH: case GL_TEXTURE_WIDTH:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_HEIGHT: case GL_TEXTURE_HEIGHT:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_DEPTH: case GL_TEXTURE_DEPTH:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_INTERNAL_FORMAT: case GL_TEXTURE_INTERNAL_FORMAT:
@@ -714,18 +748,41 @@ namespace MobileGL {
switch (pname) { switch (pname) {
case GL_TEXTURE_WIDTH: case GL_TEXTURE_WIDTH:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_HEIGHT: case GL_TEXTURE_HEIGHT:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_DEPTH: case GL_TEXTURE_DEPTH:
if (params) { if (params) {
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); switch (textureObject->GetStorageType()) {
} case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break;
}
default:
THROW_UNIMPL_EXCEPTION;
} }
break; break;
case GL_TEXTURE_INTERNAL_FORMAT: case GL_TEXTURE_INTERNAL_FORMAT:
if (params) { if (params) {
@@ -52,7 +52,9 @@ namespace MobileGL {
IntVec3 FramebufferAttachment::GetSize() const { IntVec3 FramebufferAttachment::GetSize() const {
if (IsTexture()) { if (IsTexture()) {
// TODO: get correct upload target // TODO: get correct upload target
return m_texture->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(m_texture.get()), "Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
} else if (IsRenderbuffer()) { } else if (IsRenderbuffer()) {
// TODO // TODO
} }
@@ -49,6 +49,11 @@ namespace MobileGL {
Unknown = -1 Unknown = -1
}; };
enum class TextureStorageType {
Mipmap,
Buffer
};
enum class TextureInputFormat { enum class TextureInputFormat {
Red, Red,
RG, RG,
@@ -14,14 +14,7 @@ namespace MobileGL {
using TargetEnum = TextureTarget; using TargetEnum = TextureTarget;
virtual ~ITextureObject() = default; virtual ~ITextureObject() = default;
virtual Uint GetMipmapLevelCount() const = 0; virtual TextureStorageType GetStorageType() const = 0;
virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0;
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
virtual TextureInternalFormat GetFormat() const = 0; virtual TextureInternalFormat GetFormat() const = 0;
virtual TextureTarget GetTarget() const = 0; virtual TextureTarget GetTarget() const = 0;
@@ -49,17 +42,6 @@ namespace MobileGL {
TextureObjectBase(TextureTarget target, Uint externalIndex); TextureObjectBase(TextureTarget target, Uint externalIndex);
virtual ~TextureObjectBase() = default; virtual ~TextureObjectBase() = default;
// Mipmap ops
// Uint GetMipmapLevelCount() const = 0;
// const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const =
// 0; const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const =
// 0; void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel,
// MipmapInput input) = 0; void UpdateMipmapSubData(TextureUploadTarget uploadTarget,
// Uint mipmapLevel, DataPtr input) = 0; void* MapMipmapData(TextureUploadTarget
// uploadTarget, Uint mipmapLevel) = 0; void MarkStorageDirty(TextureUploadTarget
// uploadTarget, Uint mipmapLevel, bool dirty) = 0; bool
// IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
TextureInternalFormat GetFormat() const override; TextureInternalFormat GetFormat() const override;
TextureTarget GetTarget() const override; TextureTarget GetTarget() const override;
IntVec3 GetBaseSize() const override; IntVec3 GetBaseSize() const override;
@@ -87,10 +69,26 @@ namespace MobileGL {
UintVec2 m_levelRange = {0, 1000}; UintVec2 m_levelRange = {0, 1000};
}; };
class TextureObjectWithOneMipmap : public TextureObjectBase { class TextureMipmapObject : public TextureObjectBase {
public:
TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
virtual Uint GetMipmapLevelCount() const = 0;
virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0;
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
};
class TextureObjectWithOneMipmap : public TextureMipmapObject {
public: public:
TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex)
: TextureObjectBase(target, externalIndex) {} : TextureMipmapObject(target, externalIndex) {}
virtual ~TextureObjectWithOneMipmap() = default; virtual ~TextureObjectWithOneMipmap() = default;
Uint GetMipmapLevelCount() const override; Uint GetMipmapLevelCount() const override;
@@ -4,7 +4,7 @@ namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
TextureObject2DCube::TextureObject2DCube(Uint externalIndex) TextureObject2DCube::TextureObject2DCube(Uint externalIndex)
: TextureObjectBase(TextureTarget::TextureCubeMap, externalIndex) {} : TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {}
Uint TextureObject2DCube::GetMipmapLevelCount() const { Uint TextureObject2DCube::GetMipmapLevelCount() const {
return m_textureStorage.GetLevelCount(); return m_textureStorage.GetLevelCount();
@@ -4,7 +4,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
class TextureObject2DCube : public TextureObjectBase { class TextureObject2DCube : public TextureMipmapObject {
public: public:
explicit TextureObject2DCube(Uint externalIndex); explicit TextureObject2DCube(Uint externalIndex);