Compare commits

...
2 Commits
Author SHA1 Message Date
ayozetr 6796fbbd13 Window: ask for fullscreen again when Wayland drops it at start
On Wayland a program cannot place its window. With several monitors
KWin could map the game on the one SDL reports as primary, move it to
the monitor chosen in the launcher and leave it there as a plain
window (#39); asked again, fullscreen holds, as KDE's own shortcut
showed. During the first 10 seconds the port now asks again, at most
three times and a second apart, and logs each try. After that the
desktop decides, so its own shortcuts keep working.

TROUBLESHOOTING.md: choosing the monitor, the retry and
SDL_VIDEO_DRIVER=x11 as the fallback.
2026-11-07 12:57:45 +00:00
ayozetr badd460277 Texture cache: name the images when an overlap resolve fails
The warning said only "Image overlap resolve failed". It now gives the
image the game asked for and the one dropped for it (address, size,
dimensions, format, levels and layers), and whether the dropped image
held what the GPU drew: then its contents are lost and the new image is
read from guest memory. Issue #25 had two of these warnings around a
garbled texture that went away after a reload.
2026-11-07 11:56:21 +00:00
4 changed files with 61 additions and 3 deletions

No files matched your search

+11
View File
@@ -59,6 +59,17 @@ and the HUD keeps to the screen's edges; it changes live, in the game's *Display
**Output resolution** *Auto* is the monitor's own; any other size written as `output_res=WxH` in
bbport.ini works too.
## Fullscreen opens on the wrong monitor, or drops back to a window
With several monitors, choose the one to play on in **Display → Monitor**: the port's *Primary*
is the one the system reports first, which on Wayland is not always the one KDE or GNOME show as
primary. On Wayland a program cannot place its own window, so the compositor may open it on
another monitor first and then move it; when that leaves it as a plain window, the port asks for
fullscreen again during the first seconds (the log says
`Display: the compositor left the window out of fullscreen, asked again`). If it still ends up
windowed, add `SDL_VIDEO_DRIVER=x11` under **Advanced → Developer → Extra variables**: through
Xwayland the window places itself.
## Exit to desktop
**Exit to desktop** is in the game's System menu and on the title screen, from bbport 0.7. The
+5
View File
@@ -60,6 +60,11 @@ private:
u64 last_mouse_motion_ms{}; ///< SDL_GetTicks of the last mouse motion (UpdateCursor)
bool cursor_hidden{};
u64 capture_settle_ms{}; ///< mouse motion before this (SDL_GetTicks) is not looking around
/// Issue #39: fullscreen asked again on Wayland when the compositor did not keep it (FixFullscreen).
bool fullscreen_wanted{};
u64 fullscreen_since_ms{}, fullscreen_tried_ms{};
int fullscreen_tries{};
void FixFullscreen();
bool pointer_shown{}; ///< a game module's pointer menu is open (bbgpu_pointer_wanted)
bool released_for_pointer{}; ///< the mouse was let go for it: taken back after
void CaptureMouse(bool capture);
+30 -2
View File
@@ -223,8 +223,8 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, const char* title) : width{width_}
if (gamescope && !(fullscreen && fullscreen[0] == '1')) {
std::printf("Display: gamescope: fullscreen\n");
}
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
!placed && (gamescope || (fullscreen && fullscreen[0] == '1')));
fullscreen_wanted = !placed && (gamescope || (fullscreen && fullscreen[0] == '1'));
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, fullscreen_wanted);
// Issue #234: the swapchain at the display's pixels on a scaled desktop (Wayland 200%), not at
// the logical size stretched by the compositor. Sizes below are read in pixels already.
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
@@ -249,6 +249,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, const char* title) : width{width_}
window_info.render_surface = reinterpret_cast<void*>(SDL_GetNumberProperty(wp, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0));
} else if (driver && !std::strcmp(driver, "wayland")) {
window_info.type = WindowSystemType::Wayland;
fullscreen_since_ms = SDL_GetTicks();
window_info.display_connection = SDL_GetPointerProperty(wp, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr);
window_info.render_surface = SDL_GetPointerProperty(wp, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
} else {
@@ -519,9 +520,36 @@ bool WindowSDL::PollEvents() {
}
pointer_shown = pointer;
UpdateCursor();
FixFullscreen();
return is_open;
}
// Issue #39: on Wayland a program cannot place its window. With several monitors KWin can map
// it on another one first (the one SDL calls primary, not KDE's) and move it to the monitor
// asked for, and the window is left there as a plain window. Asked again, fullscreen holds (as
// KDE's own shortcut did). Only in the first seconds and a few times: there is no fullscreen
// toggle in the game, but the desktop's own shortcuts must keep working after that.
void WindowSDL::FixFullscreen() {
constexpr u64 FirstMs = 10000, BetweenMs = 1000;
constexpr int MaxTries = 3;
if (!fullscreen_wanted || !fullscreen_since_ms || fullscreen_tries >= MaxTries) {
return;
}
const u64 now = SDL_GetTicks();
if (now - fullscreen_since_ms > FirstMs) {
fullscreen_since_ms = 0; // past the start: the desktop decides from here
return;
}
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) || now - fullscreen_tried_ms < BetweenMs) {
return;
}
fullscreen_tried_ms = now;
++fullscreen_tries;
std::printf("Display: the compositor left the window out of fullscreen, asked again (%d of %d)\n",
fullscreen_tries, MaxTries);
SDL_SetWindowFullscreen(window, true);
}
// Issue #3: the OS cursor over the game. Hidden in fullscreen, and in a window after 3 s without
// moving the mouse; always shown while the settings menu or a game's pointer menu is open.
void WindowSDL::UpdateCursor() {
+15 -1
View File
@@ -251,9 +251,23 @@ ImageId TextureCache::FindImage(ImageDesc& desc, bool exact_fmt) {
if (exact_fmt && info.pixel_format != resolved.guest_info.pixel_format) {
image_id = {}; // the very format is needed
} else if (resolved.guest_info.resources < info.resources) {
// bbport (Linux fork): which images, and whether the dropped one held what the GPU
// drew (then lost: the new image is read from guest memory). Issue #25: a texture
// garbled until the game was restarted.
const ImageInfo& had = resolved.guest_info;
LOG_WARNING(Render_Vulkan,
"Image overlap resolve failed: wanted {:#x}+{:#x} {}x{} {} levels {} layers {}; "
"dropped {:#x}+{:#x} {}x{} {} levels {} layers {}{}",
info.guest_address, info.guest_size, info.size.width, info.size.height,
vk::to_string(info.pixel_format), info.resources.levels, info.resources.layers,
had.guest_address, had.guest_size, had.size.width, had.size.height,
vk::to_string(had.pixel_format), had.resources.levels, had.resources.layers,
True(resolved.flags & ImageFlagBits::GpuModified)
? (resolved.SafeToDownload() ? ", drawn by the GPU (its contents are lost)"
: ", drawn by the GPU, then written")
: "");
FreeImage(image_id); // picked up wrongly
image_id = {};
LOG_WARNING(Render_Vulkan, "Image overlap resolve failed");
}
}
if (!image_id) {