[cogl] wayland: perform buffer resizes lazily at swap buffers



commit 87ce1b21f9f399a1b9633bbcac5817604780da7c
Author: Robert Bragg <robert linux intel com>
Date:   Mon Jan 16 12:30:06 2012 +0000

    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 bc11217..dbc4784 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 729ecac..fe75e07 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]