[Fix] (...): Some fix for TexSubImage2D(MG_Impl) and ...

This commit is contained in:
BZLZHH
2026-01-02 19:40:05 +08:00
parent 3822d8169a
commit 28c15148f2
4 changed files with 258 additions and 255 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
#define MOBILEGL_BACKEND_TYPE_DIRECT_GLES 3 #define MOBILEGL_BACKEND_TYPE_DIRECT_GLES 3
// ====================== MobileGL configurations ======================= // // ====================== MobileGL configurations ======================= //
#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_INFO #define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_DEBUG
#define MOBILEGL_LOG_ENABLE_CONSOLE 0 #define MOBILEGL_LOG_ENABLE_CONSOLE 0
#define MOBILEGL_LOG_ENABLE_FILE 1 #define MOBILEGL_LOG_ENABLE_FILE 1
+8 -1
View File
@@ -7,6 +7,7 @@
#include "Managers.h" #include "Managers.h"
#include "MG_Backend/Backends.h" #include "MG_Backend/Backends.h"
#include "MG_Util/Debug/Log.h"
#include "Utils.h" #include "Utils.h"
#include "DirectGLES.h" #include "DirectGLES.h"
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" #include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
@@ -417,6 +418,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
continue; continue;
} }
if (level > 0)
MGLOG_D("%s: Updating dirty mip %d for texture ID %u, size: %dx%d, "
"byteSize: %d",
__func__, level, m_backendTextureId,
textureMipmapObject->GetMipmapTexelSize(uploadTarget, level).x(),
textureMipmapObject->GetMipmapTexelSize(uploadTarget, level).y(), byteSize);
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
@@ -428,7 +436,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
static_cast<GLsizei>(texelSize.x()), static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType, static_cast<GLsizei>(texelSize.y()), glFormat, glType,
textureMipmapObject->MapMipmapData(uploadTarget, level)); textureMipmapObject->MapMipmapData(uploadTarget, level));
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false); textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
} }
} }
+220 -225
View File
@@ -28,7 +28,8 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
SharedPtr<MG_State::GLState::ITextureObject> GetTextureObjectByTarget(TextureUploadTarget textureUploadingTarget, TextureTarget textureTarget) { SharedPtr<MG_State::GLState::ITextureObject> GetTextureObjectByTarget(
TextureUploadTarget textureUploadingTarget, TextureTarget textureTarget) {
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr; SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) { if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
textureObject = textureObject =
@@ -40,8 +41,7 @@ namespace MobileGL {
textureObject = bindingSlot.GetBoundObject(); textureObject = bindingSlot.GetBoundObject();
} }
if (!TextureImpl::ValidateTextureObject(textureObject)) if (!TextureImpl::ValidateTextureObject(textureObject)) return nullptr;
return nullptr;
return textureObject; return textureObject;
} }
@@ -58,10 +58,10 @@ namespace MobileGL {
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
// TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(format); // TextureInternalFormat textureInternalFormat =
// MG_Util::ConvertGLEnumToTextureInternalFormat(format);
MGLOG_D("TexSubImage2D_State: (%d, %d), format = %s, pixels = %p", width, height, MGLOG_D("TexSubImage2D_State: (%d, %d), format = %s, pixels = %p", width, height,
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), pixels);
pixels);
// ===================== Error Checking ============================== // ===================== Error Checking ==============================
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
@@ -88,9 +88,8 @@ namespace MobileGL {
// ===================== Error Checking ============================== // ===================== Error Checking ==============================
if (!TextureImpl::ValidateTextureObject(textureObject)) return; if (!TextureImpl::ValidateTextureObject(textureObject)) return;
if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return; if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return;
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat, if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(
textureInternalFormat, textureInputFormat, textureInternalFormat, texturePixelDataType))
texturePixelDataType))
return; return;
// ======================= Processing ================================ // ======================= Processing ================================
@@ -99,7 +98,7 @@ namespace MobileGL {
// This should automatically compiled out in release, // This should automatically compiled out in release,
// so that we don't take the perf hit of dyn-cast. // so that we don't take the perf hit of dyn-cast.
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()), MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap"); "Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level); auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
@@ -116,17 +115,18 @@ namespace MobileGL {
originalPixels = reinterpret_cast<const char*>(pixelUnpackBufferObject->GetDataReadOnly()->data()) + originalPixels = reinterpret_cast<const char*>(pixelUnpackBufferObject->GetDataReadOnly()->data()) +
reinterpret_cast<SizeT>(pixels); reinterpret_cast<SizeT>(pixels);
} }
if (!originalPixels) { if (!originalPixels) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No data supplied from pixels parameter and no PBO bound.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"No data supplied from pixels parameter and no PBO bound."));
return; return;
} }
const auto& unpackParams = MG_State::pGLContext->GetPixelStoreParameters(true);
void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat, textureInputFormat, texturePixelDataType, {width, height, 1}, originalPixels, unpackParams, textureInternalFormat, textureInputFormat, texturePixelDataType,
false /*TODO*/, inputSize); {width, height, 1}, false, inputSize);
if (!processedPixels || inputSize == 0) { if (!processedPixels || inputSize == 0) {
MGLOG_E("TexSubImage2D_State: Failed to process pixel data for TexSubImage2D, width: %d, height: %d", MGLOG_E("TexSubImage2D_State: Failed to process pixel data for TexSubImage2D, width: %d, height: %d",
@@ -137,37 +137,31 @@ namespace MobileGL {
const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType); const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType);
const SizeT srcRowSize = width * internalBpp; const SizeT srcRowSize = static_cast<SizeT>(width) * internalBpp;
const SizeT destRowSize = texelSize.x() * internalBpp; const SizeT srcStride = (srcRowSize + unpackParams.Alignment - 1) & ~(unpackParams.Alignment - 1);
const SizeT destRowSize = static_cast<SizeT>(texelSize.x()) * internalBpp;
if (xoffset + width > static_cast<GLsizei>(texelSize.x()) || if (xoffset + width > static_cast<GLsizei>(texelSize.x()) ||
yoffset + height > static_cast<GLsizei>(texelSize.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");
"width: %d, height: %d, mipmap size: (%d, %d)",
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 = (Uint8*)textureMipmapObject->MapMipmapData(textureUploadingTarget, level); Uint8* destData = static_cast<Uint8*>(textureMipmapObject->MapMipmapData(textureUploadingTarget, level));
// No allocation should be done here
// if (data.empty()) {
// SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel;
// data.resize(totalSize);
// }
for (GLsizei y = 0; y < height; y++) { if (destData) {
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * internalBpp; for (GLsizei y = 0; y < height; y++) {
const SizeT srcRowOffset = y * srcRowSize; const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * internalBpp;
Memcpy(destData + destRowOffset, srcData + srcRowOffset, srcRowSize); const SizeT srcRowOffset = y * srcStride;
Memcpy(destData + destRowOffset, srcData + srcRowOffset, srcRowSize);
}
} }
free(processedPixels); free(processedPixels);
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true); textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, 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,
@@ -184,9 +178,8 @@ namespace MobileGL {
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
return;
switch (pname) { switch (pname) {
case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_MAG_FILTER:
@@ -246,8 +239,10 @@ namespace MobileGL {
// Not supported in this function // Not supported in this function
default: default:
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, ErrorCode::InvalidEnum,
std::format("pname {} is not a valid texture parameter.", MG_Util::ConvertGLEnumToString(pname)))); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("pname {} is not a valid texture parameter.",
MG_Util::ConvertGLEnumToString(pname))));
return; return;
} }
} }
@@ -259,9 +254,8 @@ namespace MobileGL {
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
return;
switch (pname) { switch (pname) {
case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_MAG_FILTER:
@@ -321,174 +315,170 @@ namespace MobileGL {
// Not supported in this function // Not supported in this function
default: default:
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, ErrorCode::InvalidEnum,
std::format("pname {} is not a valid texture parameter.", MG_Util::ConvertGLEnumToString(pname)))); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("pname {} is not a valid texture parameter.",
MG_Util::ConvertGLEnumToString(pname))));
return; return;
} }
} }
// Quick and dirty TexParameter*v implementation to make NeoForge happy. // Quick and dirty TexParameter*v implementation to make NeoForge happy.
// TODO: implement the missing part // TODO: implement the missing part
void TexParameterfv_State(GLenum target, GLenum pname, const GLfloat * params) { void TexParameterfv_State(GLenum target, GLenum pname, const GLfloat* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
THROW_UNIMPL_EXCEPTION;
break;
}
case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`params` is not valid."));
return; return;
THROW_UNIMPL_EXCEPTION;
break;
}
case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject)
return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`params` is not valid."));
return;
}
} }
textureObject->SetSwizzleParamRGBA(swizzleParams);
break;
} }
default: textureObject->SetSwizzleParamRGBA(swizzleParams);
TexParameterf_State(target, pname, *params); break;
break; }
default:
TexParameterf_State(target, pname, *params);
break;
} }
} }
void TexParameteriv_State(GLenum target, GLenum pname, const GLint * params) { void TexParameteriv_State(GLenum target, GLenum pname, const GLint* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
THROW_UNIMPL_EXCEPTION;
break;
}
case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`params` is not valid."));
return; return;
THROW_UNIMPL_EXCEPTION;
break;
}
case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject)
return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`params` is not valid."));
return;
}
} }
textureObject->SetSwizzleParamRGBA(swizzleParams);
break;
} }
default: textureObject->SetSwizzleParamRGBA(swizzleParams);
TexParameteri_State(target, pname, *params); break;
break; }
default:
TexParameteri_State(target, pname, *params);
break;
} }
} }
void TexParameterIiv_State(GLenum target, GLenum pname, const GLint * params) { void TexParameterIiv_State(GLenum target, GLenum pname, const GLint* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
THROW_UNIMPL_EXCEPTION; THROW_UNIMPL_EXCEPTION;
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`params` is not valid."));
return; return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`params` is not valid."));
return;
}
} }
textureObject->SetSwizzleParamRGBA(swizzleParams);
break;
} }
default: textureObject->SetSwizzleParamRGBA(swizzleParams);
TexParameteri_State(target, pname, *params); break;
break; }
default:
TexParameteri_State(target, pname, *params);
break;
} }
} }
void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint * params) { void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
THROW_UNIMPL_EXCEPTION; THROW_UNIMPL_EXCEPTION;
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
// ======================= Processing ================================ // ======================= Processing ================================
SharedPtr<MG_State::GLState::ITextureObject> textureObject = SharedPtr<MG_State::GLState::ITextureObject> textureObject =
GetTextureObjectByTarget(textureUploadingTarget, textureTarget); GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
if (!textureObject) if (!textureObject) return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`params` is not valid."));
return; return;
Vec4<TextureSwizzleParam> swizzleParams;
for (int i = 0; i < 4; i++) {
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`params` is not valid."));
return;
}
} }
textureObject->SetSwizzleParamRGBA(swizzleParams);
break;
} }
default: textureObject->SetSwizzleParamRGBA(swizzleParams);
TexParameteri_State(target, pname, static_cast<GLint>(*params)); break;
break; }
default:
TexParameteri_State(target, pname, static_cast<GLint>(*params));
break;
} }
} }
@@ -521,8 +511,8 @@ namespace MobileGL {
width, height, border, width, height, border,
MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(), MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)) MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type))
.c_str(),type, .c_str(),
pixels); type, pixels);
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
@@ -539,9 +529,8 @@ namespace MobileGL {
if (!TextureImpl::ValidateTextureSizeRange(width, height)) return; if (!TextureImpl::ValidateTextureSizeRange(width, height)) return;
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
if (!TextureImpl::ValidateTextureBorderNumber(border)) return; if (!TextureImpl::ValidateTextureBorderNumber(border)) return;
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat, if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(
textureInternalFormat, textureInputFormat, textureInternalFormat, texturePixelDataType))
texturePixelDataType))
return; return;
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return; if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
@@ -595,10 +584,9 @@ namespace MobileGL {
} }
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()), MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap"); "Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
// Allocate in TextureObject // Allocate in TextureObject
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes}); textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes});
@@ -609,10 +597,8 @@ namespace MobileGL {
void* processedPixels = nullptr; void* processedPixels = nullptr;
processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat,
textureInternalFormat, textureInputFormat, texturePixelDataType, textureInputFormat, texturePixelDataType, {width, height, 1}, false, imageSize);
{width, height, 1},
false, imageSize);
if (processedPixels && imageSize > 0) { if (processedPixels && imageSize > 0) {
if (imageSize != internalBytes) { if (imageSize != internalBytes) {
@@ -626,6 +612,8 @@ namespace MobileGL {
textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput); textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
} }
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
free(processedPixels); free(processedPixels);
} }
@@ -649,14 +637,14 @@ namespace MobileGL {
if (!bufferObject) { if (!bufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>(
"`buffer` is not zero and is not the name of an existing buffer object.")); "MG_Impl/GLImpl", __func__,
"`buffer` is not zero and is not the name of an existing buffer object."));
return; return;
} }
// ======================= Processing ================================ // ======================= Processing ================================
auto activeUnit = auto activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
auto textureObject = bindingSlot.GetBoundObject(); auto textureObject = bindingSlot.GetBoundObject();
@@ -666,7 +654,7 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"The effective target of `texture` is not `GL_TEXTURE_BUFFER`.")); "The effective target of `texture` is not `GL_TEXTURE_BUFFER`."));
return; return;
} }
@@ -891,39 +879,42 @@ namespace MobileGL {
case GL_TEXTURE_WIDTH: case GL_TEXTURE_WIDTH:
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
break; *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
} break;
default: }
THROW_UNIMPL_EXCEPTION; default:
THROW_UNIMPL_EXCEPTION;
} }
} }
break; break;
case GL_TEXTURE_HEIGHT: case GL_TEXTURE_HEIGHT:
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
break; *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
} break;
default: }
THROW_UNIMPL_EXCEPTION; default:
THROW_UNIMPL_EXCEPTION;
} }
} }
break; break;
case GL_TEXTURE_DEPTH: case GL_TEXTURE_DEPTH:
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
break; *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
} break;
default: }
THROW_UNIMPL_EXCEPTION; default:
THROW_UNIMPL_EXCEPTION;
} }
} }
break; break;
@@ -981,21 +972,23 @@ namespace MobileGL {
case GL_TEXTURE_WIDTH: case GL_TEXTURE_WIDTH:
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
break; *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
} break;
default: }
THROW_UNIMPL_EXCEPTION; default:
} THROW_UNIMPL_EXCEPTION;
}
} }
break; break;
case GL_TEXTURE_HEIGHT: case GL_TEXTURE_HEIGHT:
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break; break;
} }
@@ -1008,13 +1001,15 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); const auto textureMipmapObject =
static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break; break;
} }
default: default:
THROW_UNIMPL_EXCEPTION; THROW_UNIMPL_EXCEPTION;
} } }
}
break; break;
case GL_TEXTURE_INTERNAL_FORMAT: case GL_TEXTURE_INTERNAL_FORMAT:
if (params) { if (params) {
@@ -1224,19 +1219,19 @@ namespace MobileGL {
TexParameteri_State(target, pname, param); TexParameteri_State(target, pname, param);
} }
void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params) { void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) {
TexParameterfv_State(target, pname, params); TexParameterfv_State(target, pname, params);
} }
void TexParameteriv(GLenum target, GLenum pname, const GLint * params) { void TexParameteriv(GLenum target, GLenum pname, const GLint* params) {
TexParameteriv_State(target, pname, params); TexParameteriv_State(target, pname, params);
} }
void TexParameterIiv(GLenum target, GLenum pname, const GLint * params) { void TexParameterIiv(GLenum target, GLenum pname, const GLint* params) {
TexParameterIiv_State(target, pname, params); TexParameterIiv_State(target, pname, params);
} }
void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params) { void TexParameterIuiv(GLenum target, GLenum pname, const GLuint* params) {
TexParameterIuiv_State(target, pname, params); TexParameterIuiv_State(target, pname, params);
} }
@@ -49,32 +49,32 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
bytes += rowBytes; bytes += rowBytes;
} }
} }
static Uint8 GetSwizzledChannelValue(Uint8* pixel, TextureSwizzleParam param) { static Uint8 GetSwizzledChannelValue(Uint8* pixel, TextureSwizzleParam param) {
switch (param) { switch (param) {
case TextureSwizzleParam::Red: case TextureSwizzleParam::Red:
return pixel[0]; return pixel[0];
case TextureSwizzleParam::Green: case TextureSwizzleParam::Green:
return pixel[1]; return pixel[1];
case TextureSwizzleParam::Blue: case TextureSwizzleParam::Blue:
return pixel[2]; return pixel[2];
case TextureSwizzleParam::Alpha: case TextureSwizzleParam::Alpha:
return pixel[3]; return pixel[3];
case TextureSwizzleParam::Zero: case TextureSwizzleParam::Zero:
return 0; return 0;
case TextureSwizzleParam::One: case TextureSwizzleParam::One:
return 0xFF; return 0xFF;
default: default:
return 0xBD; return 0xBD;
} }
} }
// assume 8 bit per channel // assume 8 bit per channel
// swizzle.size() == channel count // swizzle.size() == channel count
static void ProcessColorSwizzle(void* data, SizeT pixelCount, const Vector<TextureSwizzleParam>& swizzle) { static void ProcessColorSwizzle(void* data, SizeT pixelCount, const Vector<TextureSwizzleParam>& swizzle) {
const auto bpp = swizzle.size(); const auto bpp = swizzle.size();
Uint8* bytes = static_cast<Uint8*>(data); Uint8* bytes = static_cast<Uint8*>(data);
static Uint8 pixelScratch[4]; Uint8 pixelScratch[4];
for (SizeT i = 0; i < pixelCount; ++i) { for (SizeT i = 0; i < pixelCount; ++i) {
Uint8* pixel = bytes + i * bpp; Uint8* pixel = bytes + i * bpp;
for (SizeT ch = 0; ch < bpp; ++ch) { for (SizeT ch = 0; ch < bpp; ++ch) {
@@ -85,7 +85,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
} }
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params, void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params,
TextureInternalFormat targetInternalFormat, TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType, TextureInternalFormat targetInternalFormat,
TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType,
IntVec3 dimension, Bool isBitmap, SizeT& outSize) { IntVec3 dimension, Bool isBitmap, SizeT& outSize) {
const SizeT pixelSize = MG_Util::GetInputBytesPerPixel(textureInputFormat, inputDataType); const SizeT pixelSize = MG_Util::GetInputBytesPerPixel(textureInputFormat, inputDataType);
@@ -125,14 +126,16 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
src += static_cast<SizeT>(startY) * inputStride; src += static_cast<SizeT>(startY) * inputStride;
src += static_cast<SizeT>(startX) * pixelSize; src += static_cast<SizeT>(startX) * pixelSize;
Bool isByteType =
(inputDataType == TexturePixelDataType::UnsignedByte || inputDataType == TexturePixelDataType::Byte);
for (Int z = 0; z < copyDepth; ++z) { for (Int z = 0; z < copyDepth; ++z) {
const Uint8* layerSrc = src; const Uint8* layerSrc = src;
Uint8* layerDst = dst; Uint8* layerDst = dst;
for (Int y = 0; y < copyHeight; ++y) { for (Int y = 0; y < copyHeight; ++y) {
Memcpy(layerDst, layerSrc, static_cast<SizeT>(copyWidth) * pixelSize); Memcpy(layerDst, layerSrc, static_cast<SizeT>(copyWidth) * pixelSize);
if (params.SwapBytes && pixelSize > 1) { if (params.SwapBytes && pixelSize > 1 && !isByteType) {
MGLOG_D("%s: SwapBytes", __func__); MGLOG_D("%s: SwapBytes", __func__);
SwapBytes(layerDst, pixelSize, static_cast<SizeT>(copyWidth)); SwapBytes(layerDst, pixelSize, static_cast<SizeT>(copyWidth));
} }
@@ -141,16 +144,14 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
MGLOG_D("%s: LSBFirst", __func__); MGLOG_D("%s: LSBFirst", __func__);
ProcessLSBFirst(layerDst, static_cast<SizeT>(copyWidth), 1); ProcessLSBFirst(layerDst, static_cast<SizeT>(copyWidth), 1);
} }
if (textureInputFormat == TextureInputFormat::BGRA && targetInternalFormat == TextureInternalFormat::RGBA8) { if (textureInputFormat == TextureInputFormat::BGRA &&
targetInternalFormat == TextureInternalFormat::RGBA8) {
MGLOG_D("%s: Swizzle (BGRA)", __func__); MGLOG_D("%s: Swizzle (BGRA)", __func__);
MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst)); MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst));
ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth), { ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth),
TextureSwizzleParam::Green, {TextureSwizzleParam::Green, TextureSwizzleParam::Blue,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha, TextureSwizzleParam::Red});
TextureSwizzleParam::Alpha,
TextureSwizzleParam::Red
});
MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst));
} else } else
MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst)); MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst));