[Cogl] [PATCH v2] onscreen: Adds swap_buffers_with_damage api
Neil Roberts
neil at linux.intel.com
Tue Apr 30 06:05:45 PDT 2013
Great, thanks. Looks good to me.
Reviewed-by: Neil Roberts <neil at linux.intel.com>
Regards,
- Neil
Robert Bragg <robert at sixbynine.org> writes:
> From: Robert Bragg <robert at linux.intel.com>
>
> Compared to the last version this removes the redundant onscreen_swap_buffers
> winsys vfunc and removes some redundant #ifdef EGL_EXT_swap_buffers_with_damage
> guards.
>
> -- >8 --
>
> 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 | 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>
> --
> 1.8.2.1
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl
---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
More information about the Cogl
mailing list