Skip to content

Commit

Permalink
[SwapChain] Make default surface visible at creation time with an aut…
Browse files Browse the repository at this point in the history
…o-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.
  • Loading branch information
LukasBanana committed Jul 3, 2024
1 parent 12b250d commit 5cdd3a0
Show file tree
Hide file tree
Showing 16 changed files with 104 additions and 20 deletions.
14 changes: 14 additions & 0 deletions include/LLGL/SwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>& surface,
const UTF8String& title,
const Extent2D& size,
bool fullscreen,
const void* windowContext = nullptr,
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion sources/Renderer/Direct3D11/D3D11SwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion sources/Renderer/Direct3D12/D3D12SwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion sources/Renderer/Metal/MTRenderSystem.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

SwapChain* MTRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr<Surface>& surface)
{
return swapChains_.emplace<MTSwapChain>(device_, swapChainDesc, surface);
return swapChains_.emplace<MTSwapChain>(device_, swapChainDesc, surface, GetRendererInfo());
}

void MTRenderSystem::Release(SwapChain& swapChain)
Expand Down
3 changes: 2 additions & 1 deletion sources/Renderer/Metal/MTSwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class MTSwapChain final : public SwapChain
MTSwapChain(
id<MTLDevice> device,
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& surface
const std::shared_ptr<Surface>& surface,
const RendererInfo& rendererInfo
);

void Present() override;
Expand Down
5 changes: 3 additions & 2 deletions sources/Renderer/Metal/MTSwapChain.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,14 @@ - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
MTSwapChain::MTSwapChain(
id<MTLDevice> device,
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& surface)
const std::shared_ptr<Surface>& 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());
Expand Down
6 changes: 3 additions & 3 deletions sources/Renderer/Null/NullRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static RenderingCapabilities GetNullRenderingCaps()
return caps;
}

static RendererInfo GetNullRenderInfo()
static RendererInfo GetNullRendererInfo()
{
RendererInfo info;
info.rendererName = "Null";
Expand All @@ -122,15 +122,15 @@ NullRenderSystem::NullRenderSystem(const RenderSystemDescriptor& renderSystemDes
desc_ { renderSystemDesc },
commandQueue_ { MakeUnique<NullCommandQueue>() }
{
SetRendererInfo(GetNullRenderInfo());
SetRendererInfo(GetNullRendererInfo());
SetRenderingCaps(GetNullRenderingCaps());
}

/* ----- Swap-chain ----- */

SwapChain* NullRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr<Surface>& surface)
{
return swapChains_.emplace<NullSwapChain>(swapChainDesc, surface);
return swapChains_.emplace<NullSwapChain>(swapChainDesc, surface, GetNullRendererInfo());
}

void NullRenderSystem::Release(SwapChain& swapChain)
Expand Down
8 changes: 6 additions & 2 deletions sources/Renderer/Null/NullSwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ static Format ChooseDepthStencilFormat(int depthBits, int stencilBits)
}
}

NullSwapChain::NullSwapChain(const SwapChainDescriptor& desc, const std::shared_ptr<Surface>& surface) :
NullSwapChain::NullSwapChain(
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& 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);
}
Expand Down
6 changes: 5 additions & 1 deletion sources/Renderer/Null/NullSwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class NullSwapChain final : public SwapChain

public:

NullSwapChain(const SwapChainDescriptor& desc, const std::shared_ptr<Surface>& surface);
NullSwapChain(
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& surface,
const RendererInfo& rendererInfo
);

public:

Expand Down
7 changes: 7 additions & 0 deletions sources/Renderer/OpenGL/GLRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
28 changes: 25 additions & 3 deletions sources/Renderer/OpenGL/GLSwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
#include "GLSwapChain.h"
#include "../TextureUtils.h"
#include "Platform/GLContextManager.h"
#include <LLGL/TypeInfo.h>
#include <LLGL/Platform/Platform.h>

#ifdef LLGL_MOBILE_PLATFORM
# include <LLGL/Canvas.h>
#else
# include <LLGL/Window.h>
#endif

#ifdef LLGL_OS_LINUX
#include <LLGL/Platform/NativeHandle.h>
# include <LLGL/Platform/NativeHandle.h>
#endif


Expand All @@ -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

Expand Down Expand Up @@ -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<Canvas>(GetSurface()).SetTitle(SwapChain::BuildDefaultSurfaceTitle(info));

#else // LLGL_MOBILE_PLATFORM

/* Set Window title for desktop platforms */
CastTo<Window>(GetSurface()).SetTitle(SwapChain::BuildDefaultSurfaceTitle(info));

#endif // /LLGL_MOBILE_PLATFORM
}


/*
* ======= Private: =======
Expand Down
3 changes: 3 additions & 0 deletions sources/Renderer/OpenGL/GLSwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
28 changes: 27 additions & 1 deletion sources/Renderer/SwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ Surface& SwapChain::GetSurface() const

void SwapChain::SetOrCreateSurface(
const std::shared_ptr<Surface>& surface,
const UTF8String& title,
const Extent2D& size,
bool fullscreen,
const void* windowContext,
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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: =======
Expand Down
2 changes: 1 addition & 1 deletion sources/Renderer/Vulkan/VKRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ VKRenderSystem::~VKRenderSystem()

SwapChain* VKRenderSystem::CreateSwapChain(const SwapChainDescriptor& swapChainDesc, const std::shared_ptr<Surface>& surface)
{
return swapChains_.emplace<VKSwapChain>(instance_, physicalDevice_, device_, *deviceMemoryMngr_, swapChainDesc, surface);
return swapChains_.emplace<VKSwapChain>(instance_, physicalDevice_, device_, *deviceMemoryMngr_, swapChainDesc, surface, GetRendererInfo());
}

void VKRenderSystem::Release(SwapChain& swapChain)
Expand Down
5 changes: 3 additions & 2 deletions sources/Renderer/Vulkan/VKSwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ VKSwapChain::VKSwapChain(
VkDevice device,
VKDeviceMemoryManager& deviceMemoryMngr,
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& surface)
const std::shared_ptr<Surface>& surface,
const RendererInfo& rendererInfo)
:
SwapChain { desc },
instance_ { instance },
Expand Down Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion sources/Renderer/Vulkan/VKSwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class VKSwapChain final : public SwapChain
VkDevice device,
VKDeviceMemoryManager& deviceMemoryMngr,
const SwapChainDescriptor& desc,
const std::shared_ptr<Surface>& surface
const std::shared_ptr<Surface>& surface,
const RendererInfo& rendererInfo
);

void Present() override;
Expand Down

0 comments on commit 5cdd3a0

Please sign in to comment.