[cogl] onscreen: Adds swap_buffers_with_damage api



commit 0d9684c7b7c2018bb42715c369555330d38514a2
Author: Robert Bragg <robert linux intel com>
Date:   Tue Feb 7 17:59:51 2012 +0000

    onscreen: Adds swap_buffers_with_damage api
    
    This adds api to be able requests a swap_buffers and also pass a list of
    damage rectangles that can be passed on to a compositor to enable it to
    minimize how much of the screen it needs to recompose.
    
    Reviewed-by: Neil Roberts <neil linux intel com>

 cogl/cogl-onscreen.c                            |   13 ++++-
 cogl/cogl-onscreen.h                            |   59 +++++++++++++++++++++++
 cogl/winsys/cogl-winsys-egl-feature-functions.h |   11 ++++
 cogl/winsys/cogl-winsys-egl-kms.c               |   12 +++--
 cogl/winsys/cogl-winsys-egl-wayland.c           |   12 +++--
 cogl/winsys/cogl-winsys-egl.c                   |   31 +++++++++++-
 cogl/winsys/cogl-winsys-glx.c                   |    7 ++-
 cogl/winsys/cogl-winsys-private.h               |    4 +-
 cogl/winsys/cogl-winsys-sdl.c                   |    7 ++-
 cogl/winsys/cogl-winsys-sdl2.c                  |    7 ++-
 cogl/winsys/cogl-winsys-stub.c                  |    7 ++-
 cogl/winsys/cogl-winsys-wgl.c                   |    7 ++-
 doc/reference/cogl2/cogl2-sections.txt          |    1 +
 13 files changed, 154 insertions(+), 24 deletions(-)
---
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 22127a4..03c4849 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -133,7 +133,9 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
 }
 
 void
-cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
+cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                        const int *rectangles,
+                                        int n_rectangles)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   const CoglWinsysVtable *winsys;
@@ -148,7 +150,8 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
   _cogl_framebuffer_flush_journal (framebuffer);
 
   winsys = _cogl_framebuffer_get_winsys (framebuffer);
-  winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
+  winsys->onscreen_swap_buffers_with_damage (onscreen,
+                                             rectangles, n_rectangles);
   cogl_framebuffer_discard_buffers (framebuffer,
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
@@ -172,6 +175,12 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
 }
 
 void
+cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+  cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0);
+}
+
+void
 cogl_onscreen_swap_region (CoglOnscreen *onscreen,
                            const int *rectangles,
                            int n_rectangles)
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index fa4099b..54881a8 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -345,6 +345,12 @@ cogl_onscreen_hide (CoglOnscreen *onscreen);
  * start a new frame that incrementally builds on the contents of the previous
  * frame.
  *
+ * <note>It is highly recommended that applications use
+ * cogl_onscreen_swap_buffers_with_damage() instead whenever possible
+ * and also use the cogl_onscreen_get_buffer_age() api so they can
+ * perform incremental updates to older buffers instead of having to
+ * render a full buffer for every frame.</note>
+ *
  * Since: 1.10
  * Stability: unstable
  */
