Linux native window (#3975)

Initial implementation of Native Window for Linux

Signed-off-by: Steve Pham <spham@amazon.com>
This commit is contained in:
Steve Pham
2021-09-09 10:49:39 -07:00
committed by GitHub
parent 52460189aa
commit 6cb2222da8
13 changed files with 502 additions and 126 deletions
@@ -57,6 +57,7 @@ namespace AzFramework
uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const
{
// [GFX TODO][GHI - 2678]
// Using 60 for now until proper support is added
return 60;
}
@@ -55,6 +55,29 @@ namespace AzFramework
using LinuxXcbConnectionManagerBus = AZ::EBus<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
class LinuxXcbEventHandler
{
public:
AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
virtual ~LinuxXcbEventHandler() = default;
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
};
class LinuxXcbEventHandlerBusTraits
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
};
using LinuxXcbEventHandlerBus = AZ::EBus<LinuxXcbEventHandler, LinuxXcbEventHandlerBusTraits>;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -6,101 +6,28 @@
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include "Application_Linux_xcb.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace AzFramework
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
class LinuxXcbConnectionManagerImpl
: public LinuxXcbConnectionManagerBus::Handler
{
public:
LinuxXcbConnectionManagerImpl()
{
m_xcbConnection = xcb_connect(nullptr, nullptr);
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
LinuxXcbConnectionManagerBus::Handler::BusConnect();
}
~LinuxXcbConnectionManagerImpl() override
{
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
xcb_disconnect(m_xcbConnection);
}
xcb_connection_t* GetXcbConnection() const override
{
return m_xcbConnection;
}
private:
xcb_connection_t* m_xcbConnection = nullptr;
};
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
////////////////////////////////////////////////////////////////////////////////////////////////
class ApplicationLinux
: public Application::Implementation
, public LinuxLifecycleEvents::Bus::Handler
{
public:
////////////////////////////////////////////////////////////////////////////////////////////
AZ_CLASS_ALLOCATOR(ApplicationLinux, AZ::SystemAllocator, 0);
ApplicationLinux();
~ApplicationLinux() override;
////////////////////////////////////////////////////////////////////////////////////////////
// Application::Implementation
void PumpSystemEventLoopOnce() override;
void PumpSystemEventLoopUntilEmpty() override;
private:
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
};
////////////////////////////////////////////////////////////////////////////////////////////////
Application::Implementation* Application::Implementation::Create()
{
return aznew ApplicationLinux();
}
////////////////////////////////////////////////////////////////////////////////////////////////
ApplicationLinux::ApplicationLinux()
{
LinuxLifecycleEvents::Bus::Handler::BusConnect();
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
{
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
}
return aznew ApplicationLinux_xcb();
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return nullptr;
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
#error "Linux Window Manager XLIB not supported."
return nullptr;
#else
#error "Linux Window Manager not recognized."
return nullptr;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
}
////////////////////////////////////////////////////////////////////////////////////////////////
ApplicationLinux::~ApplicationLinux()
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
{
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
}
m_xcbConnectionManager.reset();
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
}
////////////////////////////////////////////////////////////////////////////////////////////////
void ApplicationLinux::PumpSystemEventLoopOnce()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////
void ApplicationLinux::PumpSystemEventLoopUntilEmpty()
{
}
} // namespace AzFramework
@@ -0,0 +1,94 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include "Application_Linux_xcb.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace AzFramework
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
////////////////////////////////////////////////////////////////////////////////////////////////
class LinuxXcbConnectionManagerImpl
: public LinuxXcbConnectionManagerBus::Handler
{
public:
LinuxXcbConnectionManagerImpl()
{
m_xcbConnection = xcb_connect(nullptr, nullptr);
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
LinuxXcbConnectionManagerBus::Handler::BusConnect();
}
~LinuxXcbConnectionManagerImpl()
{
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
xcb_disconnect(m_xcbConnection);
}
xcb_connection_t* GetXcbConnection() const override
{
return m_xcbConnection;
}
private:
xcb_connection_t* m_xcbConnection = nullptr;
};
////////////////////////////////////////////////////////////////////////////////////////////////
ApplicationLinux_xcb::ApplicationLinux_xcb()
{
LinuxLifecycleEvents::Bus::Handler::BusConnect();
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
{
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
ApplicationLinux_xcb::~ApplicationLinux_xcb()
{
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
{
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
}
m_xcbConnectionManager.reset();
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
}
////////////////////////////////////////////////////////////////////////////////////////////////
void ApplicationLinux_xcb::PumpSystemEventLoopOnce()
{
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
{
if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
{
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
free(event);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty()
{
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
{
while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
{
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
free(event);
}
}
}
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -0,0 +1,40 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace AzFramework
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
////////////////////////////////////////////////////////////////////////////////////////////////
class ApplicationLinux_xcb
: public Application::Implementation
, public LinuxLifecycleEvents::Bus::Handler
{
public:
////////////////////////////////////////////////////////////////////////////////////////////
AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0);
ApplicationLinux_xcb();
~ApplicationLinux_xcb() override;
////////////////////////////////////////////////////////////////////////////////////////////
// Application::Implementation
void PumpSystemEventLoopOnce() override;
void PumpSystemEventLoopUntilEmpty() override;
private:
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
};
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -6,48 +6,24 @@
*
*/
#include <AzFramework/Windowing/NativeWindow.h>
#include "NativeWindow_Linux_xcb.h"
namespace AzFramework
{
class NativeWindowImpl_Linux final
: public NativeWindow::Implementation
{
public:
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux, AZ::SystemAllocator, 0);
NativeWindowImpl_Linux() = default;
~NativeWindowImpl_Linux() override = default;
// NativeWindow::Implementation overrides...
void InitWindow(const AZStd::string& title,
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
NativeWindowHandle GetWindowHandle() const override;
uint32_t GetDisplayRefreshRate() const override;
};
NativeWindow::Implementation* NativeWindow::Implementation::Create()
{
return aznew NativeWindowImpl_Linux();
}
void NativeWindowImpl_Linux::InitWindow([[maybe_unused]]const AZStd::string& title,
const WindowGeometry& geometry,
[[maybe_unused]]const WindowStyleMasks& styleMasks)
{
m_width = geometry.m_width;
m_height = geometry.m_height;
}
NativeWindowHandle NativeWindowImpl_Linux::GetWindowHandle() const
{
AZ_Assert(false, "NativeWindow not implemented for Linux");
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
return aznew NativeWindowImpl_Linux_xcb();
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return nullptr;
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
#error "Linux Window Manager XLIB not supported."
return nullptr;
#else
#error "Linux Window Manager not recognized."
return nullptr;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
}
uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const
{
//Using 60 for now until proper support is added
return 60;
}
} // namespace AzFramework
@@ -0,0 +1,244 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Windowing/NativeWindow.h>
#include <xcb/xcb.h>
#include "NativeWindow_Linux_xcb.h"
namespace AzFramework
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
[[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb";
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
////////////////////////////////////////////////////////////////////////////////////////////////
NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb()
: NativeWindow::Implementation()
{
if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get();
xcbConnectionManager != nullptr)
{
m_xcbConnection = xcbConnectionManager->GetXcbConnection();
}
AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
}
////////////////////////////////////////////////////////////////////////////////////////////////
NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title,
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks)
{
// Get the parent window
const xcb_setup_t* xcbSetup = xcb_get_setup(m_xcbConnection);
xcb_screen_t* xcbRootScreen = xcb_setup_roots_iterator(xcbSetup).data;
xcb_window_t xcbParentWindow = xcbRootScreen->root;
// Create an XCB window from the connection
m_xcbWindow = xcb_generate_id(m_xcbConnection);
uint16_t borderWidth = 0;
const uint32_t mask = styleMasks.m_platformAgnosticStyleMask;
if ((mask & WindowStyleMasks::WINDOW_STYLE_BORDERED) ||
(mask & WindowStyleMasks::WINDOW_STYLE_RESIZEABLE))
{
borderWidth = s_DefaultXcbWindowBorderWidth;
}
uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t valueList[] = { xcbRootScreen->black_pixel,
XCB_EVENT_MASK_STRUCTURE_NOTIFY };
xcb_void_cookie_t xcbCheckResult;
xcbCheckResult = xcb_create_window_checked(m_xcbConnection,
XCB_COPY_FROM_PARENT,
m_xcbWindow,
xcbParentWindow,
aznumeric_cast<int16_t>(geometry.m_posX),
aznumeric_cast<int16_t>(geometry.m_posY),
aznumeric_cast<int16_t>(geometry.m_width),
aznumeric_cast<int16_t>(geometry.m_height),
borderWidth,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
xcbRootScreen->root_visual,
eventMask,
valueList);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to create xcb window.");
SetWindowTitle(title);
// Setup the window close event
const static char* wmProtocolString = "WM_PROTOCOLS";
xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString);
xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr);
AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
m_xcbAtomProtocols = replyProtocol->atom;
const static char* wmDeleteWindowString = "WM_DELETE_WINDOW";
xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString);
xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr);
AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
m_xcbAtomDeleteWindow = replyDeleteWindow->atom;
xcbCheckResult = xcb_change_property_checked(m_xcbConnection,
XCB_PROP_MODE_REPLACE,
m_xcbWindow,
m_xcbAtomProtocols,
XCB_ATOM_ATOM,
s_XcbFormatDataSize,
1,
&m_xcbAtomDeleteWindow);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to change the xcb atom property for WM_CLOSE event");
m_width = geometry.m_width;
m_height = geometry.m_height;
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::Activate()
{
LinuxXcbEventHandlerBus::Handler::BusConnect();
if (!m_activated) // nothing to do if window was already activated
{
m_activated = true;
xcb_map_window(m_xcbConnection, m_xcbWindow);
xcb_flush(m_xcbConnection);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::Deactivate()
{
if (m_activated) // nothing to do if window was already deactivated
{
m_activated = false;
WindowNotificationBus::Event(reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowClosed);
xcb_unmap_window(m_xcbConnection, m_xcbWindow);
xcb_flush(m_xcbConnection);
}
LinuxXcbEventHandlerBus::Handler::BusDisconnect();
}
////////////////////////////////////////////////////////////////////////////////////////////////
NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const
{
return reinterpret_cast<NativeWindowHandle>(m_xcbWindow);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title)
{
xcb_void_cookie_t xcbCheckResult;
xcbCheckResult = xcb_change_property(m_xcbConnection,
XCB_PROP_MODE_REPLACE,
m_xcbWindow,
XCB_ATOM_WM_NAME,
XCB_ATOM_STRING,
8,
static_cast<uint32_t>(title.size()),
title.c_str());
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title.");
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize)
{
const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height };
xcb_configure_window(m_xcbConnection, m_xcbWindow, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
m_width = clientAreaSize.m_width;
m_height = clientAreaSize.m_height;
}
////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const
{
// [GFX TODO][GHI - 2678]
// Using 60 for now until proper support is added
return 60;
}
////////////////////////////////////////////////////////////////////////////////////////////////
bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie)
{
bool result = true;
if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie))
{
AZ_TracePrintf("Error","Error code %d", error->error_code);
result = false;
}
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event)
{
switch (event->response_type & s_XcbResponseTypeMask)
{
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t* cne = reinterpret_cast<xcb_configure_notify_event_t*>(event);
WindowSizeChanged(aznumeric_cast<uint32_t>(cne->width),
aznumeric_cast<uint32_t>(cne->height));
break;
}
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t* cme = reinterpret_cast<xcb_client_message_event_t*>(event);
if ((cme->type == m_xcbAtomProtocols) &&
(cme->format == s_XcbFormatDataSize) &&
(cme->data.data32[0] == m_xcbAtomDeleteWindow))
{
Deactivate();
ApplicationRequests::Bus::Broadcast(&ApplicationRequests::ExitMainLoop);
}
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height)
{
if (m_width != width || m_height != height)
{
m_width = width;
m_height = height;
if (m_activated)
{
WindowNotificationBus::Event(reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowResized, width, height);
}
}
}
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -0,0 +1,53 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Windowing/NativeWindow.h>
#include <xcb/xcb.h>
namespace AzFramework
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
class NativeWindowImpl_Linux_xcb final
: public NativeWindow::Implementation
, public LinuxXcbEventHandlerBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0);
NativeWindowImpl_Linux_xcb();
~NativeWindowImpl_Linux_xcb() override;
////////////////////////////////////////////////////////////////////////////////////////////
// NativeWindow::Implementation
void InitWindow(const AZStd::string& title,
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
void Activate() override;
void Deactivate() override;
NativeWindowHandle GetWindowHandle() const override;
void SetWindowTitle(const AZStd::string& title) override;
void ResizeClientArea(WindowSize clientAreaSize) override;
uint32_t GetDisplayRefreshRate() const override;
////////////////////////////////////////////////////////////////////////////////////////////
// LinuxXcbEventHandlerBus::Handler
void HandleXcbEvent(xcb_generic_event_t* event) override;
private:
bool ValidateXcbResult(xcb_void_cookie_t cookie);
void WindowSizeChanged(const uint32_t width, const uint32_t height);
xcb_connection_t* m_xcbConnection = nullptr;
xcb_window_t m_xcbWindow = 0;
xcb_atom_t m_xcbAtomProtocols;
xcb_atom_t m_xcbAtomDeleteWindow;
};
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework
@@ -12,6 +12,8 @@ set(FILES
AzFramework/API/ApplicationAPI_Platform.h
AzFramework/API/ApplicationAPI_Linux.h
AzFramework/Application/Application_Linux.cpp
AzFramework/Application/Application_Linux_xcb.h
AzFramework/Application/Application_Linux_xcb.cpp
AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
AzFramework/Process/ProcessWatcher_Linux.cpp
AzFramework/Process/ProcessCommon.h
@@ -20,6 +22,8 @@ set(FILES
../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
AzFramework/Windowing/NativeWindow_Linux.cpp
AzFramework/Windowing/NativeWindow_Linux_xcb.h
AzFramework/Windowing/NativeWindow_Linux_xcb.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Unimplemented.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp
@@ -83,11 +83,11 @@ namespace AZ
#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
// On Linux platforms that uses XCB, a resize may occur in the swap chain but the command queue may still
// reference the original surface. This flag is a temporary fix to make sure that all the swap chains
// have finished their resize events before presenting the command queue.
// reference the original surface. This flag is a temporary fix to make sure the swap chain is ready to present
// We need to remove this work around with
// [GFX TODO][GHI - 2678]
AZStd::atomic_bool m_resized{ false };
AZStd::atomic_bool m_readyToPresent { false };
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
protected:
+3 -1
View File
@@ -165,7 +165,9 @@ namespace AZ
}
#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
m_resized.store(true);
// If we are presenting through the editor, the resize is triggered through the editor's window, which
// won't happen until after the surface is ready to present
m_readyToPresent.store(true);
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
return resultCode;
@@ -45,7 +45,7 @@ namespace AZ
#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
for (RHI::SwapChain* swapChain : rhiRequest.m_swapChainsToPresent)
{
if (!swapChain->m_resized)
if (!swapChain->m_readyToPresent)
{
return;
}
@@ -12,6 +12,7 @@
#include <Atom/RHI.Reflect/ImageScopeAttachmentDescriptor.h>
#include <Atom/RHI.Reflect/ImagePoolDescriptor.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <RHI/Conversion.h>
#include <RHI/Device.h>
#include <RHI/Image.h>
@@ -127,6 +128,17 @@ namespace AZ
nativeDimensions->m_imageFormat = ConvertFormat(m_surfaceFormat.format);
}
#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
// When launching in game mode, the surface will be ready at this point, meaning that after
// intialization, this swap chain is ready to present
AZ::ApplicationTypeQuery appType;
ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
if (appType.IsGame())
{
m_readyToPresent.store(true);
}
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
SetName(GetName());
return result;
}