mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (MG_Impl/Texture): Decouple texture internal format and input format
This commit is contained in:
@@ -51,7 +51,7 @@ namespace MobileGL {
|
||||
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
|
||||
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
||||
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(format);
|
||||
// TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(format);
|
||||
|
||||
// ===================== Error Checking ==============================
|
||||
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
||||
@@ -60,10 +60,6 @@ namespace MobileGL {
|
||||
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
||||
if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return;
|
||||
if (!TextureImpl::ValidateTextureSizeRange(width, height)) return;
|
||||
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
||||
if (!TextureImpl::ValidateTextureFormatWithType(textureInputFormat, textureInternalFormat,
|
||||
texturePixelDataType))
|
||||
return;
|
||||
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
||||
if (!pixels) return;
|
||||
|
||||
@@ -79,10 +75,15 @@ namespace MobileGL {
|
||||
auto activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
||||
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
||||
auto textureObject = bindingSlot.GetBoundObject();
|
||||
TextureInternalFormat textureInternalFormat = textureObject->GetFormat();
|
||||
|
||||
// ===================== Error Checking ==============================
|
||||
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
||||
if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return;
|
||||
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat,
|
||||
textureInternalFormat,
|
||||
texturePixelDataType))
|
||||
return;
|
||||
|
||||
// ======================= Processing ================================
|
||||
// Texture object here should always be an object with mipmap
|
||||
@@ -94,8 +95,7 @@ namespace MobileGL {
|
||||
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
|
||||
|
||||
SizeT imageSize = 0;
|
||||
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
||||
SizeT inputSize = 0;
|
||||
|
||||
const void* originalPixels = pixels;
|
||||
|
||||
@@ -110,18 +110,20 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
||||
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), bytesPerPixel, {width, height, 1},
|
||||
false /*TODO*/, imageSize);
|
||||
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat, textureInputFormat, texturePixelDataType, {width, height, 1},
|
||||
false /*TODO*/, inputSize);
|
||||
|
||||
if (!processedPixels || imageSize == 0) {
|
||||
if (!processedPixels || inputSize == 0) {
|
||||
MGLOG_E("TexSubImage2D_State: Failed to process pixel data for TexSubImage2D, width: %d, height: %d",
|
||||
width, height);
|
||||
if (processedPixels) free(processedPixels);
|
||||
return;
|
||||
}
|
||||
|
||||
const SizeT srcRowSize = width * bytesPerPixel;
|
||||
const SizeT destRowSize = texelSize.x() * bytesPerPixel;
|
||||
const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
||||
|
||||
const SizeT srcRowSize = width * internalBpp;
|
||||
const SizeT destRowSize = texelSize.x() * internalBpp;
|
||||
|
||||
if (xoffset + width > static_cast<GLsizei>(texelSize.x()) ||
|
||||
yoffset + height > static_cast<GLsizei>(texelSize.y())) {
|
||||
@@ -141,7 +143,7 @@ namespace MobileGL {
|
||||
// }
|
||||
|
||||
for (GLsizei y = 0; y < height; y++) {
|
||||
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * bytesPerPixel;
|
||||
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * internalBpp;
|
||||
const SizeT srcRowOffset = y * srcRowSize;
|
||||
Memcpy(destData + destRowOffset, srcData + srcRowOffset, srcRowSize);
|
||||
}
|
||||
@@ -522,8 +524,9 @@ namespace MobileGL {
|
||||
if (!TextureImpl::ValidateTextureSizeRange(width, height)) return;
|
||||
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
||||
if (!TextureImpl::ValidateTextureBorderNumber(border)) return;
|
||||
if (!TextureImpl::ValidateTextureFormatWithType(textureInputFormat, textureInternalFormat,
|
||||
texturePixelDataType))
|
||||
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat,
|
||||
textureInternalFormat,
|
||||
texturePixelDataType))
|
||||
return;
|
||||
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
||||
|
||||
@@ -555,8 +558,9 @@ namespace MobileGL {
|
||||
// ======================= Processing ================================
|
||||
|
||||
SizeT imageSize = 0;
|
||||
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
||||
const SizeT totalBytes = width * height * bytesPerPixel;
|
||||
const SizeT inputBpp = MG_Util::GetInputBytesPerPixel(textureInputFormat, texturePixelDataType);
|
||||
const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
||||
const SizeT internalBytes = width * height * internalBpp;
|
||||
|
||||
textureObject->SetInternalFormat(textureInternalFormat);
|
||||
|
||||
@@ -581,7 +585,7 @@ namespace MobileGL {
|
||||
|
||||
|
||||
// Allocate in TextureObject
|
||||
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, totalBytes});
|
||||
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes});
|
||||
|
||||
if (!originalPixels) {
|
||||
MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer");
|
||||
@@ -590,17 +594,19 @@ namespace MobileGL {
|
||||
|
||||
void* processedPixels = nullptr;
|
||||
processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
||||
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), bytesPerPixel, {width, height, 1},
|
||||
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true),
|
||||
textureInternalFormat, textureInputFormat, texturePixelDataType,
|
||||
{width, height, 1},
|
||||
false, imageSize);
|
||||
|
||||
if (processedPixels && imageSize > 0) {
|
||||
if (imageSize != totalBytes) {
|
||||
if (imageSize != internalBytes) {
|
||||
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);
|
||||
imageSize, internalBytes);
|
||||
}
|
||||
|
||||
const SizeT copySize = std::min(imageSize, totalBytes);
|
||||
const SizeT copySize = std::min(imageSize, internalBytes);
|
||||
DataPtr texelInput{processedPixels, copySize};
|
||||
textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
|
||||
}
|
||||
|
||||
@@ -162,15 +162,15 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Bool ValidateTextureFormatWithType(TextureInputFormat format, TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type) {
|
||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type) {
|
||||
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
|
||||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
|
||||
type == TexturePixelDataType::UnsignedInt101111Rev) {
|
||||
if (format != TextureInputFormat::RGB) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureFormatWithType",
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for the given type"));
|
||||
return false;
|
||||
}
|
||||
@@ -185,7 +185,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureFormatWithType",
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for the given type"));
|
||||
return false;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
if (format != TextureInputFormat::DepthComponent) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureFormatWithType",
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid format for depth component internal format"));
|
||||
return false;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureFormatWithType",
|
||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
||||
"Invalid internal format for depth component format"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
Bool ValidateTextureSizeRange(SizeT width, SizeT height);
|
||||
Bool ValidateTextureInternalFormat(TextureInternalFormat format);
|
||||
Bool ValidateTextureBorderNumber(Int border);
|
||||
Bool ValidateTextureFormatWithType(TextureInputFormat format, TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type);
|
||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type);
|
||||
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level);
|
||||
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject);
|
||||
Bool ValidateTextureTargetUniformity(SharedPtr<MG_State::GLState::ITextureObject> textureObject,
|
||||
|
||||
@@ -85,6 +85,34 @@ namespace MobileGL {
|
||||
}
|
||||
}
|
||||
|
||||
SizeT GetBaseInputFormatComponentCount(TextureInputFormat format) {
|
||||
switch (format) {
|
||||
case TextureInputFormat::Red:
|
||||
case TextureInputFormat::RInteger:
|
||||
return 1;
|
||||
case TextureInputFormat::RG:
|
||||
case TextureInputFormat::RGInteger:
|
||||
return 2;
|
||||
case TextureInputFormat::RGB:
|
||||
case TextureInputFormat::BGR:
|
||||
case TextureInputFormat::RGBInteger:
|
||||
case TextureInputFormat::BGRInteger:
|
||||
return 3;
|
||||
case TextureInputFormat::RGBA:
|
||||
case TextureInputFormat::BGRA:
|
||||
case TextureInputFormat::RGBAInteger:
|
||||
case TextureInputFormat::BGRAInteger:
|
||||
return 4;
|
||||
case TextureInputFormat::StencilIndex:
|
||||
case TextureInputFormat::DepthComponent:
|
||||
case TextureInputFormat::DepthStencil:
|
||||
return 1;
|
||||
default:
|
||||
MGLOG_D("%s: Unknown input format!", __func__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format) {
|
||||
switch (format) {
|
||||
case TextureInternalFormat::DepthComponent:
|
||||
@@ -208,17 +236,17 @@ namespace MobileGL {
|
||||
return chCount * bytesPerChannel;
|
||||
}
|
||||
|
||||
SizeT GetInputBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) {
|
||||
SizeT GetInputBytesPerPixel(TextureInputFormat inputFormat, TexturePixelDataType type) {
|
||||
SizeT sizedPixelFormatSize = GetSizedTexturePixelDataTypeSize(type);
|
||||
if (sizedPixelFormatSize > 0) return sizedPixelFormatSize;
|
||||
SizeT bytesPerChannel = GetBaseTexturePixelDataTypeSize(type);
|
||||
SizeT chCount = GetBaseInternalFormatComponentCount(internalformat);
|
||||
SizeT chCount = GetBaseInputFormatComponentCount(inputFormat);
|
||||
return chCount * bytesPerChannel;
|
||||
}
|
||||
|
||||
SizeT CalculateInputTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType,
|
||||
SizeT CalculateInputTextureImageSize(TextureInputFormat inputFormat, TexturePixelDataType pixelDataType,
|
||||
IntVec3 size) {
|
||||
return GetInputBytesPerPixel(internalFormat, pixelDataType) * size.x() * size.y() * size.z();
|
||||
return GetInputBytesPerPixel(inputFormat, pixelDataType) * size.x() * size.y() * size.z();
|
||||
}
|
||||
|
||||
ComponentSizes GetComponentSizesForInternalFormat(TextureInternalFormat internal) {
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace MobileGL {
|
||||
// This should respect internal format more
|
||||
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type);
|
||||
// This should respect type more, representing data passed in
|
||||
SizeT GetInputBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type);
|
||||
SizeT CalculateInputTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType,
|
||||
SizeT GetInputBytesPerPixel(TextureInputFormat inputFormat, TexturePixelDataType type);
|
||||
SizeT CalculateInputTextureImageSize(TextureInputFormat inputFormat, TexturePixelDataType pixelDataType,
|
||||
IntVec3 size);
|
||||
ComponentSizes GetComponentSizesForInternalFormat(TextureInternalFormat internal);
|
||||
} // namespace MG_Util
|
||||
|
||||
@@ -43,12 +43,10 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
|
||||
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params,
|
||||
TextureInternalFormat targetInternalFormat, TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType,
|
||||
IntVec3 dimension, Bool isBitmap, SizeT& outSize) {
|
||||
if (pixelSize == 0) {
|
||||
outSize = 0;
|
||||
return nullptr;
|
||||
}
|
||||
const SizeT pixelSize = MG_Util::GetInputBytesPerPixel(textureInputFormat, inputDataType);
|
||||
|
||||
Int width = dimension.x();
|
||||
Int height = dimension.y();
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_State/GLState/RenderState/RenderState.h>
|
||||
#include "MG_State/GLState/TextureState/TextureEnum.h"
|
||||
#include "MG_Util/Metrics/TextureMetrics.h"
|
||||
|
||||
namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
|
||||
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params,
|
||||
TextureInternalFormat targetInternalFormat, TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType,
|
||||
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
||||
void* ProcessTexturePixelsDataPack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
|
||||
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
||||
|
||||
Reference in New Issue
Block a user