@@ -400,6 +406,59 @@ int
 cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
 
 /**
+ * cogl_onscreen_swap_buffers_with_damage:
+ * @onscreen: A #CoglOnscreen framebuffer
+ * @rectangles: An array of integer 4-tuples representing damaged
+ *              rectangles as (x, y, width, height) tuples.
+ * @n_rectangles: The number of 4-tuples to be read from @rectangles
+ *
+ * Swaps the current back buffer being rendered too, to the front for
+ * display and provides information to any system compositor about
+ * what regions of the buffer have changed (damage) with respect to
+ * the last swapped buffer.
+ *
+ * This function has the same semantics as
+ * cogl_framebuffer_swap_buffers() except that it additionally allows
+ * applications to pass a list of damaged rectangles which may be
+ * passed on to a compositor so that it can minimize how much of the
+ * screen is redrawn in response to this applications newly swapped
+ * front buffer.
+ *
+ * For example if your application is only animating a small object in
+ * the corner of the screen and everything else is remaining static
+ * then it can help the compositor to know that only the bottom right
+ * corner of your newly swapped buffer has really changed with respect
+ * to your previously swapped front buffer.
+ *
+ * If @n_rectangles is 0 then the whole buffer will implicitly be
+ * reported as damaged as if cogl_onscreen_swap_buffers() had been
+ * called.
+ *
+ * This function also implicitly discards the contents of the color,
+ * depth and stencil buffers as if cogl_framebuffer_discard_buffers()
+ * were used. The significance of the discard is that you should not
+ * expect to be able to start a new frame that incrementally builds on
+ * the contents of the previous frame. If you want to perform
+ * incremental updates to older back buffers then please refer to the
+ * cogl_onscreen_get_buffer_age() api.
+ *
+ * Whenever possible it is recommended that applications use this
+ * function instead of cogl_onscreen_swap_buffers() to improve
+ * performance when running under a compositor.
+ *
+ * <note>It is highly recommended to use this API in conjunction with
+ * the cogl_onscreen_get_buffer_age() api so that your application can
+ * perform incremental rendering based on old back buffers.</note>
+ *
+ * Since: 1.16
+ * Stability: unstable
+ */
+void
+cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                        const int *rectangles,
+                                        int n_rectangles);
+
+/**
  * cogl_onscreen_swap_region:
  * @onscreen: A #CoglOnscreen framebuffer
  * @rectangles: An array of integer 4-tuples representing rectangles as
diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h
index 5068090..24cc805 100644
--- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
@@ -101,3 +101,14 @@ COGL_WINSYS_FEATURE_BEGIN (buffer_age,
 COGL_WINSYS_FEATURE_END ()
 
 #endif
+
+COGL_WINSYS_FEATURE_BEGIN (swap_buffers_with_damage,
+                           "EXT\0",
+                           "swap_buffers_with_damage\0",
+                           0)
+COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersWithDamage,
+                              (EGLDisplay dpy,
+                               EGLSurface surface,
+                               const EGLint *rects,
+                               EGLint n_rects))
+COGL_WINSYS_FEATURE_END ()
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 37f7cc3..f7c65db 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -719,7 +719,9 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
   CoglDisplayEGL *egl_display = context->display->winsys;
@@ -737,8 +739,9 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
   while (kms_onscreen->next_fb_id != 0)
     handle_drm_event (kms_renderer);
 
-  /* First chain-up. This will call eglSwapBuffers */
-  parent_vtable->onscreen_swap_buffers (onscreen);
+  parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
+                                                    rectangles,
+                                                    n_rectangles);
 
   /* Now we need to set the CRTC to whatever is the front buffer */
   kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);
@@ -957,7 +960,8 @@ _cogl_winsys_egl_kms_get_vtable (void)
 
       /* The KMS winsys doesn't support swap region */
       vtable.onscreen_swap_region = NULL;
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
 
       vtable_inited = TRUE;
     }
diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c
index a288776..fe8b938 100644
--- a/cogl/winsys/cogl-winsys-egl-wayland.c
+++ b/cogl/winsys/cogl-winsys-egl-wayland.c
@@ -417,7 +417,9 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = fb->context;
@@ -441,8 +443,9 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
       wayland_onscreen->has_pending = FALSE;
     }
 
