diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 52eaac0a..c6b976cd 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -319,7 +319,7 @@ namespace MobileGL::MG_Backend::DirectGLES { targetInternal == TextureTarget::Texture1DArray || targetInternal == TextureTarget::Texture3D || targetInternal == TextureTarget::Texture2DMultisample || targetInternal == TextureTarget::Texture2DArray) { - MGLOG_D(" Texture target %s is not supported, skipping.", + MGLOG_E(" Texture target %s is not supported, skipping.", MG_Util::ConvertTextureTargetToString(targetInternal).c_str()); return; } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index df269e2a..6f4ff773 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -68,7 +68,7 @@ namespace MobileGL { if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return; if (!TextureImpl::ValidateTextureLevelNumber(level)) return; if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return; - if (!TextureImpl::ValidateTextureSizeRange(width, height)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, height, 1)) return; if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return; // TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the @@ -494,24 +494,16 @@ namespace MobileGL { void TexImage3D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) { - // TODO: implement - } - - void TexImage2D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const void* pixels) { MGLOG_D( - "TexImage2D_State called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, " - "border: %d, format: %s, type: %s (%u), pixels: %p", - MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)) - .c_str(), + "%s called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, depth: %d, " + "border: %d, format: %s, type: %s (%u), pixels: %p", __func__, + MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)).c_str(), level, MG_Util::ConvertTextureInternalFormatToString( - MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)) - .c_str(), - width, height, border, + MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)).c_str(), + width, height, depth, border, MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)) - .c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)).c_str(), type, pixels); // ======================= Converting ================================ TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); @@ -526,7 +518,124 @@ namespace MobileGL { if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return; if (!TextureImpl::ValidateTextureLevelNumber(level)) return; if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return; - if (!TextureImpl::ValidateTextureSizeRange(width, height)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, height, depth)) return; + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (!TextureImpl::ValidateTextureBorderNumber(border)) return; + if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput( + textureInputFormat, textureInternalFormat, texturePixelDataType)) + return; + if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return; + + // TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the + // GL_PIXEL_UNPACK_BUFFER target and the buffer object's data store is currently mapped. + // GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER + // target and the data would be unpacked from the buffer object such that the memory reads required would + // exceed the data store size. + // GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER + // target and data is not evenly divisible into the number of bytes needed to store in memory a datum + // indicated by type. + // ======================= Processing ================================ + SharedPtr textureObject = nullptr; + Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget); + if (isProxy) { + textureObject = + TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget); + } else { + auto activeUnit = + MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + textureObject = bindingSlot.GetBoundObject(); + } + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + + // ======================= Processing ================================ + + SizeT imageSize = 0; + const SizeT inputBpp = MG_Util::GetInputBytesPerPixel(textureInputFormat, texturePixelDataType); + const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType); + const SizeT internalBytes = width * height * depth * internalBpp; + + textureObject->SetInternalFormat(textureInternalFormat); + + // if isProxy, no more pixel transfer needed below + if (isProxy) return; + + const void* originalPixels = pixels; + + // PBO + const auto& pixelUnpackBufferObject = + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); + if (pixelUnpackBufferObject) { + MGLOG_D("%s: Using Pixel Unpack Buffer Object ID: %u", __func__, + pixelUnpackBufferObject->GetExternalIndex()); + originalPixels = reinterpret_cast(pixelUnpackBufferObject->GetDataReadOnly()->data()) + + reinterpret_cast(pixels); + } + + + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + + // Allocate in TextureObject + textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, depth}, internalBytes}); + + if (!originalPixels) { + MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__); + return; + } + + void* processedPixels = nullptr; + processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( + originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat, + textureInputFormat, texturePixelDataType, {width, height, depth}, false, imageSize); + + if (processedPixels && imageSize > 0) { + if (imageSize != internalBytes) { + MGLOG_W("%s: Processed pixel data size (%zu) does not match expected size (%zu). " + "This may indicate an alignment or processing issue.", __func__, + imageSize, internalBytes); + } + + const SizeT copySize = std::min(imageSize, internalBytes); + DataPtr texelInput{processedPixels, copySize}; + textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput); + } + + textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true); + + free(processedPixels); + } + + void TexImage2D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const void* pixels) { + MGLOG_D( + "%s called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, " + "border: %d, format: %s, type: %s (%u), pixels: %p", __func__, + MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)).c_str(), + level, + MG_Util::ConvertTextureInternalFormatToString( + MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)).c_str(), + width, height, border, + MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)).c_str(), + type, pixels); + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); + TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; + if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return; + if (!TextureImpl::ValidateTextureLevelNumber(level)) return; + if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, height, 1)) return; if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; if (!TextureImpl::ValidateTextureBorderNumber(border)) return; if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput( @@ -577,7 +686,7 @@ namespace MobileGL { const auto& pixelUnpackBufferObject = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); if (pixelUnpackBufferObject) { - MGLOG_D("TexImage2D_State: Using Pixel Unpack Buffer Object ID: %u", + MGLOG_D("%s: Using Pixel Unpack Buffer Object ID: %u", __func__, pixelUnpackBufferObject->GetExternalIndex()); originalPixels = reinterpret_cast(pixelUnpackBufferObject->GetDataReadOnly()->data()) + reinterpret_cast(pixels); @@ -591,7 +700,7 @@ namespace MobileGL { textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes}); if (!originalPixels) { - MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer"); + MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__); return; } @@ -1153,6 +1262,7 @@ namespace MobileGL { } void BindTexture_State(GLenum target, GLuint texture) { + // TODO: deal with condition where texture == 0 MGLOG_D("BindTexture_State called with target: 0x%X, texture: %u", target, texture); // ======================= Converting ================================ TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp index e9dc2e03..3d378124 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp @@ -134,8 +134,8 @@ namespace MobileGL::MG_Impl::GLImpl { return true; } - Bool ValidateTextureSizeRange(SizeT width, SizeT height) { - if (width < 0 || height < 0) { + Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth) { + if (width < 0 || height < 0 || depth < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", "ValidateTextureSizeRange", diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h index 03003d9f..9cae1b15 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h @@ -19,7 +19,7 @@ namespace MobileGL::MG_Impl::GLImpl { Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType); Bool ValidateTextureLevelNumber(Int level); Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height); - Bool ValidateTextureSizeRange(SizeT width, SizeT height); + Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth); Bool ValidateTextureInternalFormat(TextureInternalFormat format); Bool ValidateTextureBorderNumber(Int border); Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat, diff --git a/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp b/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp index 6458d09f..c8272fe5 100644 --- a/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp +++ b/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp @@ -148,13 +148,14 @@ namespace MobileGL::MG_Util::PixelStoreProcessor { if (textureInputFormat == TextureInputFormat::BGRA && targetInternalFormat == TextureInternalFormat::RGBA8) { 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(copyWidth), {TextureSwizzleParam::Green, TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha, TextureSwizzleParam::Red}); - MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); - } else - MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst)); +// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); + } +// else +// MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst)); layerSrc += inputStride; layerDst += static_cast(copyWidth) * pixelSize;