Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support for wayland to bgfx renderer #11451

Merged
merged 8 commits into from
Sep 28, 2023

Conversation

belegdol
Copy link
Contributor

@belegdol belegdol commented Jul 30, 2023

This is an initial working prototype of wayland working with bgfx renderer. It only works with -bgfx_backend opengl due to bkaradzic/bgfx#3143 still needing work. Proper conditionalisation is also required so that X11 or Wayland are included and linked only when required.
In order to get to this stage, update to the libraries was required:
- bgfx to 3101a0d93f024e4278caaab29566647cd3e2bf84
- bx to 198cd120e4941d8aeb677db945ef4291a1ced291
- bimg to ec02df824a763b2e2ae31e19c674ba0bc88c0695
Libs update moved to #11493 for clarity.

While still hacky, it allows for bgfx in a native Wayland window:

Bildschirmfoto vom 2023-07-30 21-42-47

@belegdol
Copy link
Contributor Author

belegdol commented Aug 2, 2023

Now vulkan renderer is working on wayland as well. I am not sure whether this is ready to be merged due to the following:

  • with vulkan renderer on wayland the window is blinking with umk3 on my nvidia system. Not sure where the issue is coming from
  • in comparison with current state, attempting to start mame with -videodriver wayland when it is not built in results in segmentation fault
  • with wayland support built in, attempting to start mame with -videodriver x11 results in segmentation fault due to -bgfx_backend vulkan being default

Nevertheless, it shows that native wayland is possible.

@belegdol
Copy link
Contributor Author

belegdol commented Aug 2, 2023

Blinking seems to be an nvidia specific issue, I do not see this on my amd laptop.

Comment on lines 1517 to 1524
MAME_DIR .. "3rdparty/bgfx/src/glcontext_eagl.mm",
MAME_DIR .. "3rdparty/bgfx/src/glcontext_nsgl.mm",
MAME_DIR .. "3rdparty/bgfx/src/renderer_mtl.mm",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this potentially cause issues for older Apple hardware that has poor Metal support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, but OpenGL support was dropped from upstream bgfx:
bkaradzic/bgfx@928800f

If the PR is interesting but we want to keep OpenGL on Macs, I can see if the necessary commits can be cherry-picked instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rb6502 how many people are going to want my head if bgfx via OpenGL is no longer possible on macOS?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just got done promising Mac users I wouldn't lift the system requirements until January, so I would strongly prefer to hold off on anything that would affect that until then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Particularly as Belegdol says this doesn't actually work that well (which describes the totality of Wayland in my experience, to be fair).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. Maybe we can leave this PR open in the draft state as a proof-of-concept?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You really should follow the code style of files you’re modifying. Also, why are you casting data pointers through uintptr_t? That’s only necessary when coercing pointer-to-code to pointer-to-data or vice versa.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped the cast. Apologies for the style, I am a C++ newbie at best. The code is more or less a copy-paste from
https://github.com/bkaradzic/bgfx/blob/3101a0d93f024e4278caaab29566647cd3e2bf84/examples/common/entry/entry_sdl.cpp#L53-L64

Do you mind being more specific in terms of what I should fix style-wise?

@belegdol
Copy link
Contributor Author

belegdol commented Aug 3, 2023

There are at least two additional points which would be worth clarifying before this is ready for merging

  • can wayland be detected at runtime? It works for EGL renderer but not for the Vulkan one as it needs a different function on wayland. If this is possible, segfaults would go away. I got it running for native X11 and native Wayland with the help of $XDG_SESSION_TYPE, but this does not cover XWayland unfortunately.
  • why is egl_window pointer provided by SDL not working: Defer EGLSurface creation to SDL_GL_CreateContext libsdl-org/SDL#5386 (comment)

@belegdol
Copy link
Contributor Author

belegdol commented Aug 11, 2023

I have now pushed an update allowing wayland and X11 to be compiled in simultaneously. XWayland is working as well. The patches needed to achieve this are not merged to upstream bgfx yet, but I am putting these here in case someone is curious and would like to test it themselves.
SDL upstream have also clarified that the egl_window pointer being defined the way it was was an accident meaning that creating it with wl_egl_window_create is the way to go.
With nvidia binary driver this is not really usable: with vulkan renderer the window is blinking whereas opengl one falls back to software rendering [1], but I would tend do blame these on generally subpar wayland support with the nvidia drivers.

[1] https://forums.developer.nvidia.com/t/hardware-egl-not-working-on-wayland-libegl-warning-egl-failed-to-create-dri2-screen/262167

@belegdol belegdol changed the title Update BGFX, BX and BIMG and add initial support for wayland to bgfx renderer Add initial support for wayland to bgfx renderer Aug 18, 2023
@belegdol
Copy link
Contributor Author