-  /* chain-up */
-  parent_vtable->onscreen_swap_buffers (onscreen);
+  parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
+                                                    rectangles,
+                                                    n_rectangles);
 
   /*
    * The implementation of eglSwapBuffers may do a flush however the semantics
@@ -647,7 +650,8 @@ _cogl_winsys_egl_wayland_get_vtable (void)
       vtable.renderer_connect = _cogl_winsys_renderer_connect;
       vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
 
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
 
       vtable_inited = TRUE;
     }
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index f9e3ae4..ae4f7e8 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -784,7 +784,9 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
   CoglRenderer *renderer = context->display->renderer;
@@ -800,7 +802,29 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
                                  COGL_FRAMEBUFFER (onscreen),
                                  COGL_FRAMEBUFFER_STATE_BIND);
 
-  eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
+  if (n_rectangles && egl_renderer->pf_eglSwapBuffersWithDamage)
+    {
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
+      size_t size = n_rectangles * sizeof (int) * 4;
+      int *flipped = alloca (size);
+      int i;
+
+      memcpy (flipped, rectangles, size);
+      for (i = 0; i < n_rectangles; i++)
+        {
+          const int *rect = rectangles + 4 * i;
+          int *flip_rect = flipped + 4 * i;
+          flip_rect[1] = fb->height - rect[1] - rect[3];
+        }
+
+      if (egl_renderer->pf_eglSwapBuffersWithDamage (egl_renderer->edpy,
+                                                     egl_onscreen->egl_surface,
+                                                     flipped,
+                                                     n_rectangles) == EGL_FALSE)
+        g_warning ("Error reported by eglSwapBuffersWithDamage");
+    }
+  else
+    eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
 }
 
 static void
@@ -901,7 +925,8 @@ static CoglWinsysVtable _cogl_winsys_vtable =
     .onscreen_init = _cogl_winsys_onscreen_init,
     .onscreen_deinit = _cogl_winsys_onscreen_deinit,
     .onscreen_bind = _cogl_winsys_onscreen_bind,
-    .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
+    .onscreen_swap_buffers_with_damage =
+      _cogl_winsys_onscreen_swap_buffers_with_damage,
     .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
     .onscreen_get_buffer_age = _cogl_winsys_onscreen_get_buffer_age,
     .onscreen_update_swap_throttled =
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 5fdf59b..d800cdd 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -1857,7 +1857,9 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = framebuffer->context;
@@ -2610,7 +2612,8 @@ static CoglWinsysVtable _cogl_winsys_vtable =
     .onscreen_init = _cogl_winsys_onscreen_init,
     .onscreen_deinit = _cogl_winsys_onscreen_deinit,
     .onscreen_bind = _cogl_winsys_onscreen_bind,
-    .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
+    .onscreen_swap_buffers_with_damage =
+      _cogl_winsys_onscreen_swap_buffers_with_damage,
     .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
     .onscreen_get_buffer_age = _cogl_winsys_onscreen_get_buffer_age,
     .onscreen_update_swap_throttled =
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 2e47fd6..170cf2f 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -111,7 +111,9 @@ typedef struct _CoglWinsysVtable
   (*onscreen_bind) (CoglOnscreen *onscreen);
 
   void
-  (*onscreen_swap_buffers) (CoglOnscreen *onscreen);
+  (*onscreen_swap_buffers_with_damage) (CoglOnscreen *onscreen,
+                                        const int *rectangles,
+                                        int n_rectangles);
 
   void
   (*onscreen_update_swap_throttled) (CoglOnscreen *onscreen);
diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c
index 6cb246e..ed8212e 100644
--- a/cogl/winsys/cogl-winsys-sdl.c
+++ b/cogl/winsys/cogl-winsys-sdl.c
@@ -362,7 +362,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   SDL_GL_SwapBuffers ();
 }
@@ -430,7 +432,8 @@ _cogl_winsys_sdl_get_vtable (void)
       vtable.onscreen_init = _cogl_winsys_onscreen_init;
       vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
       vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
       vtable.onscreen_update_swap_throttled =
         _cogl_winsys_onscreen_update_swap_throttled;
       vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
diff --git a/cogl/winsys/cogl-winsys-sdl2.c b/cogl/winsys/cogl-winsys-sdl2.c
index dc0fad5..5595f46 100644
--- a/cogl/winsys/cogl-winsys-sdl2.c
+++ b/cogl/winsys/cogl-winsys-sdl2.c
@@ -497,7 +497,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglOnscreenSdl2 *sdl_onscreen = onscreen->winsys;
 
@@ -572,7 +574,8 @@ _cogl_winsys_sdl_get_vtable (void)
       vtable.onscreen_init = _cogl_winsys_onscreen_init;
       vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
       vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
       vtable.onscreen_update_swap_throttled =
         _cogl_winsys_onscreen_update_swap_throttled;
       vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
diff --git a/cogl/winsys/cogl-winsys-stub.c b/cogl/winsys/cogl-winsys-stub.c
index aee70a9..55ae3e2 100644
--- a/cogl/winsys/cogl-winsys-stub.c
+++ b/cogl/winsys/cogl-winsys-stub.c
@@ -133,7 +133,9 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
 }
 
@@ -176,7 +178,8 @@ _cogl_winsys_stub_get_vtable (void)
       vtable.onscreen_init = _cogl_winsys_onscreen_init;
       vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
       vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
       vtable.onscreen_update_swap_throttled =
         _cogl_winsys_onscreen_update_swap_throttled;
       vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c
index 33e7ad2..ce2e97c 100644
--- a/cogl/winsys/cogl-winsys-wgl.c
+++ b/cogl/winsys/cogl-winsys-wgl.c
@@ -836,7 +836,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
 {
   CoglOnscreenWgl *wgl_onscreen = onscreen->winsys;
 
@@ -901,7 +903,8 @@ _cogl_winsys_wgl_get_vtable (void)
       vtable.onscreen_init = _cogl_winsys_onscreen_init;
       vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
       vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
-      vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+      vtable.onscreen_swap_buffers_with_damage =
+        _cogl_winsys_onscreen_swap_buffers_with_damage;
       vtable.onscreen_update_swap_throttled =
         _cogl_winsys_onscreen_update_swap_throttled;
       vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
diff --git a/doc/reference/cogl2/cogl2-sections.txt b/doc/reference/cogl2/cogl2-sections.txt
index be9d691..68769bd 100644
--- a/doc/reference/cogl2/cogl2-sections.txt
+++ b/doc/reference/cogl2/cogl2-sections.txt
@@ -562,6 +562,7 @@ cogl_onscreen_remove_resize_callback
 
 <SUBSECTION>
 cogl_onscreen_swap_buffers
+cogl_onscreen_swap_buffers_with_damage
 cogl_onscreen_swap_region
 cogl_onscreen_set_swap_throttled
 </SECTION>


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