mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_State/TextureState): refractor mipmap (TextureStorage)
This commit is contained in:
@@ -602,12 +602,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(mglInternalFormat, texturePixelDataType);
|
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(mglInternalFormat, texturePixelDataType);
|
||||||
const SizeT totalBytes = width * height * bytesPerPixel;
|
const SizeT totalBytes = width * height * bytesPerPixel;
|
||||||
|
|
||||||
MG_State::GLState::MipmapLevelInput mipmap =
|
// MG_State::GLState::MipmapLevelInput mipmap =
|
||||||
MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0,
|
// MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0,
|
||||||
{nullptr, totalBytes});
|
// {nullptr, totalBytes});
|
||||||
|
|
||||||
textureObject->SetInternalFormat(mglInternalFormat);
|
textureObject->SetInternalFormat(mglInternalFormat);
|
||||||
textureObject->SetMipmapLevel(mipmap);
|
textureObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, totalBytes});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
|
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
|
||||||
|
|||||||
@@ -273,10 +273,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
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();
|
||||||
StateTextureBasicInfo currentTextureInfo = {
|
StateTextureBasicInfo currentTextureInfo = {
|
||||||
stateTextureObject->GetFormat(), static_cast<SizeT>(stateTextureObject->GetBaseSize().x()),
|
stateTextureObject->GetFormat(), static_cast<SizeT>(baseSize.x()),
|
||||||
static_cast<SizeT>(stateTextureObject->GetBaseSize().y()),
|
static_cast<SizeT>(baseSize.y()),
|
||||||
static_cast<SizeT>(stateTextureObject->GetBaseSize().z()), stateTextureObject->GetMipmaps().size()};
|
static_cast<SizeT>(baseSize.z()), mipmapCount };
|
||||||
|
|
||||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||||
|
|
||||||
@@ -285,34 +287,34 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
m_backendTextureId);
|
m_backendTextureId);
|
||||||
|
|
||||||
// Regenerate all mipmap levels
|
// Regenerate all mipmap levels
|
||||||
const auto& mipmaps = stateTextureObject->GetMipmaps();
|
|
||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
||||||
&glFormat);
|
&glFormat);
|
||||||
for (SizeT level = 0; level < mipmaps.size(); ++level) {
|
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||||
const auto& mipmap = mipmaps[level];
|
// TODO: deal with multiple upload target texture
|
||||||
|
auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level);
|
||||||
|
auto levelByteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level);
|
||||||
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(GL_TEXTURE_2D, static_cast<GLint>(level), glInternalFormat,
|
MG_External::GLES::glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), glInternalFormat,
|
||||||
static_cast<GLsizei>(mipmap.size.x()),
|
static_cast<GLsizei>(levelTexelSize.x()),
|
||||||
static_cast<GLsizei>(mipmap.size.y()), 0, glFormat, glType,
|
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType,
|
||||||
mipmap.hasData ? mipmap.data.data() : nullptr);
|
(levelByteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr);
|
||||||
|
|
||||||
errorLopper.Loop([index = stateTextureObject->GetExternalIndex(), &mipmap, level, glInternalFormat, glFormat, glType, file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
// errorLopper.Loop([index = stateTextureObject->GetExternalIndex(), &mipmap, level, glInternalFormat, glFormat, glType, file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||||
MGLOG_D("%s(%s:%d) ES error: %s, texobj %d, mip %d (%dx%d, %s, %s, %s)", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
// MGLOG_D("%s(%s:%d) ES error: %s, texobj %d, mip %d (%dx%d, %s, %s, %s)", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||||
index, level, mipmap.size.x(), mipmap.size.y(),
|
// index, level, mipmap.size.x(), mipmap.size.y(),
|
||||||
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(),
|
// MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(glFormat).c_str(),
|
// MG_Util::ConvertGLEnumToString(glFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(glType).c_str()
|
// MG_Util::ConvertGLEnumToString(glType).c_str()
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
// 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->UnmarkMipmapDirty(level);
|
stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
@@ -418,17 +420,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Update all dirty mipmap levels
|
{ // Update all dirty mipmap levels
|
||||||
const auto& mipmaps = stateTextureObject->GetMipmaps();
|
const auto mipmapCount = stateTextureObject->GetMipmapLevelCount();
|
||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
||||||
&glFormat);
|
&glFormat);
|
||||||
for (const auto& mipmap : stateTextureObject->GetMipmaps()) {
|
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||||
if (!mipmap.dirty) {
|
if (!stateTextureObject->IsStorageDirty(TextureUploadTarget::Texture2D, level)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mipmap.data.empty()) {
|
auto byteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level);
|
||||||
MGLOG_W("Mipmap level %d has no data, skipping update.", mipmap.level);
|
if (byteSize == 0) {
|
||||||
|
MGLOG_W("Mipmap level %d has no data, skipping update.", level);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,15 +441,16 @@ 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());
|
||||||
});
|
});
|
||||||
MG_External::GLES::glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(mipmap.level), 0, 0,
|
auto texelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level);
|
||||||
static_cast<GLsizei>(mipmap.size.x()),
|
MG_External::GLES::glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), 0, 0,
|
||||||
static_cast<GLsizei>(mipmap.size.y()), glFormat, glType,
|
static_cast<GLsizei>(texelSize.x()),
|
||||||
mipmap.hasData ? mipmap.data.data() : nullptr);
|
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, &mipmap, glFormat, glType](GLenum err) {
|
(byteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr);
|
||||||
MGLOG_D("%s(%s:%d) ES error at glTexSubImage2D: %s (mip %d, %dx%d, %s, %s)", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
// errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, &mipmap, glFormat, glType](GLenum err) {
|
||||||
mipmap.level, mipmap.size.x(), mipmap.size.y(), MG_Util::ConvertGLEnumToString(glFormat).c_str(), MG_Util::ConvertGLEnumToString(glType).c_str());
|
// MGLOG_D("%s(%s:%d) ES error at glTexSubImage2D: %s (mip %d, %dx%d, %s, %s)", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||||
});
|
// mipmap.level, mipmap.size.x(), mipmap.size.y(), MG_Util::ConvertGLEnumToString(glFormat).c_str(), MG_Util::ConvertGLEnumToString(glType).c_str());
|
||||||
stateTextureObject->UnmarkMipmapDirty(mipmap.level);
|
// });
|
||||||
|
stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ 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);
|
// auto& mipmap = textureObject->GetMipmap(level);
|
||||||
Vector<Uint8>& data = mipmap.data;
|
// Vector<Uint8>& data = mipmap.data;
|
||||||
|
auto texelSize = textureObject->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);
|
||||||
@@ -94,23 +95,24 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SizeT srcRowSize = width * bytesPerPixel;
|
const SizeT srcRowSize = width * bytesPerPixel;
|
||||||
const SizeT destRowSize = mipmap.size.x() * bytesPerPixel;
|
const SizeT destRowSize = texelSize.x() * bytesPerPixel;
|
||||||
|
|
||||||
if (xoffset + width > static_cast<GLsizei>(mipmap.size.x()) ||
|
if (xoffset + width > static_cast<GLsizei>(texelSize.x()) ||
|
||||||
yoffset + height > static_cast<GLsizei>(mipmap.size.y())) {
|
yoffset + height > static_cast<GLsizei>(texelSize.y())) {
|
||||||
MGLOG_E("TexSubImage2D_State: Specified region exceeds texture dimensions, xoffset: %d, yoffset: %d, "
|
MGLOG_E("TexSubImage2D_State: Specified region exceeds texture dimensions, xoffset: %d, yoffset: %d, "
|
||||||
"width: %d, height: %d, mipmap size: (%d, %d)",
|
"width: %d, height: %d, mipmap size: (%d, %d)",
|
||||||
xoffset, yoffset, width, height, mipmap.size.x(), mipmap.size.y());
|
xoffset, yoffset, width, height, texelSize.x(), texelSize.y());
|
||||||
free(processedPixels);
|
free(processedPixels);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* srcData = static_cast<const Uint8*>(processedPixels);
|
const auto* srcData = static_cast<const Uint8*>(processedPixels);
|
||||||
Uint8* destData = data.data();
|
Uint8* destData = (Uint8*)textureObject->MapMipmapData(textureUploadingTarget, level);
|
||||||
if (data.empty()) {
|
// No allocation should be done here
|
||||||
SizeT totalSize = mipmap.size.x() * mipmap.size.y() * bytesPerPixel;
|
// if (data.empty()) {
|
||||||
data.resize(totalSize);
|
// SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel;
|
||||||
}
|
// data.resize(totalSize);
|
||||||
|
// }
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; y++) {
|
for (GLsizei y = 0; y < height; y++) {
|
||||||
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * bytesPerPixel;
|
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * bytesPerPixel;
|
||||||
@@ -120,8 +122,9 @@ namespace MobileGL {
|
|||||||
|
|
||||||
free(processedPixels);
|
free(processedPixels);
|
||||||
|
|
||||||
mipmap.dirty = true;
|
textureObject->MarkStorageDirty(textureUploadingTarget, level, true);
|
||||||
mipmap.hasData = true;
|
// mipmap.dirty = true;
|
||||||
|
// mipmap.hasData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
|
void TexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
|
||||||
@@ -375,10 +378,17 @@ namespace MobileGL {
|
|||||||
// ======================= Processing ================================
|
// ======================= Processing ================================
|
||||||
|
|
||||||
SizeT imageSize = 0;
|
SizeT imageSize = 0;
|
||||||
void* processedPixels = nullptr;
|
|
||||||
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
||||||
const SizeT totalBytes = width * height * bytesPerPixel;
|
const SizeT totalBytes = width * height * bytesPerPixel;
|
||||||
|
|
||||||
|
textureObject->SetInternalFormat(textureInternalFormat);
|
||||||
|
// Allocate in TextureObject
|
||||||
|
textureObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, isProxy ? 0 : totalBytes});
|
||||||
|
|
||||||
|
// if isProxy, no more pixel transfer needed below
|
||||||
|
if (isProxy)
|
||||||
|
return;
|
||||||
|
|
||||||
const void* originalPixels = pixels;
|
const void* originalPixels = pixels;
|
||||||
|
|
||||||
// PBO
|
// PBO
|
||||||
@@ -391,25 +401,17 @@ namespace MobileGL {
|
|||||||
reinterpret_cast<SizeT>(pixels);
|
reinterpret_cast<SizeT>(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* processedPixels = nullptr;
|
||||||
if (originalPixels) {
|
if (originalPixels) {
|
||||||
processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
||||||
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), bytesPerPixel,
|
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), bytesPerPixel,
|
||||||
{width, height, 1}, false, imageSize);
|
{width, height, 1}, false, imageSize);
|
||||||
} else {
|
} else {
|
||||||
MGLOG_D("TexImage2D_State: No input pixel, do allocate only");
|
MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MG_State::GLState::MipmapLevelInput mipmap =
|
if (processedPixels && imageSize > 0) {
|
||||||
MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0,
|
|
||||||
{(isProxy || originalPixels == nullptr) ? nullptr : malloc(totalBytes), isProxy ? 0 : totalBytes});
|
|
||||||
|
|
||||||
if (!isProxy && originalPixels != nullptr && !mipmap.inputData.data) {
|
|
||||||
MGLOG_E("TexImage2D_State: Failed to allocate memory for mipmap level data, size: %zu", totalBytes);
|
|
||||||
free(processedPixels);
|
|
||||||
processedPixels = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processedPixels && imageSize > 0 && !isProxy) {
|
|
||||||
if (imageSize != totalBytes) {
|
if (imageSize != totalBytes) {
|
||||||
MGLOG_W("TexImage2D_State: Processed pixel data size (%zu) does not match expected size (%zu). "
|
MGLOG_W("TexImage2D_State: Processed pixel data size (%zu) does not match expected size (%zu). "
|
||||||
"This may indicate an alignment or processing issue.",
|
"This may indicate an alignment or processing issue.",
|
||||||
@@ -417,20 +419,53 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SizeT copySize = std::min(imageSize, totalBytes);
|
const SizeT copySize = std::min(imageSize, totalBytes);
|
||||||
Memcpy(mipmap.inputData.data, processedPixels, copySize);
|
DataPtr texelInput { processedPixels, copySize };
|
||||||
free(processedPixels);
|
textureObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
|
||||||
} else if (processedPixels && !isProxy) {
|
} else if (originalPixels) {
|
||||||
MGLOG_E("TexImage2D_State: Failed to process pixel data, initializing with original data.");
|
MGLOG_E("TexImage2D_State: Failed to process pixel data, initializing with original data.");
|
||||||
Memcpy(mipmap.inputData.data, originalPixels, totalBytes);
|
DataPtr texelInput { (void*)originalPixels, totalBytes };
|
||||||
} else {
|
textureObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
|
||||||
if (mipmap.inputData.data) {
|
|
||||||
free(mipmap.inputData.data);
|
|
||||||
mipmap.inputData.data = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
free(processedPixels);
|
||||||
textureObject->SetInternalFormat(textureInternalFormat);
|
|
||||||
textureObject->SetMipmapLevel(mipmap);
|
// MG_State::GLState::MipmapLevelInput mipmap =
|
||||||
free(mipmap.inputData.data);
|
// MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0,
|
||||||
|
// {(isProxy || originalPixels == nullptr) ? nullptr : malloc(totalBytes), isProxy ? 0 : totalBytes});
|
||||||
|
|
||||||
|
|
||||||
|
// if (!isProxy && originalPixels != nullptr && !mipmap.inputData.data) {
|
||||||
|
// MGLOG_E("TexImage2D_State: Failed to allocate memory for mipmap level data, size: %zu", totalBytes);
|
||||||
|
// free(processedPixels);
|
||||||
|
// processedPixels = nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!isProxy && originalPixels != nullptr) {
|
||||||
|
// MGLOG_E("TexImage2D_State: Failed to allocate memory for mipmap level data, size: %zu", totalBytes);
|
||||||
|
// free(processedPixels);
|
||||||
|
// processedPixels = nullptr;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (processedPixels && imageSize > 0 && !isProxy) {
|
||||||
|
// if (imageSize != totalBytes) {
|
||||||
|
// MGLOG_W("TexImage2D_State: Processed pixel data size (%zu) does not match expected size (%zu). "
|
||||||
|
// "This may indicate an alignment or processing issue.",
|
||||||
|
// imageSize, totalBytes);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const SizeT copySize = std::min(imageSize, totalBytes);
|
||||||
|
// Memcpy(mipmap.inputData.data, processedPixels, copySize);
|
||||||
|
// free(processedPixels);
|
||||||
|
// } else if (processedPixels && !isProxy) {
|
||||||
|
// MGLOG_E("TexImage2D_State: Failed to process pixel data, initializing with original data.");
|
||||||
|
// Memcpy(mipmap.inputData.data, originalPixels, totalBytes);
|
||||||
|
// } else {
|
||||||
|
// if (mipmap.inputData.data) {
|
||||||
|
// free(mipmap.inputData.data);
|
||||||
|
// mipmap.inputData.data = nullptr;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// textureObject->SetMipmapLevel(mipmap);
|
||||||
|
// free(mipmap.inputData.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border,
|
void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border,
|
||||||
@@ -649,17 +684,17 @@ namespace MobileGL {
|
|||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_TEXTURE_WIDTH:
|
case GL_TEXTURE_WIDTH:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.x();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_HEIGHT:
|
case GL_TEXTURE_HEIGHT:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.y();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_DEPTH:
|
case GL_TEXTURE_DEPTH:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.z();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||||
@@ -715,17 +750,17 @@ namespace MobileGL {
|
|||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_TEXTURE_WIDTH:
|
case GL_TEXTURE_WIDTH:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.x();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_HEIGHT:
|
case GL_TEXTURE_HEIGHT:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.y();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_DEPTH:
|
case GL_TEXTURE_DEPTH:
|
||||||
if (params) {
|
if (params) {
|
||||||
*params = textureObject->GetMipmap(level).size.z();
|
*params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||||
|
|||||||
@@ -16,13 +16,16 @@ namespace MobileGL {
|
|||||||
auto fbo0 = MG_State::pGLContext->CreateFramebufferObject(0);
|
auto fbo0 = MG_State::pGLContext->CreateFramebufferObject(0);
|
||||||
auto colorTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
auto colorTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
||||||
colorTex->SetInternalFormat(TextureInternalFormat::RGBA8);
|
colorTex->SetInternalFormat(TextureInternalFormat::RGBA8);
|
||||||
colorTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
colorTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, { {512, 512, 1}, 0 });
|
||||||
|
// colorTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
||||||
auto depthTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
auto depthTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
||||||
depthTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
|
depthTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
|
||||||
depthTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, { {512, 512, 1}, 0 });
|
||||||
|
// depthTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
||||||
auto stencilTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
auto stencilTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
|
||||||
stencilTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
|
stencilTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
|
||||||
stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, { {512, 512, 1}, 0 });
|
||||||
|
// stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
||||||
fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex);
|
fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex);
|
||||||
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
|
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
|
||||||
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
|
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ namespace MobileGL {
|
|||||||
|
|
||||||
IntVec3 FramebufferAttachment::GetSize() const {
|
IntVec3 FramebufferAttachment::GetSize() const {
|
||||||
if (IsTexture()) {
|
if (IsTexture()) {
|
||||||
return m_texture->GetMipmap(m_textureLevel).size;
|
// TODO: get correct upload target
|
||||||
|
return m_texture->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
|
||||||
} else if (IsRenderbuffer()) {
|
} else if (IsRenderbuffer()) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace MobileGL {
|
||||||
|
enum class TextureTarget {
|
||||||
|
Texture1D,
|
||||||
|
Texture2D,
|
||||||
|
Texture3D,
|
||||||
|
TextureCubeMap,
|
||||||
|
TextureRectangle,
|
||||||
|
Texture2DMultisample,
|
||||||
|
TextureBuffer,
|
||||||
|
Texture1DArray,
|
||||||
|
Texture2DArray,
|
||||||
|
TextureCubeMapArray,
|
||||||
|
Texture2DMultisampleArray,
|
||||||
|
TextureTargetCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't tinker with order in this enum
|
||||||
|
// it is used in TextureStorage
|
||||||
|
enum class TextureUploadTarget {
|
||||||
|
Texture2D,
|
||||||
|
ProxyTexture2D,
|
||||||
|
Texture1DArray,
|
||||||
|
ProxyTexture1DArray,
|
||||||
|
TextureRectangle,
|
||||||
|
ProxyTextureRectangle,
|
||||||
|
CubeMapPositiveX,
|
||||||
|
CubeMapNegativeX,
|
||||||
|
CubeMapPositiveY,
|
||||||
|
CubeMapNegativeY,
|
||||||
|
CubeMapPositiveZ,
|
||||||
|
CubeMapNegativeZ,
|
||||||
|
ProxyCubeMap,
|
||||||
|
Texture2DMultisample,
|
||||||
|
ProxyTexture2DMultisample,
|
||||||
|
TextureUploadTargetCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureInputFormat {
|
||||||
|
Red,
|
||||||
|
RG,
|
||||||
|
RGB,
|
||||||
|
BGR,
|
||||||
|
RGBA,
|
||||||
|
BGRA,
|
||||||
|
RInteger,
|
||||||
|
RGInteger,
|
||||||
|
RGBInteger,
|
||||||
|
BGRInteger,
|
||||||
|
RGBAInteger,
|
||||||
|
BGRAInteger,
|
||||||
|
StencilIndex,
|
||||||
|
DepthComponent,
|
||||||
|
DepthStencil,
|
||||||
|
|
||||||
|
FormatCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureInternalFormat {
|
||||||
|
R8,
|
||||||
|
R8Snorm,
|
||||||
|
R16,
|
||||||
|
R16Snorm,
|
||||||
|
RG8,
|
||||||
|
RG8Snorm,
|
||||||
|
RG16,
|
||||||
|
RG16Snorm,
|
||||||
|
R3G3B2,
|
||||||
|
RGB4,
|
||||||
|
RGB5,
|
||||||
|
RGB8,
|
||||||
|
RGB8Snorm,
|
||||||
|
RGB10,
|
||||||
|
RGB12,
|
||||||
|
RGB16Snorm,
|
||||||
|
RGBA2,
|
||||||
|
RGBA4,
|
||||||
|
RGB5A1,
|
||||||
|
RGBA8,
|
||||||
|
RGBA8Snorm,
|
||||||
|
RGB10A2,
|
||||||
|
RGB10A2UI,
|
||||||
|
RGBA12,
|
||||||
|
RGBA16,
|
||||||
|
SRGB8,
|
||||||
|
SRGB8Alpha8,
|
||||||
|
R16F,
|
||||||
|
RG16F,
|
||||||
|
RGB16F,
|
||||||
|
RGBA16F,
|
||||||
|
R32F,
|
||||||
|
RG32F,
|
||||||
|
RGB32F,
|
||||||
|
RGBA32F,
|
||||||
|
R11FG11FB10F,
|
||||||
|
RGB9E5,
|
||||||
|
R8I,
|
||||||
|
R8UI,
|
||||||
|
R16I,
|
||||||
|
R16UI,
|
||||||
|
R32I,
|
||||||
|
R32UI,
|
||||||
|
RG8I,
|
||||||
|
RG8UI,
|
||||||
|
RG16I,
|
||||||
|
RG16UI,
|
||||||
|
RG32I,
|
||||||
|
RG32UI,
|
||||||
|
RGB8I,
|
||||||
|
RGB8UI,
|
||||||
|
RGB16I,
|
||||||
|
RGB16UI,
|
||||||
|
RGB32I,
|
||||||
|
RGB32UI,
|
||||||
|
RGBA8I,
|
||||||
|
RGBA8UI,
|
||||||
|
RGBA16I,
|
||||||
|
RGBA16UI,
|
||||||
|
RGBA32I,
|
||||||
|
RGBA32UI,
|
||||||
|
DepthComponent16,
|
||||||
|
DepthComponent24,
|
||||||
|
DepthComponent32, // not a standard format in OpenGL core profile
|
||||||
|
DepthComponent32F,
|
||||||
|
Depth24Stencil8,
|
||||||
|
Depth32FStencil8,
|
||||||
|
|
||||||
|
DepthComponent,
|
||||||
|
DepthStencil,
|
||||||
|
Red,
|
||||||
|
RG,
|
||||||
|
RGB,
|
||||||
|
RGBA,
|
||||||
|
|
||||||
|
TextureInternalFormatCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TexturePixelDataType {
|
||||||
|
UnsignedByte,
|
||||||
|
Byte,
|
||||||
|
UnsignedShort,
|
||||||
|
Short,
|
||||||
|
UnsignedInt,
|
||||||
|
Int,
|
||||||
|
Float,
|
||||||
|
UnsignedByte332,
|
||||||
|
UnsignedByte233Rev,
|
||||||
|
UnsignedShort565,
|
||||||
|
UnsignedShort565Rev,
|
||||||
|
UnsignedShort4444,
|
||||||
|
UnsignedShort4444Rev,
|
||||||
|
UnsignedShort5551,
|
||||||
|
UnsignedShort1555Rev,
|
||||||
|
UnsignedInt8888,
|
||||||
|
UnsignedInt8888Rev,
|
||||||
|
UnsignedInt1010102,
|
||||||
|
UnsignedInt2101010Rev,
|
||||||
|
UnsignedInt101111Rev, // not a standard type in OpenGL core profile
|
||||||
|
UnsignedInt5999Rev, // not a standard type in OpenGL core profile
|
||||||
|
|
||||||
|
TypeCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureSwizzleParam {
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Blue,
|
||||||
|
Alpha,
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
|
||||||
|
SwizzleParamCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -10,10 +10,45 @@ namespace MobileGL {
|
|||||||
m_sampler = MakeShared<SamplerObject>(0);
|
m_sampler = MakeShared<SamplerObject>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureObjectBase::SetMipmapLevel(const MipmapLevelInput& level) {
|
Uint TextureObjectBase::GetMipmapLevelCount() const {
|
||||||
SetMipmapImpl(level);
|
return m_textureStorage.GetLevelCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IntVec3 TextureObjectBase::GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.GetTexelSize(0, mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SizeT TextureObjectBase::GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.GetByteSize(0, mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureObjectBase::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||||
|
MipmapInput input) {
|
||||||
|
// don't care target, index always 0
|
||||||
|
m_textureStorage.AllocateLevel(0, mipmapLevel, input);
|
||||||
|
}
|
||||||
|
void TextureObjectBase::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||||
|
DataPtr input) {
|
||||||
|
// ditto
|
||||||
|
m_textureStorage.UpdateSubData(0, mipmapLevel, input);
|
||||||
|
}
|
||||||
|
void* TextureObjectBase::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) {
|
||||||
|
return m_textureStorage.MapData(0, mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureObjectBase::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) {
|
||||||
|
// ditto
|
||||||
|
m_textureStorage.MarkDirty(0, mipmapLevel, dirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureObjectBase::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.IsDirty(0, mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void TextureObjectBase::SetMipmapLevel(const MipmapLevelInput& level) {
|
||||||
|
// SetMipmapImpl(level);
|
||||||
|
// }
|
||||||
|
|
||||||
TextureInternalFormat TextureObjectBase::GetFormat() const {
|
TextureInternalFormat TextureObjectBase::GetFormat() const {
|
||||||
return m_internalFormat;
|
return m_internalFormat;
|
||||||
}
|
}
|
||||||
@@ -23,32 +58,33 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IntVec3 TextureObjectBase::GetBaseSize() const {
|
IntVec3 TextureObjectBase::GetBaseSize() const {
|
||||||
if (m_mipmaps.empty()) {
|
if (m_textureStorage.GetLevelCount() == 0) {
|
||||||
return {0, 0, 0};
|
return {0, 0, 0};
|
||||||
}
|
}
|
||||||
return m_mipmaps[0].size;
|
return m_textureStorage.GetTexelSize(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<SamplerObject> TextureObjectBase::GetSamplerObject() const {
|
SharedPtr<SamplerObject> TextureObjectBase::GetSamplerObject() const {
|
||||||
return m_sampler;
|
return m_sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector<MipmapLevelInternal>& TextureObjectBase::GetMipmaps() const {
|
// const Vector<MipmapLevelInternal>& TextureObjectBase::GetMipmaps() const {
|
||||||
return m_mipmaps;
|
// return m_mipmaps;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Bool TextureObjectBase::IsComplete() const {
|
Bool TextureObjectBase::IsComplete() const {
|
||||||
if (m_internalFormat == TextureInternalFormat::Unknown) {
|
if (m_internalFormat == TextureInternalFormat::Unknown) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mipmaps.empty()) {
|
SizeT levelCount = m_textureStorage.GetLevelCount();
|
||||||
|
if (levelCount == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_mipmaps.size(); ++i) {
|
for (size_t i = 0; i < levelCount; ++i) {
|
||||||
const auto& level = m_mipmaps[i];
|
const auto& levelSize = m_textureStorage.GetTexelSize(0, i);
|
||||||
if (level.size.x() <= 0 || level.size.y() <= 0 || level.size.z() <= 0) {
|
if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,23 +93,23 @@ namespace MobileGL {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MipmapLevelInternal& TextureObjectBase::GetMipmap(Int index) {
|
// MipmapLevelInternal& TextureObjectBase::GetMipmap(TextureUploadTarget target, Int index) {
|
||||||
if (index >= m_mipmaps.size()) {
|
// if (index >= m_mipmaps.size()) {
|
||||||
MOBILEGL_ASSERT(false, "GetMipmap: index %d out of bounds, returning last mipmap level", index);
|
// MOBILEGL_ASSERT(false, "GetMipmap: index %d out of bounds, returning last mipmap level", index);
|
||||||
index = static_cast<Int>(m_mipmaps.size() - 1);
|
// index = static_cast<Int>(m_mipmaps.size() - 1);
|
||||||
}
|
// }
|
||||||
return m_mipmaps[index];
|
// return m_mipmaps[index];
|
||||||
}
|
// }
|
||||||
|
|
||||||
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
|
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
|
||||||
m_internalFormat = format;
|
m_internalFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureObjectBase::UnmarkMipmapDirty(Int index) {
|
// void TextureObjectBase::UnmarkMipmapDirty(Int index) {
|
||||||
if (index >= 0 && index < static_cast<Int>(m_mipmaps.size())) {
|
// if (index >= 0 && index < static_cast<Int>(m_mipmaps.size())) {
|
||||||
m_mipmaps[index].dirty = false;
|
// m_mipmaps[index].dirty = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Uint TextureObjectBase::GetExternalIndex() const {
|
Uint TextureObjectBase::GetExternalIndex() const {
|
||||||
return m_externalIndex;
|
return m_externalIndex;
|
||||||
|
|||||||
@@ -1,186 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "TextureEnum.h"
|
||||||
|
#include "TextureStorage.h"
|
||||||
#include "MG_Util/Types.h"
|
#include "MG_Util/Types.h"
|
||||||
#include "../SamplerState/SamplerObject.h"
|
#include "../SamplerState/SamplerObject.h"
|
||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
#include <MG_Util/Math/VectorTypes.h>
|
#include <MG_Util/Math/VectorTypes.h>
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
enum class TextureTarget {
|
|
||||||
Texture1D,
|
|
||||||
Texture2D,
|
|
||||||
Texture3D,
|
|
||||||
TextureCubeMap,
|
|
||||||
TextureRectangle,
|
|
||||||
Texture2DMultisample,
|
|
||||||
TextureBuffer,
|
|
||||||
Texture1DArray,
|
|
||||||
Texture2DArray,
|
|
||||||
TextureCubeMapArray,
|
|
||||||
Texture2DMultisampleArray,
|
|
||||||
TextureTargetCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TextureUploadTarget {
|
|
||||||
Texture2D,
|
|
||||||
ProxyTexture2D,
|
|
||||||
Texture1DArray,
|
|
||||||
ProxyTexture1DArray,
|
|
||||||
TextureRectangle,
|
|
||||||
ProxyTextureRectangle,
|
|
||||||
CubeMapPositiveX,
|
|
||||||
CubeMapNegativeX,
|
|
||||||
CubeMapPositiveY,
|
|
||||||
CubeMapNegativeY,
|
|
||||||
CubeMapPositiveZ,
|
|
||||||
CubeMapNegativeZ,
|
|
||||||
ProxyCubeMap,
|
|
||||||
Texture2DMultisample,
|
|
||||||
ProxyTexture2DMultisample,
|
|
||||||
TextureUploadTargetCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TextureInputFormat {
|
|
||||||
Red,
|
|
||||||
RG,
|
|
||||||
RGB,
|
|
||||||
BGR,
|
|
||||||
RGBA,
|
|
||||||
BGRA,
|
|
||||||
RInteger,
|
|
||||||
RGInteger,
|
|
||||||
RGBInteger,
|
|
||||||
BGRInteger,
|
|
||||||
RGBAInteger,
|
|
||||||
BGRAInteger,
|
|
||||||
StencilIndex,
|
|
||||||
DepthComponent,
|
|
||||||
DepthStencil,
|
|
||||||
|
|
||||||
FormatCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TextureInternalFormat {
|
|
||||||
R8,
|
|
||||||
R8Snorm,
|
|
||||||
R16,
|
|
||||||
R16Snorm,
|
|
||||||
RG8,
|
|
||||||
RG8Snorm,
|
|
||||||
RG16,
|
|
||||||
RG16Snorm,
|
|
||||||
R3G3B2,
|
|
||||||
RGB4,
|
|
||||||
RGB5,
|
|
||||||
RGB8,
|
|
||||||
RGB8Snorm,
|
|
||||||
RGB10,
|
|
||||||
RGB12,
|
|
||||||
RGB16Snorm,
|
|
||||||
RGBA2,
|
|
||||||
RGBA4,
|
|
||||||
RGB5A1,
|
|
||||||
RGBA8,
|
|
||||||
RGBA8Snorm,
|
|
||||||
RGB10A2,
|
|
||||||
RGB10A2UI,
|
|
||||||
RGBA12,
|
|
||||||
RGBA16,
|
|
||||||
SRGB8,
|
|
||||||
SRGB8Alpha8,
|
|
||||||
R16F,
|
|
||||||
RG16F,
|
|
||||||
RGB16F,
|
|
||||||
RGBA16F,
|
|
||||||
R32F,
|
|
||||||
RG32F,
|
|
||||||
RGB32F,
|
|
||||||
RGBA32F,
|
|
||||||
R11FG11FB10F,
|
|
||||||
RGB9E5,
|
|
||||||
R8I,
|
|
||||||
R8UI,
|
|
||||||
R16I,
|
|
||||||
R16UI,
|
|
||||||
R32I,
|
|
||||||
R32UI,
|
|
||||||
RG8I,
|
|
||||||
RG8UI,
|
|
||||||
RG16I,
|
|
||||||
RG16UI,
|
|
||||||
RG32I,
|
|
||||||
RG32UI,
|
|
||||||
RGB8I,
|
|
||||||
RGB8UI,
|
|
||||||
RGB16I,
|
|
||||||
RGB16UI,
|
|
||||||
RGB32I,
|
|
||||||
RGB32UI,
|
|
||||||
RGBA8I,
|
|
||||||
RGBA8UI,
|
|
||||||
RGBA16I,
|
|
||||||
RGBA16UI,
|
|
||||||
RGBA32I,
|
|
||||||
RGBA32UI,
|
|
||||||
DepthComponent16,
|
|
||||||
DepthComponent24,
|
|
||||||
DepthComponent32, // not a standard format in OpenGL core profile
|
|
||||||
DepthComponent32F,
|
|
||||||
Depth24Stencil8,
|
|
||||||
Depth32FStencil8,
|
|
||||||
|
|
||||||
DepthComponent,
|
|
||||||
DepthStencil,
|
|
||||||
Red,
|
|
||||||
RG,
|
|
||||||
RGB,
|
|
||||||
RGBA,
|
|
||||||
|
|
||||||
TextureInternalFormatCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TexturePixelDataType {
|
|
||||||
UnsignedByte,
|
|
||||||
Byte,
|
|
||||||
UnsignedShort,
|
|
||||||
Short,
|
|
||||||
UnsignedInt,
|
|
||||||
Int,
|
|
||||||
Float,
|
|
||||||
UnsignedByte332,
|
|
||||||
UnsignedByte233Rev,
|
|
||||||
UnsignedShort565,
|
|
||||||
UnsignedShort565Rev,
|
|
||||||
UnsignedShort4444,
|
|
||||||
UnsignedShort4444Rev,
|
|
||||||
UnsignedShort5551,
|
|
||||||
UnsignedShort1555Rev,
|
|
||||||
UnsignedInt8888,
|
|
||||||
UnsignedInt8888Rev,
|
|
||||||
UnsignedInt1010102,
|
|
||||||
UnsignedInt2101010Rev,
|
|
||||||
UnsignedInt101111Rev, // not a standard type in OpenGL core profile
|
|
||||||
UnsignedInt5999Rev, // not a standard type in OpenGL core profile
|
|
||||||
|
|
||||||
TypeCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TextureSwizzleParam {
|
|
||||||
Red,
|
|
||||||
Green,
|
|
||||||
Blue,
|
|
||||||
Alpha,
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
|
|
||||||
SwizzleParamCount,
|
|
||||||
Unknown = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace MG_State {
|
namespace MG_State {
|
||||||
namespace GLState {
|
namespace GLState {
|
||||||
struct MipmapLevelBase {
|
struct MipmapLevelBase {
|
||||||
@@ -217,10 +43,19 @@ namespace MobileGL {
|
|||||||
using TargetEnum = TextureTarget;
|
using TargetEnum = TextureTarget;
|
||||||
virtual ~ITextureObject() = default;
|
virtual ~ITextureObject() = default;
|
||||||
|
|
||||||
virtual void SetMipmapLevel(const MipmapLevelInput& level) = 0;
|
// virtual void SetMipmapLevel(const MipmapLevelInput& level) = 0;
|
||||||
virtual const Vector<MipmapLevelInternal>& GetMipmaps() const = 0;
|
// virtual const Vector<MipmapLevelInternal>& GetMipmaps() const = 0;
|
||||||
virtual MipmapLevelInternal& GetMipmap(Int index) = 0;
|
// virtual MipmapLevelInternal& GetMipmap(Int index) = 0;
|
||||||
virtual void UnmarkMipmapDirty(Int index) = 0;
|
// virtual void UnmarkMipmapDirty(Int index) = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
virtual TextureInternalFormat GetFormat() const = 0;
|
virtual TextureInternalFormat GetFormat() const = 0;
|
||||||
virtual TextureTarget GetTarget() const = 0;
|
virtual TextureTarget GetTarget() const = 0;
|
||||||
@@ -243,10 +78,19 @@ namespace MobileGL {
|
|||||||
TextureObjectBase(TextureTarget target, Uint externalIndex);
|
TextureObjectBase(TextureTarget target, Uint externalIndex);
|
||||||
virtual ~TextureObjectBase() = default;
|
virtual ~TextureObjectBase() = default;
|
||||||
|
|
||||||
void SetMipmapLevel(const MipmapLevelInput& level) override;
|
// void SetMipmapLevel(const MipmapLevelInput& level) override;
|
||||||
const Vector<MipmapLevelInternal>& GetMipmaps() const override;
|
// const Vector<MipmapLevelInternal>& GetMipmaps() const override;
|
||||||
MipmapLevelInternal& GetMipmap(Int index) override;
|
// MipmapLevelInternal& GetMipmap(TextureUploadTarget target, Int index) override;
|
||||||
void UnmarkMipmapDirty(Int index) override;
|
// void UnmarkMipmapDirty(Int index) override;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
TextureInternalFormat GetFormat() const override;
|
TextureInternalFormat GetFormat() const override;
|
||||||
TextureTarget GetTarget() const override;
|
TextureTarget GetTarget() const override;
|
||||||
@@ -264,12 +108,13 @@ namespace MobileGL {
|
|||||||
void SetMaxLevel(Uint maxLevel) override;
|
void SetMaxLevel(Uint maxLevel) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetMipmapImpl(const MipmapLevelInput& level) = 0;
|
// virtual void SetMipmapImpl(const MipmapLevelInput& level) = 0;
|
||||||
|
|
||||||
const Uint m_externalIndex;
|
const Uint m_externalIndex;
|
||||||
const TextureTarget m_target = TextureTarget::Unknown;
|
const TextureTarget m_target = TextureTarget::Unknown;
|
||||||
TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown;
|
TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown;
|
||||||
Vector<MipmapLevelInternal> m_mipmaps = {};
|
// Vector<MipmapLevelInternal> m_mipmaps = {};
|
||||||
|
TextureStorage<1> m_textureStorage;
|
||||||
SharedPtr<SamplerObject> m_sampler = nullptr;
|
SharedPtr<SamplerObject> m_sampler = nullptr;
|
||||||
FloatVec4 m_borderColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
FloatVec4 m_borderColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
TextureSwizzleParam m_swizzleParams[4] = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
TextureSwizzleParam m_swizzleParams[4] = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ namespace MobileGL {
|
|||||||
TextureObject1D::TextureObject1D(Uint externalIndex)
|
TextureObject1D::TextureObject1D(Uint externalIndex)
|
||||||
: TextureObjectBase(TextureTarget::Texture1D, externalIndex) {}
|
: TextureObjectBase(TextureTarget::Texture1D, externalIndex) {}
|
||||||
|
|
||||||
void TextureObject1D::SetMipmapImpl(const MipmapLevelInput& level) {
|
// void TextureObject1D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||||
if (level.size.x() > 0) {
|
// if (level.size.x() > 0) {
|
||||||
m_mipmaps.push_back(MipmapLevelInternal(level));
|
// m_mipmaps.push_back(MipmapLevelInternal(level));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace MobileGL {
|
|||||||
explicit TextureObject1D(Uint externalIndex);
|
explicit TextureObject1D(Uint externalIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
// void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ namespace MobileGL {
|
|||||||
TextureObject2D::TextureObject2D(Uint externalIndex)
|
TextureObject2D::TextureObject2D(Uint externalIndex)
|
||||||
: TextureObjectBase(TextureTarget::Texture2D, externalIndex) {}
|
: TextureObjectBase(TextureTarget::Texture2D, externalIndex) {}
|
||||||
|
|
||||||
void TextureObject2D::SetMipmapImpl(const MipmapLevelInput& level) {
|
// void TextureObject2D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||||
if (level.size.x() > 0 && level.size.y() > 0) {
|
// if (level.size.x() > 0 && level.size.y() > 0) {
|
||||||
m_mipmaps.push_back(MipmapLevelInternal(level));
|
// m_mipmaps.push_back(MipmapLevelInternal(level));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace MobileGL {
|
|||||||
explicit TextureObject2D(Uint externalIndex);
|
explicit TextureObject2D(Uint externalIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
// void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ namespace MobileGL {
|
|||||||
TextureObject3D::TextureObject3D(Uint externalIndex)
|
TextureObject3D::TextureObject3D(Uint externalIndex)
|
||||||
: TextureObjectBase(TextureTarget::Texture3D, externalIndex) {}
|
: TextureObjectBase(TextureTarget::Texture3D, externalIndex) {}
|
||||||
|
|
||||||
void TextureObject3D::SetMipmapImpl(const MipmapLevelInput& level) {
|
// void TextureObject3D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||||
if (level.size.x() > 0 && level.size.y() > 0 && level.size.z() > 0) {
|
// if (level.size.x() > 0 && level.size.y() > 0 && level.size.z() > 0) {
|
||||||
m_mipmaps.push_back(MipmapLevelInternal(level));
|
// m_mipmaps.push_back(MipmapLevelInternal(level));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace MobileGL {
|
|||||||
explicit TextureObject3D(Uint externalIndex);
|
explicit TextureObject3D(Uint externalIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
// void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TextureEnum.h"
|
||||||
|
#include "MG_Util/Types.h"
|
||||||
|
#include "MG_Util/Math/VectorTypes.h"
|
||||||
|
|
||||||
|
namespace MobileGL {
|
||||||
|
namespace MG_State {
|
||||||
|
namespace GLState {
|
||||||
|
struct MipmapInput {
|
||||||
|
IntVec3 texelSize = {0, 0, 0};
|
||||||
|
SizeT byteSize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <SizeT TargetCount>
|
||||||
|
class TextureStorage {
|
||||||
|
public:
|
||||||
|
TextureStorage() {
|
||||||
|
static_assert(TargetCount > 0, "Mipmap size must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid");
|
||||||
|
|
||||||
|
auto& targetData = m_data[targetIndex];
|
||||||
|
targetData.reserve(std::bit_ceil(level + 1));
|
||||||
|
targetData.resize(level + 1);
|
||||||
|
auto& targetTexelSizes = m_texelSizes[targetIndex];
|
||||||
|
targetTexelSizes.reserve(std::bit_ceil(level + 1));
|
||||||
|
targetTexelSizes.resize(level + 1);
|
||||||
|
targetTexelSizes[level] = input.texelSize;
|
||||||
|
auto& dirtyArr = m_isDirty[targetIndex];
|
||||||
|
dirtyArr.resize(level + 1, true);
|
||||||
|
|
||||||
|
auto& data = targetData[level];
|
||||||
|
data.resize(input.byteSize, 0);
|
||||||
|
// if (input.texelData.data && input.texelData.size > 0) {
|
||||||
|
// const Uint8* src = static_cast<const Uint8*>(input.texelData.data);
|
||||||
|
// Memcpy(data.data(), src, input.texelData.size);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSubData(Uint targetIndex, Uint level, DataPtr input) {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid");
|
||||||
|
auto& targetData = m_data[targetIndex];
|
||||||
|
MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range");
|
||||||
|
auto& levelData = targetData[level];
|
||||||
|
MOBILEGL_ASSERT(levelData.size() < input.size, "UpdateSubData: input data larger than allocated");
|
||||||
|
|
||||||
|
if (input.data && input.size > 0) {
|
||||||
|
const Uint8* src = static_cast<const Uint8*>(input.data);
|
||||||
|
Memcpy(levelData.data(), src, input.size);
|
||||||
|
m_isDirty[targetIndex][level] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MapData(Uint targetIndex, Uint level) {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid");
|
||||||
|
auto& targetData = m_data[targetIndex];
|
||||||
|
MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range");
|
||||||
|
auto& levelData = targetData[level];
|
||||||
|
return levelData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
IntVec3 GetTexelSize(Uint targetIndex, Uint level) const {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "GetTexelSize: target invalid");
|
||||||
|
|
||||||
|
auto& targetTexelSizes = m_texelSizes[targetIndex];
|
||||||
|
if (level >= targetTexelSizes.size())
|
||||||
|
return {0, 0, 0};
|
||||||
|
return targetTexelSizes[level];
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT GetByteSize(Uint targetIndex, Uint level) const {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "GetByteSize: target invalid");
|
||||||
|
|
||||||
|
auto& data = m_data[targetIndex];
|
||||||
|
return data[level].size();
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT GetLevelCount() const {
|
||||||
|
return m_data[0].size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkDirty(Uint targetIndex, Uint level, bool dirty) {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "MarkDirty: target invalid");
|
||||||
|
MOBILEGL_ASSERT(level < m_isDirty[targetIndex].size(), "MarkDirty: level out of range");
|
||||||
|
m_isDirty[targetIndex][level] = dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDirty(Uint targetIndex, Uint level) const {
|
||||||
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "IsDirty: target invalid");
|
||||||
|
MOBILEGL_ASSERT(level < m_isDirty[targetIndex].size(), "IsDirty: level out of range");
|
||||||
|
return m_isDirty[targetIndex][level];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Array<Vector<IntVec3>, TargetCount> m_texelSizes;
|
||||||
|
Array<Vector<Vector<Uint8>>, TargetCount> m_data;
|
||||||
|
Array<Vector<bool>, TargetCount> m_isDirty;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user