From 5cdd3a0db7244cae91138490616f26e7ffc2432c Mon Sep 17 00:00:00 2001 From: Laura Hermanns Date: Wed, 3 Jul 2024 12:54:45 -0400 Subject: [PATCH] [SwapChain] Make default surface visible at creation time with an auto-generated title when creating a swap-chain. The rationale of making the surface invisible when creating a swap-chain was to prevent the window to be visible before it has a valid title. The client programmer was responsible for changing the title and then making the window (or canvas on mobile) visible. This is not an issue when a custom surface is passed into the CreateSwapChain() function, but the default surface never had an initial title. With this change, the default surface is always visible at creation time and an auto-generated title is used to initialzie the window/canvas. If this behavior is undesired, the client programmer can continue to use a custom surface but the default surface is supposed to make things easier. --- include/LLGL/SwapChain.h | 14 ++++++++++ .../Renderer/Direct3D11/D3D11SwapChain.cpp | 2 +- .../Renderer/Direct3D12/D3D12SwapChain.cpp | 2 +- sources/Renderer/Metal/MTRenderSystem.mm | 2 +- sources/Renderer/Metal/MTSwapChain.h | 3 +- sources/Renderer/Metal/MTSwapChain.mm | 5 ++-- sources/Renderer/Null/NullRenderSystem.cpp | 6 ++-- sources/Renderer/Null/NullSwapChain.cpp | 8 ++++-- sources/Renderer/Null/NullSwapChain.h | 6 +++- sources/Renderer/OpenGL/GLRenderSystem.cpp | 7 +++++ sources/Renderer/OpenGL/GLSwapChain.cpp | 28 +++++++++++++++++-- sources/Renderer/OpenGL/GLSwapChain.h | 3 ++ sources/Renderer/SwapChain.cpp | 28 ++++++++++++++++++- sources/Renderer/Vulkan/VKRenderSystem.cpp | 2 +- sources/Renderer/Vulkan/VKSwapChain.cpp | 5 ++-- sources/Renderer/Vulkan/VKSwapChain.h | 3 +- 16 files changed, 104 insertions(+), 20 deletions(-) diff --git a/include/LLGL/SwapChain.h b/include/LLGL/SwapChain.h index d3fcfcb46f..d2fdae6498 100644 --- a/include/LLGL/SwapChain.h +++ b/include/LLGL/SwapChain.h @@ -191,16 +191,19 @@ class LLGL_EXPORT SwapChain : public RenderTarget \brief Sets the swap-chain surface or creates one if 'surface' is null, and switches to fullscreen mode if enabled. \param[in] surface Optional shared pointer to a surface which will be used as main render target. If this is null, a new surface is created for this swap-chain. + \param[in] title Specifies the surface title. This is only used if \c surface is null. \param[in] size Specifies the surface content size. This is only used if \c surface is null. Otherwise, the size is determined by the content size of the specified surface (i.e. with the Surface::GetContentSize function). \param[in] fullscreen Specifies whether to put the surface into fullscreen mode. \param[in] windowContext Optional pointer to a NativeHandle structure. This is only used for desktop platforms. + \param[in] windowContextSize Size (in bytes) of the native handle \c windowContext points to. This must be equal to \c sizeof(LLGL::NativeHandle). \see WindowDescriptor::windowContext \see Surface::GetContentSize \see SwitchFullscreenMode */ void SetOrCreateSurface( const std::shared_ptr& surface, + const UTF8String& title, const Extent2D& size, bool fullscreen, const void* windowContext = nullptr, @@ -225,6 +228,17 @@ class LLGL_EXPORT SwapChain : public RenderTarget */ bool ResetDisplayFullscreenMode(); + protected: + + /** + \brief Builds a default title for the swap-chain surface when no custom surface is specified. + \remarks This has the format \c "LLGL SURFACE NUMBER ( RENDERER )": + - \c SURFACE is either "Window" on desktop platforms or "Canvas" on mobile platforms. + - \c NUMBER denotes the number of the swap-chain starting at 1. + - \c RENDERER denotes the renderer name (see RendererInfo::rendererName). + */ + static UTF8String BuildDefaultSurfaceTitle(const RendererInfo& info); + private: void StoreSurfacePosition(); diff --git a/sources/Renderer/Direct3D11/D3D11SwapChain.cpp b/sources/Renderer/Direct3D11/D3D11SwapChain.cpp index fc3d99572d..2107c6d9a3 100644 --- a/sources/Renderer/Direct3D11/D3D11SwapChain.cpp +++ b/sources/Renderer/Direct3D11/D3D11SwapChain.cpp @@ -35,7 +35,7 @@ D3D11SwapChain::D3D11SwapChain( depthBufferLocator_ { ResourceType::Texture, BindFlags::DepthStencilAttachment } { /* Setup surface for the swap-chain */ - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, nullptr); + SetOrCreateSurface(surface, SwapChain::BuildDefaultSurfaceTitle(renderSystem.GetRendererInfo()), desc.resolution, desc.fullscreen); /* Create D3D objects */ CreateSwapChain(factory, GetResolution(), desc.samples, desc.swapBuffers); diff --git a/sources/Renderer/Direct3D12/D3D12SwapChain.cpp b/sources/Renderer/Direct3D12/D3D12SwapChain.cpp index 789a612870..8b9934654c 100644 --- a/sources/Renderer/Direct3D12/D3D12SwapChain.cpp +++ b/sources/Renderer/Direct3D12/D3D12SwapChain.cpp @@ -44,7 +44,7 @@ D3D12SwapChain::D3D12SwapChain( commandQueue_ = LLGL_CAST(D3D12CommandQueue*, renderSystem_.GetCommandQueue()); /* Setup surface for the swap-chain */ - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, nullptr); + SetOrCreateSurface(surface, SwapChain::BuildDefaultSurfaceTitle(renderSystem.GetRendererInfo()), desc.resolution, desc.fullscreen); /* Create device resources and window dependent resource */ CreateDescriptorHeaps(renderSystem.GetDevice(), desc.samples); diff --git a/sources/Renderer/Metal/MTRenderSystem.mm b/sources/Renderer/Metal/MTRenderSystem.mm index da82543f57..28e64fdc5f 100644 --- a/sources/Renderer/Metal/MTRenderSystem.mm +++ b/sources/Renderer/Metal/MTRenderSystem.mm @@ -49,7 +49,7 @@ SwapChain* MTRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr& surface) { - return swapChains_.emplace(device_, swapChainDesc, surface); + return swapChains_.emplace(device_, swapChainDesc, surface, GetRendererInfo()); } void MTRenderSystem::Release(SwapChain& swapChain) diff --git a/sources/Renderer/Metal/MTSwapChain.h b/sources/Renderer/Metal/MTSwapChain.h index 8c8ea48833..e23b594a6f 100644 --- a/sources/Renderer/Metal/MTSwapChain.h +++ b/sources/Renderer/Metal/MTSwapChain.h @@ -36,7 +36,8 @@ class MTSwapChain final : public SwapChain MTSwapChain( id device, const SwapChainDescriptor& desc, - const std::shared_ptr& surface + const std::shared_ptr& surface, + const RendererInfo& rendererInfo ); void Present() override; diff --git a/sources/Renderer/Metal/MTSwapChain.mm b/sources/Renderer/Metal/MTSwapChain.mm index 97f323c359..a71075d921 100644 --- a/sources/Renderer/Metal/MTSwapChain.mm +++ b/sources/Renderer/Metal/MTSwapChain.mm @@ -52,13 +52,14 @@ - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size MTSwapChain::MTSwapChain( id device, const SwapChainDescriptor& desc, - const std::shared_ptr& surface) + const std::shared_ptr& surface, + const RendererInfo& rendererInfo) : SwapChain { desc }, renderPass_ { device, desc } { /* Initialize surface for MetalKit view */ - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, nullptr); + SetOrCreateSurface(surface, SwapChain::BuildDefaultSurfaceTitle(rendererInfo), desc.resolution, desc.fullscreen); /* Allocate and initialize MetalKit view */ view_ = AllocMTKViewAndInitWithSurface(device, GetSurface()); diff --git a/sources/Renderer/Null/NullRenderSystem.cpp b/sources/Renderer/Null/NullRenderSystem.cpp index 5d4bb2743f..c21c8eb1fb 100644 --- a/sources/Renderer/Null/NullRenderSystem.cpp +++ b/sources/Renderer/Null/NullRenderSystem.cpp @@ -108,7 +108,7 @@ static RenderingCapabilities GetNullRenderingCaps() return caps; } -static RendererInfo GetNullRenderInfo() +static RendererInfo GetNullRendererInfo() { RendererInfo info; info.rendererName = "Null"; @@ -122,7 +122,7 @@ NullRenderSystem::NullRenderSystem(const RenderSystemDescriptor& renderSystemDes desc_ { renderSystemDesc }, commandQueue_ { MakeUnique() } { - SetRendererInfo(GetNullRenderInfo()); + SetRendererInfo(GetNullRendererInfo()); SetRenderingCaps(GetNullRenderingCaps()); } @@ -130,7 +130,7 @@ NullRenderSystem::NullRenderSystem(const RenderSystemDescriptor& renderSystemDes SwapChain* NullRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr& surface) { - return swapChains_.emplace(swapChainDesc, surface); + return swapChains_.emplace(swapChainDesc, surface, GetNullRendererInfo()); } void NullRenderSystem::Release(SwapChain& swapChain) diff --git a/sources/Renderer/Null/NullSwapChain.cpp b/sources/Renderer/Null/NullSwapChain.cpp index 2ea222119a..baadf4062d 100644 --- a/sources/Renderer/Null/NullSwapChain.cpp +++ b/sources/Renderer/Null/NullSwapChain.cpp @@ -35,13 +35,17 @@ static Format ChooseDepthStencilFormat(int depthBits, int stencilBits) } } -NullSwapChain::NullSwapChain(const SwapChainDescriptor& desc, const std::shared_ptr& surface) : +NullSwapChain::NullSwapChain( + const SwapChainDescriptor& desc, + const std::shared_ptr& surface, + const RendererInfo& rendererInfo) +: SwapChain { desc }, samples_ { desc.samples }, colorFormat_ { ChooseColorFormat(desc.colorBits) }, depthStencilFormat_ { ChooseDepthStencilFormat(desc.depthBits, desc.stencilBits) } { - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, nullptr); + SetOrCreateSurface(surface, SwapChain::BuildDefaultSurfaceTitle(rendererInfo), desc.resolution, desc.fullscreen); if (desc.debugName != nullptr) SetDebugName(desc.debugName); } diff --git a/sources/Renderer/Null/NullSwapChain.h b/sources/Renderer/Null/NullSwapChain.h index 6973fe61eb..468c80c911 100644 --- a/sources/Renderer/Null/NullSwapChain.h +++ b/sources/Renderer/Null/NullSwapChain.h @@ -22,7 +22,11 @@ class NullSwapChain final : public SwapChain public: - NullSwapChain(const SwapChainDescriptor& desc, const std::shared_ptr& surface); + NullSwapChain( + const SwapChainDescriptor& desc, + const std::shared_ptr& surface, + const RendererInfo& rendererInfo + ); public: diff --git a/sources/Renderer/OpenGL/GLRenderSystem.cpp b/sources/Renderer/OpenGL/GLRenderSystem.cpp index cf8b05d05f..58eeb1d9e7 100644 --- a/sources/Renderer/OpenGL/GLRenderSystem.cpp +++ b/sources/Renderer/OpenGL/GLRenderSystem.cpp @@ -77,6 +77,13 @@ SwapChain* GLRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainD if (isFirstSwapChain) CreateGLContextDependentDevices(swapChainGL->GetStateManager()); + /* + If no surface was specified, set a default title to the automatically created one now + as we need a valid GL context to query the renderer information for the default title. + */ + if (!surface) + swapChainGL->BuildAndSetDefaultSurfaceTitle(GetRendererInfo()); + return swapChainGL; } diff --git a/sources/Renderer/OpenGL/GLSwapChain.cpp b/sources/Renderer/OpenGL/GLSwapChain.cpp index a2d8507371..db9e75f3a2 100644 --- a/sources/Renderer/OpenGL/GLSwapChain.cpp +++ b/sources/Renderer/OpenGL/GLSwapChain.cpp @@ -8,10 +8,17 @@ #include "GLSwapChain.h" #include "../TextureUtils.h" #include "Platform/GLContextManager.h" +#include #include +#ifdef LLGL_MOBILE_PLATFORM +# include +#else +# include +#endif + #ifdef LLGL_OS_LINUX -#include +# include #endif @@ -38,12 +45,12 @@ GLSwapChain::GLSwapChain( /* Set up surface for the swap-chain and pass native context handle */ NativeHandle windowContext = {}; ChooseGLXVisualAndGetX11WindowContext(pixelFormat, windowContext); - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, &windowContext, sizeof(windowContext)); + SetOrCreateSurface(surface, UTF8String{}, desc.resolution, desc.fullscreen, &windowContext, sizeof(windowContext)); #else /* Setup surface for the swap-chain */ - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen); + SetOrCreateSurface(surface, UTF8String{}, desc.resolution, desc.fullscreen); #endif @@ -115,6 +122,21 @@ bool GLSwapChain::MakeCurrent(GLSwapChain* swapChain) return GLSwapChainContext::MakeCurrent(nullptr); } +void GLSwapChain::BuildAndSetDefaultSurfaceTitle(const RendererInfo& info) +{ + #ifdef LLGL_MOBILE_PLATFORM + + /* Set Canvas title for mobile platforms */ + CastTo(GetSurface()).SetTitle(SwapChain::BuildDefaultSurfaceTitle(info)); + + #else // LLGL_MOBILE_PLATFORM + + /* Set Window title for desktop platforms */ + CastTo(GetSurface()).SetTitle(SwapChain::BuildDefaultSurfaceTitle(info)); + + #endif // /LLGL_MOBILE_PLATFORM +} + /* * ======= Private: ======= diff --git a/sources/Renderer/OpenGL/GLSwapChain.h b/sources/Renderer/OpenGL/GLSwapChain.h index 8c8eade311..dcdd7e8a3f 100644 --- a/sources/Renderer/OpenGL/GLSwapChain.h +++ b/sources/Renderer/OpenGL/GLSwapChain.h @@ -60,6 +60,9 @@ class GLSwapChain final : public SwapChain // Makes the swap-chain's GL context current and updates the renger-target height in the linked GL state manager. static bool MakeCurrent(GLSwapChain* swapChain); + // Make this function public for GLSwapChain as the default title has to be set outside its constructor due to GL context management. + void BuildAndSetDefaultSurfaceTitle(const RendererInfo& info); + // Returns the state manager of the swap chain's GL context. inline GLStateManager& GetStateManager() { diff --git a/sources/Renderer/SwapChain.cpp b/sources/Renderer/SwapChain.cpp index 266953420d..6db73e7147 100644 --- a/sources/Renderer/SwapChain.cpp +++ b/sources/Renderer/SwapChain.cpp @@ -146,6 +146,7 @@ Surface& SwapChain::GetSurface() const void SwapChain::SetOrCreateSurface( const std::shared_ptr& surface, + const UTF8String& title, const Extent2D& size, bool fullscreen, const void* windowContext, @@ -163,6 +164,7 @@ void SwapChain::SetOrCreateSurface( /* Create new canvas for this swap-chain */ CanvasDescriptor canvasDesc; { + canvasDesc.title = title; canvasDesc.flags = (fullscreen ? CanvasFlags::Borderless : 0); } pimpl_->surface = Canvas::Create(canvasDesc); @@ -172,8 +174,9 @@ void SwapChain::SetOrCreateSurface( /* Create new window for this swap-chain */ WindowDescriptor windowDesc; { + windowDesc.title = title; windowDesc.size = size; - windowDesc.flags = (fullscreen ? WindowFlags::Borderless : WindowFlags::Centered) | WindowFlags::DisableSizeScaling; + windowDesc.flags = WindowFlags::Visible | WindowFlags::DisableSizeScaling | (fullscreen ? WindowFlags::Borderless : WindowFlags::Centered); windowDesc.windowContext = windowContext; windowDesc.windowContextSize = windowContextSize; } @@ -224,6 +227,29 @@ bool SwapChain::ResetDisplayFullscreenMode() return false; } +UTF8String SwapChain::BuildDefaultSurfaceTitle(const RendererInfo& info) +{ + UTF8String title = "LLGL"; + + /* Append surface typename */ + #ifdef LLGL_MOBILE_PLATFORM + title += " Canvas "; + #else + title += " Window "; + #endif + + /* Append swap-chain number */ + static int swapChainCounter; + title += UTF8String{ std::to_string(++swapChainCounter) }; + + /* Append renderer name */ + title += " ( "; + title += UTF8String{ info.rendererName }; + title += " )"; + + return title; +} + /* * ======= Private: ======= diff --git a/sources/Renderer/Vulkan/VKRenderSystem.cpp b/sources/Renderer/Vulkan/VKRenderSystem.cpp index ff920f1ee1..4adad273fc 100644 --- a/sources/Renderer/Vulkan/VKRenderSystem.cpp +++ b/sources/Renderer/Vulkan/VKRenderSystem.cpp @@ -89,7 +89,7 @@ VKRenderSystem::~VKRenderSystem() SwapChain* VKRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr& surface) { - return swapChains_.emplace(instance_, physicalDevice_, device_, *deviceMemoryMngr_, swapChainDesc, surface); + return swapChains_.emplace(instance_, physicalDevice_, device_, *deviceMemoryMngr_, swapChainDesc, surface, GetRendererInfo()); } void VKRenderSystem::Release(SwapChain& swapChain) diff --git a/sources/Renderer/Vulkan/VKSwapChain.cpp b/sources/Renderer/Vulkan/VKSwapChain.cpp index ad1ecf77b8..4d98c5d7c7 100644 --- a/sources/Renderer/Vulkan/VKSwapChain.cpp +++ b/sources/Renderer/Vulkan/VKSwapChain.cpp @@ -54,7 +54,8 @@ VKSwapChain::VKSwapChain( VkDevice device, VKDeviceMemoryManager& deviceMemoryMngr, const SwapChainDescriptor& desc, - const std::shared_ptr& surface) + const std::shared_ptr& surface, + const RendererInfo& rendererInfo) : SwapChain { desc }, instance_ { instance }, @@ -84,7 +85,7 @@ VKSwapChain::VKSwapChain( NullVkFence(device_), NullVkFence(device_) } { - SetOrCreateSurface(surface, desc.resolution, desc.fullscreen, nullptr); + SetOrCreateSurface(surface, SwapChain::BuildDefaultSurfaceTitle(rendererInfo), desc.resolution, desc.fullscreen); CreatePresentSemaphoresAndFences(); CreateGpuSurface(); diff --git a/sources/Renderer/Vulkan/VKSwapChain.h b/sources/Renderer/Vulkan/VKSwapChain.h index afcb2357fb..52a25bcd4e 100644 --- a/sources/Renderer/Vulkan/VKSwapChain.h +++ b/sources/Renderer/Vulkan/VKSwapChain.h @@ -40,7 +40,8 @@ class VKSwapChain final : public SwapChain VkDevice device, VKDeviceMemoryManager& deviceMemoryMngr, const SwapChainDescriptor& desc, - const std::shared_ptr& surface + const std::shared_ptr& surface, + const RendererInfo& rendererInfo ); void Present() override;