I moved the update to the 3rdparty libraries to a separate PR (#11493) for clarity.

@cuavas
Copy link
Member

cuavas commented Aug 19, 2023

I moved the update to the 3rdparty libraries to a separate PR (#11493) for clarity.

It’s still showing as having all those 3rdparty files changed (1063 files changed).

@belegdol
Copy link
Contributor Author

I moved the update to the 3rdparty libraries to a separate PR (#11493) for clarity.

It’s still showing as having all those 3rdparty files changed (1063 files changed).

Apologies. This is either me failing at github or github not being able to create a pr based on another PR. If I understand correctly, it would work if the b* libs update could be temporarily put in a mamedev branch.
Alternatively I could rebase against master but this would make testing slightly more complicated.

@belegdol
Copy link
Contributor Author

belegdol commented Aug 19, 2023

Apologies if it is a dumb question, but is the code in

//============================================================
// helper for getting native platform window
//============================================================
#ifdef OSD_SDL
static void *sdlNativeWindowHandle(SDL_Window *window)
{
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if (!SDL_GetWindowWMInfo(window, &wmi))
return nullptr;
switch (wmi.subsystem)
{
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
case SDL_SYSWM_WINDOWS:
return wmi.info.win.window;
#endif
#if defined(SDL_VIDEO_DRIVER_X11)
case SDL_SYSWM_X11:
return (void *)uintptr_t(wmi.info.x11.window);
#endif
#if defined(SDL_VIDEO_DRIVER_COCOA)
case SDL_SYSWM_COCOA:
return wmi.info.cocoa.window;
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16)
case SDL_SYSWM_WAYLAND:
return wmi.info.wl.egl_window;
#endif
#if defined(SDL_VIDEO_DRIVER_ANDROID)
case SDL_SYSWM_ANDROID:
return wmi.info.android.window;
#endif
default:
return nullptr;
}
}
#endif // OSD_SDL
actually used? I put a breakpoint at
SDL_SysWMinfo wmi;
but it seems not to get hit.
If this code is not being used, making the change cleaner would be much simpler. Thanks!

@belegdol
Copy link
Contributor Author

I moved the update to the 3rdparty libraries to a separate PR (#11493) for clarity.

It’s still showing as having all those 3rdparty files changed (1063 files changed).

Apologies. This is either me failing at github or github not being able to create a pr based on another PR. If I understand correctly, it would work if the b* libs update could be temporarily put in a mamedev branch. Alternatively I could rebase against master but this would make testing slightly more complicated.

I rebased onto master, will deal with the dependencies locally.

@belegdol
Copy link
Contributor Author

belegdol commented Aug 20, 2023

@cuavas, is this better style-wise? Also, if sdlNativeWindowHandle() is actually needed, which namespace would be the best to put create_wl_egl_window() into?

@cuavas
Copy link
Member

cuavas commented Aug 21, 2023

Apologies if it is a dumb question, but is the code in

//============================================================
// helper for getting native platform window
//============================================================
#ifdef OSD_SDL
static void *sdlNativeWindowHandle(SDL_Window *window)
{
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if (!SDL_GetWindowWMInfo(window, &wmi))
return nullptr;
switch (wmi.subsystem)
{
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
case SDL_SYSWM_WINDOWS:
return wmi.info.win.window;
#endif
#if defined(SDL_VIDEO_DRIVER_X11)
case SDL_SYSWM_X11:
return (void *)uintptr_t(wmi.info.x11.window);
#endif
#if defined(SDL_VIDEO_DRIVER_COCOA)
case SDL_SYSWM_COCOA:
return wmi.info.cocoa.window;
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16)
case SDL_SYSWM_WAYLAND:
return wmi.info.wl.egl_window;
#endif
#if defined(SDL_VIDEO_DRIVER_ANDROID)
case SDL_SYSWM_ANDROID:
return wmi.info.android.window;
#endif
default:
return nullptr;
}
}
#endif // OSD_SDL

actually used? I put a breakpoint at

SDL_SysWMinfo wmi;

but it seems not to get hit.
If this code is not being used, making the change cleaner would be much simpler. Thanks!

It’s used by renderer_bgfx::create if you have multiple output windows/screens. It definitely is needed.

Comment on lines 429 to 456
platform_data.nwh = wmi.info.wl.egl_window;
platform_data.nwh = (void *)create_wl_egl_window(dynamic_cast<sdl_window_info const &>(window).platform_window(), wmi.info.wl.surface);
platform_data.type = bgfx::NativeWindowHandleType::Wayland;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you explicitly casting to void *? You don’t seem to be casting away CV qualifiers, and you aren’t doing a dynamic cast to the canonical object pointer. You should be able to implicitly convert to void * if you just want the pointer value to be preserved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implicit conversion seems to be working, will fix it.

Comment on lines 393 to 408
#if defined(SDLMAME_USE_WAYLAND)
wl_egl_window* create_wl_egl_window(SDL_Window *window, struct wl_surface *surface)
{
wl_egl_window *win_impl = (wl_egl_window*)SDL_GetWindowData(window, "wl_egl_window");
if(!win_impl)
{
int width, height;
SDL_GetWindowSize(window, &width, &height);
if(!surface)
return nullptr;
win_impl = wl_egl_window_create(surface, width, height);
SDL_SetWindowData(window, "wl_egl_window", win_impl);
}
return win_impl;
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the formatting of the file:

  • Space before but not after right-associative unary *
  • Space between flow control keyword and opening parenthesis of controlling expression

Why are you checking surface after getting the window size? You won’t use the window size if it’s null.

Can wl_egl_window_create fail?

Unlike the other cases in the switch (wmi.subsystem) this can fail. However, you aren’t checking for failure and returning false from video_bgfx::set_platform_data when that happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now.

Comment on lines 546 to 557
wl_egl_window *win_impl = (wl_egl_window*)SDL_GetWindowData(window, "wl_egl_window");
if(!win_impl)
{
int width, height;
SDL_GetWindowSize(window, &width, &height);
struct wl_surface* surface = wmi.info.wl.surface;
if(!surface)
return nullptr;
win_impl = wl_egl_window_create(surface, width, height);
SDL_SetWindowData(window, "wl_egl_window", win_impl);
}
return (void*)win_impl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is non-trivial copy/pasta – shouldn’t it be factored out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

- do not cast wayland window pointer implicitly
- fix whitespace
- add error handling
- factor out second instance of wayland window creation
@belegdol
Copy link
Contributor Author

I have attempted to implement your feedback to the best of my abilities. Thanks to your hint about multiple windows, it appears that there is an issue with vulkan on wayland whereby second window is not being shown. It is with the opengl renderer strangely enough. I need to investigate further.
Thank you for your patience so far.

@belegdol
Copy link
Contributor Author

I have attempted to implement your feedback to the best of my abilities. Thanks to your hint about multiple windows, it appears that there is an issue with vulkan on wayland whereby second window is not being shown. It is with the opengl renderer strangely enough. I need to investigate further. Thank you for your patience so far.

Multiple windows needs to be fixed in bgfx:
bkaradzic/bgfx#3162

Comment on lines 394 to 415
wl_egl_window *create_wl_egl_window(SDL_Window *window, struct wl_surface *surface)
{
if (!surface)
{
osd_printf_error("Wayland surface missing, aborting\n");
return nullptr;
}
wl_egl_window *win_impl = (wl_egl_window *)SDL_GetWindowData(window, "wl_egl_window");
if (!win_impl)
{
int width, height;
SDL_GetWindowSize(window, &width, &height);
win_impl = wl_egl_window_create(surface, width, height);
if (!win_impl)
{
osd_printf_error("Creating wayland window failed\n");
return nullptr;
}
SDL_SetWindowData(window, "wl_egl_window", win_impl);
}
return win_impl;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off in two places – you’ve bumped two levels for some of the if statements. The braces should be at the level of the if statement itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 462 to 464
platform_data.ndt = wmi.info.wl.display;
platform_data.nwh = wmi.info.wl.egl_window;
platform_data.nwh = create_wl_egl_window(dynamic_cast<sdl_window_info const &>(window).platform_window(), wmi.info.wl.surface);
platform_data.type = bgfx::NativeWindowHandleType::Wayland;
Copy link
Member

@cuavas cuavas Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because create_wl_egl_window can fail (unlike the other branches of this switch statement), you need to check whether it succeeded here, and return false if it didn’t.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now. Is it also needed for sdlNativeWindowHandle()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now. Is it also needed for sdlNativeWindowHandle()?

It is, but the function would need to be rearranged a bit. I’ll worry about that later.

- more whitespace fixes
- more failure handling
Comment on lines -429 to +469
platform_data.nwh = wmi.info.wl.egl_window;
platform_data.nwh = create_wl_egl_window(dynamic_cast<sdl_window_info const &>(window).platform_window(), wmi.info.wl.surface);
if (!platform_data.nwh)
{
osd_printf_error("BGFX: Error creating a Wayland window\n");
return false;
}
platform_data.type = bgfx::NativeWindowHandleType::Wayland;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the rest of the branches in this switch statement be setting platform_data.type to bgfx::NativeWindowHandleType::Default to be explicit? The bgfx examples all seem to be doing it now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

platform_data.type is supposed initialised to default in bgfx.cpp:

, type(NativeWindowHandleType::Default)

The reason why examples are doing it explicitly is because they all go via an intermediate getNativeWindowHandleType() function which has to return something for non-Wayland. mame appears to be setting the parameters directly which would suggest setting the window handle to default would be redundant.

@cuavas
Copy link
Member

cuavas commented Sep 28, 2023

@belegdol can this be marked as ready for review now that the bgfx changes have been merged, or are there other things that would hold it up?

@belegdol belegdol marked this pull request as ready for review September 28, 2023 15:22
@belegdol
Copy link
Contributor Author

No other things holding up, just wanted to make sure things are merged in the correct order.

@cuavas cuavas merged commit 117c384 into mamedev:master Sep 28, 2023
5 checks passed
@belegdol belegdol deleted the bgfx_wayland branch September 28, 2023 15:26
@belegdol
Copy link
Contributor Author

Thanks for merging!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants