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
Virgil 3D with SDL2 on macOS #4986
Comments
|
Should this go in to 2.0.18, after review of course? |
|
Maybe it's should be I am confusing about the change. |
|
Conceptually fullscreen (and fullscreen desktop) windows cover the entire screen. By definition their position comes from the layout of the monitors on the desktop. I'm not sure I understand why this change would be helpful or meaningful? |
@slouken I am not sure if the question was directed at me. Here's my take anyway inferring the simplicity of single-monitor scenario. Conceptually, fullscreen isn't quite the same as fullscreen desktop. Your definition is only valid for fullscreen window, which involves a display mode switch, either for real or emulated by the underlaying compositor. So the window position is always the entire display area. A fullscreen desktop window, on the other hand, is a borderless, stretched window, without display mode switch. The window position may be moved outside of display area and not necessarily visible in the display area, just like an ordinary window with decoration. It is possible that an SDL2 application can manage multiple fullscreen desktop window and implement swipe transitional motion similar to multiple virtual desktop. Hence, window position should be notified into the lower level platform specific window compositor. The Virgil 3D QEMU macOS use case is really simple, it just need to notify Apple macOS window compositor for repainting with the same window position. |
I think this is what's confusing me at the moment. Is the problem that SDL_WINDOW_FULLSCREEN_DESKTOP, which on macOS will generate a new "fullscreen space" (which is an OS-provided virtual desktop), refusing the redraw the window when it isn't in the foreground? Is it that QEMU won't draw to the window when it thinks it hasn't changed? One can definitely keep drawing to a fullscreen space's window in general and the compositor will notice, so I must be misunderstanding the problem here. I know you've explained this twice now, and I'm grateful for your patience, but I don't understand the problem, and my guessing at what I think is the problem has me believing this isn't the right solution. |
I have to say that I do not have the answer to what's confusing you. I can only describe the problem, QEMU will draw the window but macOS won't paint it. If I keep QEMU in windowed mode, then I can get macOS to paint it by resizing/moving QEMU window, without any modification to SDL2. This obviously did not work when QEMU was in fullscreen due to the if condition that blocked window position into macOS compositor.
You could be right, but that was not always the case. For eg. running The rest of Virgil 3D SDL2 OpenGL implementation is exactly the same for Windows, Linux & macOS. I had even forced the same codes on Linux (without GBM & EGL), just SDL2 OpenGL and it worked. Virgil 3D with SDL2 OpenGL for macOS depends on a quirk that requires window position to reach down into macOS compositor for screen updates. IMHO, even without considering such macOS specific quirk, it is conceptually incorrect to block window position for SDL_WINDOW_FULLSCREEN_DESKTOP. The fake fullscreen should possess similar movable property as borderless window. |
|
Thanks, it's helpful to see the exact source line in QEMU. I'm going to get QEMU building over here and look at this directly, because it seems like some weird interaction beyond the window size issue. For now, though, I'll move this to 2.0.24, because we're running out of time on 2.0.22. |
|
We've been focused on SDL3 development, so I'm moving this out of the milestone. Please let us know if you have more information or a fix. |
|
The 1-liner fix had already been offered since the beginning. |
|
The problem is that according to the API contract, setting the window position in fullscreen mode is only supposed to set where the window will be once it leaves fullscreen mode, so regardless of platform, this would be a breaking change. Have you tracked down the underlying reason this fixes the issue for you? |
|
Could it be that the context is being deleted on the wrong thread? |
|
I'm wondering if it could be related to #7410? |
|
If you wished to enforce such API contract, then just send the same window position again and discard the (x, y) inputs for FULLSCREEN_DESKTOP only. This is essentially no-op but achieves the same effect of kicking the macOS underlying compositor.
Unfortunately, I highly depend on Windows/Linux for debugging and this issue just applies for macOS. I can't do much over there. |
|
I was able to build qemu for macOS, and I did fix an unrelated issue in 1bd9ebf53, but I wasn't able to reproduce the bug listed here. I ran |
|
You need Linux with GL acceleration, for eg. Ubuntu AArch64 or ArchLinux AArch64, and qemu for macOS with virglrenderer. On GNOME/Wayland, this issue reproduces 100% every time after GDM login, or just run |
|
You mean as a guest OS? Do you have a disk image I can run to reproduce this? Do I have to do anything special to enable virglrenderer when building or running qemu? |
Yes, Linux as a guest OS with GL acceleration. I do, but it's huge, over 4GB in compressed size.
It's an unfortunate "YES" for macOS. The virglrender is solely Linux focus. |
|
Sure, if you give me a download link for the disk image and a qemu configure and run command line, I'll be happy to check it out. I'm applying the patches from your tree now. |
|
I am sorry that I don't have anything that can host such a huge download. ArchLinux AArch64 setup is quick & easy if you like Linux. Otherwise, Ubuntu server AArch64 has guided setup. It won't take a long time for Apple M1 superb performance and SSD throughput. |
|
Okay, what qemu target do I need to build to run AArch64 Linux? |
|
Okay, I'm configuring with |
|
You missed out Make sure the configure log has |
|
Okay, I have it built and installed. What is the command line to boot the VM? |
|
I'm trying: Just to get something running, but it just comes up with the QEMU monitor console and doesn't boot. I'm about out of time, so I'm going to wait for good instructions on how to get a bootable Linux environment. |
|
You missed out the GPU and |
|
That's closer... |
|
When you get to the "Tiano EFI Framework" logo, press "Fn-F2" to enter the UEFI setup. You should be able to select "Boot Manager" and boot from the USB-CD. Arch AArch64 gist |
|
Okay, I found an archboot image at https://pkgbuild.com/~tpowa/archboot/iso/aarch64/latest/, and I found out how to set up bridged networking with macOS. Here's my boot command: ... and I successfully installed an Arch Linux system. |
|
So I'm not running fullscreen yet, just trying to get this working, and I have GDM starting at boot, but all I get is a black screen and these warnings: If I run with |
|
I am using virglrenderer from here: https://github.com/akihikodaki/virglrenderer/tree/macos |
|
The other virglrenderer tree was customized for libANGLE/GLES/CocoaGL, AFAICT. I doubt it ever works for SDL2 OpenGL. You should just use the patch from qemu-3dfx for virglrenderer 0.10.4. |
|
Okay, that worked much better. :) |
|
So one thing I noticed without even going fullscreen is that |
Yes. Congratulation! You have the exact repro now! 😁 Isn't that simple? |
|
Except that I'm running windowed and I've applied your patch. :) |
|
Did you mean my offered patch for SDL2 or just the misc QEMU/virglrenderer? Running windowed or fullscreen doesn't matter. QEMU uses FULLSCREEN_DESKTOP and that's just fake borderless window. Without my offered SDL2 patch, you will just get black window on GL acceleration. In windowed mode, you can resize/move the window to kick the compositor to repaint it. You can't do that in fullscreen. |
If we don't do this, the view will be blanked even if another context is current and rendering from that context won't be visible. Fixes #4986
|
Okay, I tracked down the root cause of this, and fixed it in f5c0760. Thanks for your patience! |
|
You can delete the code in qemu that does the macOS setposition hack, it's no longer necessary. :) |
If we don't do this, the view will be blanked even if another context is current and rendering from that context won't be visible. Fixes #4986
|
No, I don't believe so. That code has been entirely reworked for SDL3. |
|
I know you just released 2.26.4. Any hope we can see this in 2.26.5 instead of 2.28.0? |
I actually hope that 2.28.0 is scheduled for release soon, instead of 2.26.x |
|
We'll have one more 2.26.5 before 2.28.0. We don't have a firm date for 2.28 yet, but it'll likely be toward the end of April. I'm glad the patches work well for you, but they're a big enough behavior change that I'd like them to get more testing before they go into a point release. |
|
Also, as an aside, the mouse warping behavior was really frustrating, so I made a quick patch to improve it. As noted, the right way to handle this is for qemu to render the cursor at the guest position instead of warping the system cursor, but this is a bit better. diff --git a/ui/sdl2.c b/ui/sdl2.c
index 8cb77416af..4cd5081108 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -51,6 +51,9 @@ static SDL_Cursor *sdl_cursor_hidden;
static int absolute_enabled;
static int guest_cursor;
static int guest_x, guest_y;
+static int mouse_warped;
+static int mouse_warp_x;
+static int mouse_warp_y;
static SDL_Cursor *guest_sprite;
static Notifier mouse_mode_notifier;
@@ -224,6 +227,9 @@ static void sdl_grab_start(struct sdl2_console *scon)
if (guest_cursor) {
SDL_SetCursor(guest_sprite);
if (!qemu_input_is_absolute() && !absolute_enabled) {
+ mouse_warped = 1;
+ mouse_warp_x = guest_x;
+ mouse_warp_y = guest_y;
SDL_WarpMouseInWindow(scon->real_window, guest_x, guest_y);
}
} else {
@@ -295,16 +301,13 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y,
y, 0, surface_height(scon->surface));
} else {
- if (guest_cursor) {
- x -= guest_x;
- y -= guest_y;
- guest_x += x;
- guest_y += y;
- dx = x;
- dy = y;
+ if (mouse_warped && x == mouse_warp_x && y == mouse_warp_y) {
+ /* Ignore mouse warp motion */
+ mouse_warped = 0;
+ } else {
+ qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_X, dx);
+ qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_Y, dy);
}
- qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_X, dx);
- qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_Y, dy);
}
qemu_input_event_sync();
}
@@ -715,7 +718,26 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
SDL_SetCursor(guest_sprite);
if (!qemu_input_is_absolute() && !absolute_enabled) {
- SDL_WarpMouseInWindow(scon->real_window, x, y);
+ /*
+ * Only warp if we're far away from the desired position,
+ * this prevents continually warping and jittering.
+ *
+ * The real solution is to use relative mouse motion
+ * and have qemu render the cursor itself at the expected
+ * location if the input isn't absolute.
+ */
+ const int WARP_THRESHOLD_SQUARED = 100;
+ int current_x, current_y, delta_x, delta_y;
+
+ SDL_GetMouseState(¤t_x, ¤t_y);
+ delta_x = (current_x - x);
+ delta_y = (current_y - y);
+ if ((delta_x * delta_x + delta_y * delta_y) > WARP_THRESHOLD_SQUARED) {
+ mouse_warped = 1;
+ mouse_warp_x = x;
+ mouse_warp_y = y;
+ SDL_WarpMouseInWindow(scon->real_window, x, y);
+ }
}
}
} else if (gui_grab) { |
A minor change is required for SDL2 to support QEMU Virgil 3D on macOS. Virgil 3D manages OpenGL context with FBO and for Apple OpenGL it seems to require window move/resize events for the screen to be repainted. For borderless fullscreen as in SDL_WINDOW_FULLSCREEN_DESKTOP, it should be legal to allow window position to pass into native backends.
sdl2.patch
OpenGL on Windows 10 and Linux do not require this, but I do not foresee any issue at keeping the same semantics for consistency. If necessary, #ifdef-#endif can be used to guard the change.
The text was updated successfully, but these errors were encountered: