[cogl/wip/wayland: 6/8] onscreen: Adds swap_buffers_with_damage api



commit bc958eb820a5ab1b24421a57a2d9b137e682a4b4
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.

 cogl/cogl-onscreen.c                            |   26 +++++++++++++++++
 cogl/cogl-onscreen.h                            |   35 +++++++++++++++++++++++
 cogl/winsys/cogl-winsys-egl-feature-functions.h |   13 ++++++++
 cogl/winsys/cogl-winsys-egl-kms.c               |   29 +++++++++++++++++--
 cogl/winsys/cogl-winsys-egl-wayland.c           |   27 ++++++++++++++++-
 cogl/winsys/cogl-winsys-egl.c                   |   28 +++++++++++++++++-
 cogl/winsys/cogl-winsys-private.h               |    5 +++
 7 files changed, 156 insertions(+), 7 deletions(-)
---
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 7c81ec0..49dcd80 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -143,6 +143,32 @@ cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
 }
 
 void
+cogl_framebuffer_swap_buffers_with_damage (CoglFramebuffer *framebuffer,
+                                           const int *rectangles,
+                                           int n_rectangles)
+{
+  const CoglWinsysVtable *winsys;
+
+  _COGL_RETURN_IF_FAIL  (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
+
+  /* FIXME: we shouldn't need to flush *all* journals here! */
+  cogl_flush ();
+  winsys = _cogl_framebuffer_get_winsys (framebuffer);
+
+  if (winsys->onscreen_swap_buffers_with_damage)
+    winsys->onscreen_swap_buffers_with_damage (COGL_ONSCREEN (framebuffer),
+                                               rectangles,
+                                               n_rectangles);
+  else
+    winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
+
+  cogl_framebuffer_discard_buffers (framebuffer,
+                                    COGL_BUFFER_BIT_COLOR |
+                                    COGL_BUFFER_BIT_DEPTH |
+                                    COGL_BUFFER_BIT_STENCIL);
+}
+
+void
 cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
                               const int *rectangles,
                               int n_rectangles)
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index dbc4784..528b92d 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -309,6 +309,41 @@ void
 cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
 
 /**
+ * cogl_framebuffer_swap_buffers_with_damage:
+ *
+ * Swaps the current back buffer being rendered too, to the front for display.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Whenever possible it is recommended that applications use this function
+ * instead of cogl_framebuffer_swap_buffers() to improve performance when
+ * running under a compositor.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+cogl_framebuffer_swap_buffers_with_damage (CoglFramebuffer *framebuffer,
+                                           const int *rectangles,
+                                           int n_rectangles);
+
+/**
  * cogl_framebuffer_swap_region:
  * @framebuffer: A #CoglFramebuffer
  * @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 e979724..84110b8 100644
--- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
@@ -103,3 +103,16 @@ COGL_WINSYS_FEATURE_BEGIN (surfaceless_gles2,
                            "surfaceless_gles2\0",
                            COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES2)
 COGL_WINSYS_FEATURE_END ()
+#ifdef EGL_EXT_swap_buffers_with_damage
+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 ()
+#endif
+
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 4c5293b..6d760c6 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -637,7 +637,9 @@ handle_drm_event (CoglRendererKMS *kms_renderer)
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_real (CoglOnscreen *onscreen,
+                                         const int *rectangles,
+                                         int n_rectangles)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
   CoglDisplayEGL *egl_display = context->display->winsys;
@@ -655,8 +657,13 @@ _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);
+  /* First chain-up. */
+  if (rectangles == NULL)
+    parent_vtable->onscreen_swap_buffers (onscreen);
+  else
+    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_get_bo (kms_onscreen->surface);
@@ -726,6 +733,20 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
     }
 }
 
+static void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+  _cogl_winsys_onscreen_swap_buffers_real (onscreen, NULL, 0);
+}
+
+static void
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
+{
+  _cogl_winsys_onscreen_swap_buffers_real (onscreen, rectangles, n_rectangles);
+}
+
 static gboolean
 _cogl_winsys_egl_context_init (CoglContext *context,
                                GError **error)
@@ -942,6 +963,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.poll_get_info = _cogl_winsys_poll_get_info;
       vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c
index fe75e07..6b1771c 100644
--- a/cogl/winsys/cogl-winsys-egl-wayland.c
+++ b/cogl/winsys/cogl-winsys-egl-wayland.c
@@ -370,7 +370,9 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
 }
 
 static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+_cogl_winsys_onscreen_swap_buffers_real (CoglOnscreen *onscreen,
+                                         const int *rectangles,
+                                         int n_rectangles)
 {
   CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = fb->context;
@@ -395,7 +397,12 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
     }
 
   /* chain-up */
-  parent_vtable->onscreen_swap_buffers (onscreen);
+  if (rectangles == NULL)
+    parent_vtable->onscreen_swap_buffers (onscreen);
+  else
+    parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
+                                                      rectangles,
+                                                      n_rectangles);
 
   /*
    * The implementation of eglSwapBuffers may do a flush however the semantics
@@ -406,6 +413,20 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
   wl_display_flush (wayland_renderer->wayland_display);
 }
 
+static void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+  _cogl_winsys_onscreen_swap_buffers_real (onscreen, NULL, 0);
+}
+
+static void
+_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+                                                const int *rectangles,
+                                                int n_rectangles)
+{
+  _cogl_winsys_onscreen_swap_buffers_real (onscreen, rectangles, n_rectangles);
+}
+
 void
 cogl_wayland_renderer_set_foreign_display (CoglRenderer *renderer,
                                            struct wl_display *display)
@@ -589,6 +610,8 @@ _cogl_winsys_egl_wayland_get_vtable (void)
       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 96b91c2..bb4eadc 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -592,7 +592,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;
@@ -608,7 +610,27 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
                                  COGL_FRAMEBUFFER (onscreen),
                                  COGL_FRAMEBUFFER_STATE_BIND);
 
-  eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
+#ifdef EGL_EXT_swap_buffers_with_damage
+  if (egl_renderer->pf_eglSwapBuffersWithDamage)
+    {
+      if (egl_renderer->pf_eglSwapBuffersWithDamage (egl_renderer->edpy,
+                                                     egl_onscreen->egl_surface,
+                                                     rectangles,
+                                                     n_rectangles) == EGL_FALSE)
+        g_warning ("Error reported by eglSwapBuffersWithDamage");
+    }
+  else
+#endif
+    eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
+}
+
+static void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
+  int rect[] = {0, 0, fb->width, fb->height};
+
+  _cogl_winsys_onscreen_swap_buffers_with_damage (onscreen, rect, 1);
 }
 
 static void
@@ -654,6 +676,8 @@ static CoglWinsysVtable _cogl_winsys_vtable =
     .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_update_swap_throttled =
       _cogl_winsys_onscreen_update_swap_throttled,
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 8b864ec..0bbcc0a 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -107,6 +107,11 @@ typedef struct _CoglWinsysVtable
   /* Optional functions */
 
   void
+  (*onscreen_swap_buffers_with_damage) (CoglOnscreen *onscreen,
+                                        const int *rectangles,
+                                        int n_rectangles);
+
+  void
   (*onscreen_swap_region) (CoglOnscreen *onscreen,
                            const int *rectangles,
                            int n_rectangles);



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