From 87ce1b21f9f399a1b9633bbcac5817604780da7c Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 16 Jan 2012 12:30:06 +0000 Subject: [PATCH] wayland: perform buffer resizes lazily at swap buffers Resizing a wayland client framebuffer should not affect the viewport of additional primitives drawn to that framebuffer before the next swap buffers request nor should querying the framebuffer's width and height be affected until the next swap buffers request completes. This patch changes cogl_wayland_onscreen_resize() so it only saves the new geometry as "pending" state internal to the given CoglOnscreen. Only when cogl_framebuffer_swap_buffers() is next called will the pending size be flushed to the wayland egl api. --- cogl/cogl-onscreen.h | 29 ++++++++++++++++ cogl/winsys/cogl-winsys-egl-wayland.c | 49 ++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h index bc11217b0..dbc4784ca 100644 --- a/cogl/cogl-onscreen.h +++ b/cogl/cogl-onscreen.h @@ -185,6 +185,35 @@ cogl_wayland_onscreen_get_surface (CoglOnscreen *onscreen); struct wl_shell_surface * cogl_wayland_onscreen_get_shell_surface (CoglOnscreen *onscreen); +/** + * cogl_wayland_onscreen_resize: + * @onscreen: A #CoglOnscreen framebuffer + * @width: The desired width of the framebuffer + * @height: The desired height of the framebuffer + * @offset_x: A relative x offset for the new framebuffer + * @offset_y: A relative x offset for the new framebuffer + * + * Queues a resize of the given @onscreen framebuffer which will be applied + * during the next swap buffers request. Since a buffer is usually conceptually + * scaled with a center point the @offset_x and @offset_y arguments allow the + * newly allocated buffer to be positioned relative to the old buffer size. + * + * For example a buffer that is being resized by moving the bottom right + * corner, and the top left corner is remaining static would use x and y + * offsets of (0, 0) since the top-left of the new buffer should have the same + * position as the old buffer. If the center of the old buffer is being zoomed + * into then all the corners of the new buffer move out from the center and the x + * and y offsets would be (-half_x_size_increase, -half_y_size_increase) where + * x/y_size_increase is how many pixels bigger the buffer is on the x and y + * axis. + * + * If cogl_wayland_onscreen_resize() is called multiple times before the next + * swap buffers request then the relative x and y offsets accumulate instead of + * being replaced. The @width and @height values superseed the old values. + * + * Since: 1.10 + * Stability: unstable + */ void cogl_wayland_onscreen_resize (CoglOnscreen *onscreen, int width, diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c index 729ecac3a..fe75e07f3 100644 --- a/cogl/winsys/cogl-winsys-egl-wayland.c +++ b/cogl/winsys/cogl-winsys-egl-wayland.c @@ -60,6 +60,15 @@ typedef struct _CoglOnscreenWayland struct wl_egl_window *wayland_egl_native_window; struct wl_surface *wayland_surface; struct wl_shell_surface *wayland_shell_surface; + + /* Resizing a wayland framebuffer doesn't take affect + * until the next swap buffers request, so we have to + * track the resize geometry until then... */ + int pending_width; + int pending_height; + int pending_dx; + int pending_dy; + gboolean has_pending; } CoglOnscreenWayland; static void @@ -363,12 +372,29 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) static void _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) { - CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = fb->context; CoglRenderer *renderer = context->display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererWayland *wayland_renderer = egl_renderer->platform; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform; - /* First chain-up */ + if (wayland_onscreen->has_pending) + { + wl_egl_window_resize (wayland_onscreen->wayland_egl_native_window, + wayland_onscreen->pending_width, + wayland_onscreen->pending_height, + wayland_onscreen->pending_dx, + wayland_onscreen->pending_dy); + + _cogl_framebuffer_winsys_update_size (fb, + wayland_onscreen->pending_width, + wayland_onscreen->pending_height); + wayland_onscreen->has_pending = FALSE; + } + + /* chain-up */ parent_vtable->onscreen_swap_buffers (onscreen); /* @@ -514,13 +540,20 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen, CoglOnscreenEGL *egl_onscreen = onscreen->winsys; CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform; - wl_egl_window_resize (wayland_onscreen->wayland_egl_native_window, - width, - height, - offset_x, - offset_y); - _cogl_framebuffer_winsys_update_size (fb, width, height); + if (cogl_framebuffer_get_width (fb) != width || + cogl_framebuffer_get_height (fb) != height || + offset_x || + offset_y) + { + wayland_onscreen->pending_width = width; + wayland_onscreen->pending_height = height; + wayland_onscreen->pending_dx += offset_x; + wayland_onscreen->pending_dy += offset_y; + wayland_onscreen->has_pending = TRUE; + } } + else + _cogl_framebuffer_winsys_update_size (fb, width, height); } static const CoglWinsysEGLVtable