[cogl/wip/wayland: 7/9] onscreen: Adds swap_buffers_with_damage api
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/wayland: 7/9] onscreen: Adds swap_buffers_with_damage api
- Date: Wed, 22 Feb 2012 17:02:39 +0000 (UTC)
commit ccc0868a35056f5874039062bdc41e6f58fcdfb6
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 | 25 +++++++++++++
cogl/cogl-onscreen.h | 43 +++++++++++++++++++++++
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, 163 insertions(+), 7 deletions(-)
---
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 4247de6..c846855 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -145,6 +145,31 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
}
void
+cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
+ const int *rectangles,
+ int n_rectangles)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ const CoglWinsysVtable *winsys;
+
+ /* 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 (onscreen,
+ 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_onscreen_swap_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 66206ba..273b05a 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -308,6 +308,49 @@ void
cogl_onscreen_swap_buffers (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 with respect to the last
+ * swapped buffer.
+ *
+ * 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_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 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 a05412f..f46cda4 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -590,7 +590,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;
@@ -606,7 +608,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
@@ -652,6 +674,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 0e6c78b..90a63f8 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -109,6 +109,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]