Subject: [cogl/wip/wayland: 7/9] onscreen: Adds swap_buffers_with_damage api commit 2041e208aa61b8d8ee7bcab9819064b652de0bb6 Author: Robert Bragg <robert@xxxxxxxxxxxxxxx> 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..028a642 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_framebuffer_swap_buffers_with_damage (CoglFramebuffer *framebuffer, + 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); _______________________________________________ commits-list mailing list (read only) http://mail.gnome.org/mailman/listinfo/commits-list Want to limit the commits to a few modules? Go to above URL, log in to edit your options and select the modules ('topics') you want. |