diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index 9c36ab3d..d3a3eff5 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -110,10 +110,32 @@ #define VK_USE_PLATFORM_WIN32_KHR #elif defined(__APPLE__) #define VK_USE_PLATFORM_METAL_EXT +#elif defined(__linux__) +#define VK_USE_PLATFORM_XLIB_KHR +typedef struct _XDisplay Display; +typedef unsigned long XID; +typedef XID Window; +typedef unsigned long VisualID; #else #warning "VK_USE_PLATFORM_*_KHR not defined for this platform!" #endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) +#pragma push_macro("Bool") +#pragma push_macro("None") +#pragma push_macro("Always") +#pragma push_macro("Status") +#pragma push_macro("LSBFirst") +#pragma push_macro("DestroyAll") +#endif #include +#if defined(VK_USE_PLATFORM_XLIB_KHR) +#pragma pop_macro("DestroyAll") +#pragma pop_macro("LSBFirst") +#pragma pop_macro("Status") +#pragma pop_macro("Always") +#pragma pop_macro("None") +#pragma pop_macro("Bool") +#endif #ifdef TRACY_ENABLE #include diff --git a/MobileGL/MG_Backend/BackendObject.cpp b/MobileGL/MG_Backend/BackendObject.cpp index 1574b33e..33840df7 100644 --- a/MobileGL/MG_Backend/BackendObject.cpp +++ b/MobileGL/MG_Backend/BackendObject.cpp @@ -164,6 +164,14 @@ namespace MobileGL::MG_Backend { return true; } + void BackendObject::ReleaseEGLResources() { + const std::lock_guard lock(m_eglStateMutex); + ResetEGLRuntimeState(); + m_eglDisplay = EGL_NO_DISPLAY; + m_eglDisplayInitialized = false; + m_windowHandle = {}; + } + void BackendObject::SetWindowHandle(const WindowHandle& handle) { const std::lock_guard lock(m_eglStateMutex); m_windowHandle = handle; diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 27ec3a10..10f80e2c 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -118,6 +118,7 @@ namespace MobileGL { virtual Bool CreateEGLPbufferSurface(EGLint width, EGLint height); virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw); + virtual void ReleaseEGLResources(); void SetWindowHandle(const WindowHandle& handle); diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 69583192..119ba42b 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -113,6 +113,12 @@ namespace MobileGL::MG_Backend::DirectGLES { return BackendObject::SwapEGLBuffers(dpy, draw); } + void BackendObject_DirectGLES::ReleaseEGLResources() { + const std::lock_guard lock(m_eglStateMutex); + DestroyEGLContext(); + BackendObject::ReleaseEGLResources(); + } + const RendererInfo& BackendObject_DirectGLES::GetRendererInfo() const { static RendererInfo RendererInfo = { .RendererName = "Espryt", // Renderer Name diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.h index 70b3b55a..c228233b 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.h @@ -23,6 +23,7 @@ namespace MobileGL::MG_Backend::DirectGLES { Bool CreateEGLWindowSurface(const WindowHandle& handle) override; Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override; Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override; + void ReleaseEGLResources() override; const RendererInfo& GetRendererInfo() const override; String GetBackendAPIVersionString() const override; diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 18362046..4a8b9238 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -1943,7 +1943,7 @@ namespace MobileGL::MG_Backend::DirectGLES { } using XOpenDisplayFn = Display* (*)(const char*); - using XGetWindowAttributesFn = Status (*)(Display*, Window, XWindowAttributes*); + using XGetWindowAttributesFn = int (*)(Display*, Window, XWindowAttributes*); using XVisualIDFromVisualFn = unsigned long (*)(Visual*); using XCloseDisplayFn = int (*)(Display*); diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index 1a2c4d2b..21e1279d 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -66,8 +66,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_E("DirectVulkan backend not initialized"); return false; } - if (handle.Backend != WindowBackend::Android || !handle.Handle) { - MGLOG_E("DirectVulkan backend only supports Android native windows"); + if (!handle.Handle || (handle.Backend != WindowBackend::Android && handle.Backend != WindowBackend::X11)) { + MGLOG_E("DirectVulkan backend only supports Android and X11 native windows"); return false; } @@ -106,6 +106,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { return BackendObject::SwapEGLBuffers(dpy, draw); } + void BackendObject_DirectVulkan::ReleaseEGLResources() { + const std::lock_guard lock(m_eglStateMutex); + pVulkanRenderer.reset(); + BackendObject::ReleaseEGLResources(); + } + const RendererInfo& BackendObject_DirectVulkan::GetRendererInfo() const { static RendererInfo RendererInfo = { .RendererName = "Magma", // Renderer Name @@ -118,7 +124,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { .Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, - E_GL_ARB_program_interface_query}, + E_GL_ARB_program_interface_query, E_GL_ARB_framebuffer_object, + E_GL_EXT_framebuffer_object, E_GL_ARB_depth_texture}, .IsCompatibilityProfile = false // Is Compatibility Profile }, .StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.h b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.h index 0379c50b..74e045fa 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.h +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.h @@ -23,6 +23,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool CreateEGLWindowSurface(const WindowHandle& handle) override; Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override; Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override; + void ReleaseEGLResources() override; const RendererInfo& GetRendererInfo() const override; String GetBackendAPIVersionString() const override; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp index 68da880d..c9b0b563 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp @@ -52,10 +52,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } VertexInputStateBuilder builder; - UnorderedMap bindingByBufferKey; - UnorderedMap strideByBufferKey; - UnorderedMap inputRateByBufferKey; Vector bindingBufferKeys; + Vector bindingBaseOffsets; for (Uint32 location = 0; location < MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS; ++location) { const auto& attr = vao.GetAttribute(location); @@ -84,29 +82,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { (attr.Divisor == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; const SizeT bufferKey = reinterpret_cast(attr.Buffer.get()); - Uint32 binding = 0; - auto itBinding = bindingByBufferKey.find(bufferKey); - if (itBinding == bindingByBufferKey.end()) { - binding = static_cast(bindingByBufferKey.size()); - bindingByBufferKey.emplace(bufferKey, binding); - strideByBufferKey.emplace(bufferKey, stride); - inputRateByBufferKey.emplace(bufferKey, inputRate); - bindingBufferKeys.push_back(bufferKey); - builder.AddBinding(binding, stride, inputRate); - } else { - binding = itBinding->second; - if (strideByBufferKey[bufferKey] != stride) { - MGLOG_D("Skipping vertex attribute at location %u: stride mismatch (%u vs %u) on same buffer", - location, stride, strideByBufferKey[bufferKey]); - continue; - } - if (inputRateByBufferKey[bufferKey] != inputRate) { - MGLOG_D("Skipping vertex attribute at location %u: input-rate mismatch on same buffer", location); - continue; - } - } - - builder.AddAttribute(location, binding, vkFormat, static_cast(attr.Offset)); + const Uint32 binding = static_cast(bindingBufferKeys.size()); + bindingBufferKeys.push_back(bufferKey); + bindingBaseOffsets.push_back(attr.Offset); + builder.AddBinding(binding, stride, inputRate); + builder.AddAttribute(location, binding, vkFormat, 0); } const auto& state = builder.Build(); @@ -116,6 +96,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { entry.bindings = builder.GetBindings(); entry.attributes = builder.GetAttributes(); entry.bindingBufferKeys = std::move(bindingBufferKeys); + entry.bindingBaseOffsets = std::move(bindingBaseOffsets); entry.state = state; entry.state.pVertexBindingDescriptions = entry.bindings.empty() ? nullptr : entry.bindings.data(); entry.state.pVertexAttributeDescriptions = entry.attributes.empty() ? nullptr : entry.attributes.data(); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h index 2b79a4f8..b42d6c9a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.h @@ -24,6 +24,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { Vector bindings; Vector attributes; Vector bindingBufferKeys; + Vector bindingBaseOffsets; VkPipelineVertexInputStateCreateInfo state{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 6068ec46..7e35920a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -1331,6 +1331,22 @@ void main() { m_surface = VK_NULL_HANDLE; } +#if defined(VK_USE_PLATFORM_XLIB_KHR) + if (m_platformDisplay != nullptr) { + using XCloseDisplayFn = int (*)(Display*); + auto* closeDisplay = reinterpret_cast(m_platformCloseDisplay); + if (closeDisplay) { + closeDisplay(static_cast(m_platformDisplay)); + } + m_platformDisplay = nullptr; + } + m_platformCloseDisplay = nullptr; + if (m_platformLibrary != nullptr) { + dlclose(m_platformLibrary); + m_platformLibrary = nullptr; + } +#endif + if (m_debugMessenger != VK_NULL_HANDLE) { DestroyDebugMessenger(); m_debugMessenger = VK_NULL_HANDLE; @@ -1413,7 +1429,12 @@ void main() { } } vkBuffers[binding] = slice.buffer; - vkOffsets[binding] = slice.offset; + const SizeT baseOffset = + binding < vertexInputState.bindingBaseOffsets.size() ? vertexInputState.bindingBaseOffsets[binding] : 0; + MOBILEGL_ASSERT(baseOffset <= sourceSize, + "UploadAndBindVertexStreams skipped: binding %zu base offset %zu exceeds buffer size %zu", + binding, baseOffset, sourceSize); + vkOffsets[binding] = slice.offset + static_cast(baseOffset); } SizeT syntheticBinding = vertexInputState.bindings.size(); @@ -3515,8 +3536,15 @@ void main() { resource = m_textureManager->SyncTextureAndGetDescriptor(*texture); MOBILEGL_ASSERT(resource != nullptr && resource->image != VK_NULL_HANDLE, "GenerateMipmap failed to resync the backend texture after allocating mip storage."); - MOBILEGL_ASSERT(resource->layout != VK_IMAGE_LAYOUT_UNDEFINED, - "GenerateMipmap requires initialized base-level image data."); + if (resource->layout == VK_IMAGE_LAYOUT_UNDEFINED) { + const VkImageLayout finalLayout = ResolveGenerateMipmapFinalLayout(resource->aspect); + Bool transitioned = VkTextureManager::TransitionImageLayout( + frame.commandBuffer, resource->image, resource->layout, finalLayout, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, VK_ACCESS_SHADER_READ_BIT, resource->aspect, 0, resource->mipLevels, resource->arrayLayers); + MOBILEGL_ASSERT(transitioned, "GenerateMipmap: failed to transition uninitialized mip chain"); + return; + } const IntVec3 storageBaseTexelSize = { static_cast(resource->extent.width), @@ -3801,6 +3829,8 @@ void main() { VK_KHR_WIN32_SURFACE_EXTENSION_NAME #elif defined VK_USE_PLATFORM_METAL_EXT VK_EXT_METAL_SURFACE_EXTENSION_NAME +#elif defined VK_USE_PLATFORM_XLIB_KHR + VK_KHR_XLIB_SURFACE_EXTENSION_NAME #else #warning "VulkanContext::CreateInstance: VK_KHR_*_surface extension not defined on this platform" #endif @@ -4195,6 +4225,31 @@ void main() { VkMetalSurfaceCreateInfoEXT sci{VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT}; sci.pLayer = reinterpret_cast(m_window); VK_VERIFY(vkCreateMetalSurfaceEXT(m_instance, &sci, nullptr, &m_surface), "vkCreateMetalSurfaceEXT failed"); +#elif defined VK_USE_PLATFORM_XLIB_KHR + MOBILEGL_ASSERT(m_window, "X11 Window is null"); + + void* x11Lib = dlopen("libX11.so.6", RTLD_LOCAL | RTLD_NOW); + if (!x11Lib) { + x11Lib = dlopen("libX11.so", RTLD_LOCAL | RTLD_NOW); + } + MOBILEGL_ASSERT(x11Lib != nullptr, "Failed to open libX11 while creating Vulkan Xlib surface"); + using XOpenDisplayFn = Display* (*)(const char*); + using XCloseDisplayFn = int (*)(Display*); + auto* xOpenDisplay = reinterpret_cast(dlsym(x11Lib, "XOpenDisplay")); + auto* xCloseDisplay = reinterpret_cast(dlsym(x11Lib, "XCloseDisplay")); + MOBILEGL_ASSERT(xOpenDisplay != nullptr && xCloseDisplay != nullptr, + "Failed to resolve XOpenDisplay/XCloseDisplay while creating Vulkan Xlib surface"); + + auto* display = xOpenDisplay(std::getenv("DISPLAY")); + MOBILEGL_ASSERT(display != nullptr, "XOpenDisplay failed while creating Vulkan Xlib surface"); + m_platformDisplay = display; + m_platformLibrary = x11Lib; + m_platformCloseDisplay = reinterpret_cast(xCloseDisplay); + + VkXlibSurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR}; + sci.dpy = display; + sci.window = static_cast(m_window); + VK_VERIFY(vkCreateXlibSurfaceKHR(m_instance, &sci, nullptr, &m_surface), "vkCreateXlibSurfaceKHR failed"); #else // #warning "VulkanRenderer::Initialize called on a platform which is not supported yet" MGLOG_W("VulkanRenderer::Initialize called on a platform which is not supported yet"); // TODO: support more diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index efb2443a..7bbe39d0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -174,6 +174,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { void QueueClearBufferPayload(GLenum buffer, GLint drawbuffer, const ClearAttachmentPayload& clearPayload); NativeWindowType m_window = 0; + void* m_platformDisplay = nullptr; + void* m_platformLibrary = nullptr; + void* m_platformCloseDisplay = nullptr; VulkanRendererConfig m_config; // Vulkan objects diff --git a/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp b/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp index 1fc03383..4f689eda 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLImpl.cpp @@ -244,7 +244,13 @@ namespace MobileGL::MG_Impl::EGLImpl { if (!state) { return EGL_FALSE; } - return state->TerminateDisplay(dpy) ? EGL_TRUE : EGL_FALSE; + if (!state->TerminateDisplay(dpy)) { + return EGL_FALSE; + } + if (auto* backendObject = MG_Backend::pActiveBackendObject.get()) { + backendObject->ReleaseEGLResources(); + } + return EGL_TRUE; } EGLBoolean ReleaseThread() { diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 4293d50a..1970a1f2 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -29,6 +29,7 @@ namespace MobileGL::MG_Impl::GLImpl { static SharedPtr nullTextureObject; + static UnorderedMap g_autoGenerateMipmapByTextureId; const SharedPtr& GetTextureObjectByTarget( TextureUploadTarget textureUploadTarget, TextureTarget textureTarget) { @@ -50,6 +51,18 @@ namespace MobileGL::MG_Impl::GLImpl { MG_Backend::gBackendFunctionsTable.GL.GenerateMipmap(target); } + void MaybeAutoGenerateMipmap(GLenum target, const SharedPtr& textureObject, + Bool isProxy, GLint level) { + if (isProxy || level != 0 || !textureObject) { + return; + } + const auto it = g_autoGenerateMipmapByTextureId.find(textureObject->GetExternalIndex()); + if (it == g_autoGenerateMipmapByTextureId.end() || !it->second) { + return; + } + GenerateMipmap_Backend(target); + } + void TexSubImage3D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { // TODO: implement @@ -169,6 +182,7 @@ namespace MobileGL::MG_Impl::GLImpl { MGLOG_D("%s: mark mip %d as dirty", __func__, level); textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, true); + MaybeAutoGenerateMipmap(target, textureObject, false, level); } void TexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, @@ -240,6 +254,9 @@ namespace MobileGL::MG_Impl::GLImpl { case GL_TEXTURE_LOD_BIAS: textureObject->GetSamplerObject()->SetLodBias(param); break; + case GL_GENERATE_MIPMAP: + g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != 0.0f); + break; case GL_TEXTURE_SWIZZLE_RGBA: // Not supported in this function case GL_TEXTURE_BORDER_COLOR: @@ -314,6 +331,9 @@ namespace MobileGL::MG_Impl::GLImpl { case GL_TEXTURE_LOD_BIAS: textureObject->GetSamplerObject()->SetLodBias((GLfloat)param); break; + case GL_GENERATE_MIPMAP: + g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != GL_FALSE); + break; case GL_TEXTURE_SWIZZLE_RGBA: // Not supported in this function case GL_TEXTURE_BORDER_COLOR: @@ -546,6 +566,10 @@ namespace MobileGL::MG_Impl::GLImpl { if (!TextureImpl::ValidateTextureObject(textureObject)) return; // ======================= Processing ================================ + if (internalformat == GL_ALPHA || format == GL_ALPHA) { + textureObject->SetSwizzleParamRGBA({TextureSwizzleParam::Zero, TextureSwizzleParam::Zero, + TextureSwizzleParam::Zero, TextureSwizzleParam::Red}); + } SizeT imageSize = 0; const SizeT inputBpp = MG_Util::GetInputBytesPerPixel(textureInputFormat, texturePixelDataType); @@ -655,6 +679,10 @@ namespace MobileGL::MG_Impl::GLImpl { if (!TextureImpl::ValidateTextureObject(textureObject)) return; // ======================= Processing ================================ + if (internalformat == GL_ALPHA || format == GL_ALPHA) { + textureObject->SetSwizzleParamRGBA({TextureSwizzleParam::Zero, TextureSwizzleParam::Zero, + TextureSwizzleParam::Zero, TextureSwizzleParam::Red}); + } SizeT imageSize = 0; const SizeT inputBpp = MG_Util::GetInputBytesPerPixel(textureInputFormat, texturePixelDataType); @@ -719,6 +747,7 @@ namespace MobileGL::MG_Impl::GLImpl { MGLOG_D("%s: mark mip %d as dirty", __func__, level); textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, true); + MaybeAutoGenerateMipmap(target, textureObject, isProxy, level); } void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, diff --git a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp index e3ce180c..0225d6ef 100644 --- a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp +++ b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp @@ -48,6 +48,7 @@ namespace MobileGL { TextureInputFormat ConvertGLEnumToTextureInputFormat(GLenum format) { switch (format) { + case GL_ALPHA: case GL_RED: return TextureInputFormat::Red; case GL_RG: @@ -225,6 +226,7 @@ namespace MobileGL { return TextureInternalFormat::DepthComponent; case GL_DEPTH_STENCIL: return TextureInternalFormat::DepthStencil; + case GL_ALPHA: case GL_RED: return TextureInternalFormat::Red; case GL_RG: