diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c index 4c834fd86..26626ee51 100644 --- a/src/video/wayland/SDL_waylandopengles.c +++ b/src/video/wayland/SDL_waylandopengles.c @@ -140,9 +140,9 @@ Wayland_GLES_SwapWindow(_THIS, SDL_Window *window) /* wl_display_prepare_read_queue() will return -1 if the event queue is not empty. * If the event queue is empty, it will prepare us for our SDL_IOReady() call. */ - if (WAYLAND_wl_display_prepare_read_queue(display, data->frame_event_queue) != 0) { + if (WAYLAND_wl_display_prepare_read_queue(display, data->gles_swap_frame_event_queue) != 0) { /* We have some pending events. Check if the frame callback happened. */ - WAYLAND_wl_display_dispatch_queue_pending(display, data->frame_event_queue); + WAYLAND_wl_display_dispatch_queue_pending(display, data->gles_swap_frame_event_queue); continue; } @@ -163,7 +163,7 @@ Wayland_GLES_SwapWindow(_THIS, SDL_Window *window) /* We have events. Read and dispatch them. */ WAYLAND_wl_display_read_events(display); - WAYLAND_wl_display_dispatch_queue_pending(display, data->frame_event_queue); + WAYLAND_wl_display_dispatch_queue_pending(display, data->gles_swap_frame_event_queue); } SDL_AtomicSet(&data->swap_interval_ready, 0); } diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 2c70d4055..8be9cd987 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -426,27 +426,44 @@ SetFullscreen(SDL_Window *window, struct wl_output *output, SDL_bool commit) } } -static const struct wl_callback_listener surface_frame_listener; +const struct wl_callback_listener surface_damage_frame_listener; static void -handle_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) +surface_damage_frame_done(void *data, struct wl_callback *cb, uint32_t time) { - SDL_WindowData *wind = (SDL_WindowData *) data; - SDL_AtomicSet(&wind->swap_interval_ready, 1); /* mark window as ready to present again. */ + SDL_WindowData *wind = (SDL_WindowData *)data; + /* Manually set the damage region when using a viewport. */ if (!SDL_RectEmpty(&wind->viewport_rect)) { wl_surface_damage(wind->surface, wind->viewport_rect.x, wind->viewport_rect.y, wind->viewport_rect.w, wind->viewport_rect.h); } - /* reset this callback to fire again once a new frame was presented and compositor wants the next one. */ - wind->frame_callback = wl_surface_frame(wind->frame_surface_wrapper); wl_callback_destroy(cb); - wl_callback_add_listener(wind->frame_callback, &surface_frame_listener, data); + wind->surface_damage_frame_callback = wl_surface_frame(wind->surface); + wl_callback_add_listener(wind->surface_damage_frame_callback, &surface_damage_frame_listener, data); } -static const struct wl_callback_listener surface_frame_listener = { - handle_surface_frame_done +const struct wl_callback_listener surface_damage_frame_listener = { + surface_damage_frame_done +}; + +static const struct wl_callback_listener gles_swap_frame_listener; + +static void +gles_swap_frame_done(void *data, struct wl_callback *cb, uint32_t time) +{ + SDL_WindowData *wind = (SDL_WindowData *) data; + SDL_AtomicSet(&wind->swap_interval_ready, 1); /* mark window as ready to present again. */ + + /* reset this callback to fire again once a new frame was presented and compositor wants the next one. */ + wind->gles_swap_frame_callback = wl_surface_frame(wind->gles_swap_frame_surface_wrapper); + wl_callback_destroy(cb); + wl_callback_add_listener(wind->gles_swap_frame_callback, &gles_swap_frame_listener, data); +} + +static const struct wl_callback_listener gles_swap_frame_listener = { + gles_swap_frame_done }; @@ -1838,13 +1855,17 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window) * window isn't visible. */ if (window->flags & SDL_WINDOW_OPENGL) { - data->frame_event_queue = WAYLAND_wl_display_create_queue(data->waylandData->display); - data->frame_surface_wrapper = WAYLAND_wl_proxy_create_wrapper(data->surface); - WAYLAND_wl_proxy_set_queue((struct wl_proxy *)data->frame_surface_wrapper, data->frame_event_queue); - data->frame_callback = wl_surface_frame(data->frame_surface_wrapper); - wl_callback_add_listener(data->frame_callback, &surface_frame_listener, data); + data->gles_swap_frame_event_queue = WAYLAND_wl_display_create_queue(data->waylandData->display); + data->gles_swap_frame_surface_wrapper = WAYLAND_wl_proxy_create_wrapper(data->surface); + WAYLAND_wl_proxy_set_queue((struct wl_proxy *)data->gles_swap_frame_surface_wrapper, data->gles_swap_frame_event_queue); + data->gles_swap_frame_callback = wl_surface_frame(data->gles_swap_frame_surface_wrapper); + wl_callback_add_listener(data->gles_swap_frame_callback, &gles_swap_frame_listener, data); } + /* Fire a callback when the compositor wants a new frame to set the surface damage region. */ + data->surface_damage_frame_callback = wl_surface_frame(data->surface); + wl_callback_add_listener(data->surface_damage_frame_callback, &surface_damage_frame_listener, data); + #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH if (c->surface_extension) { data->extended_surface = qt_surface_extension_get_extended_surface( @@ -2107,10 +2128,14 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window) SDL_free(wind->outputs); - if (wind->frame_callback) { - WAYLAND_wl_event_queue_destroy(wind->frame_event_queue); - WAYLAND_wl_proxy_wrapper_destroy(wind->frame_surface_wrapper); - wl_callback_destroy(wind->frame_callback); + if (wind->gles_swap_frame_callback) { + WAYLAND_wl_event_queue_destroy(wind->gles_swap_frame_event_queue); + WAYLAND_wl_proxy_wrapper_destroy(wind->gles_swap_frame_surface_wrapper); + wl_callback_destroy(wind->gles_swap_frame_callback); + } + + if (wind->surface_damage_frame_callback) { + wl_callback_destroy(wind->surface_damage_frame_callback); } #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index e77cb80a5..703ec53da 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -42,9 +42,10 @@ typedef struct { SDL_Window *sdlwindow; SDL_VideoData *waylandData; struct wl_surface *surface; - struct wl_callback *frame_callback; - struct wl_event_queue *frame_event_queue; - struct wl_surface *frame_surface_wrapper; + struct wl_callback *gles_swap_frame_callback; + struct wl_event_queue *gles_swap_frame_event_queue; + struct wl_surface *gles_swap_frame_surface_wrapper; + struct wl_callback *surface_damage_frame_callback; union { #ifdef HAVE_LIBDECOR_H