[Cogl] [PATCH 2/2] wayland: Don't delay resize if nothing is drawn since last swap

Robert Bragg robert at sixbynine.org
Wed May 29 10:46:55 PDT 2013


Cool, thanks for all the updates, this looks good to land to me:

Reviewed-by: Robert Bragg <robert at linux.intel.com>

thanks,
- Robert

On Wed, May 29, 2013 at 5:44 PM, Neil Roberts <neil at linux.intel.com> wrote:
> After discussing with Kristian Høgsberg it seems that the semantics of
> wl_egl_window_resize is meant to be that if nothing has been drawn to
> the framebuffer since the last swap then the resize will take effect
> immediately. Cogl was previously always delaying the call to
> wl_egl_window_resize until the next swap. That meant that if you
> wanted to resize the surface you would have to call
> cogl_wayland_onscreen_resize and then redundantly draw a frame at the
> old size so that you can swap to get the resize to occur before
> drawing again at the right size. Typically an application would decide
> to resize at the start of its paint sequence so it should be able to
> just resize immediately.
>
> In current Mesa master it seems that there is a bug which means that
> it won't actually delay a resize that is done mid-scene and instead it
> will just discard what came before. To get consistent behaviour in
> Cogl, the code to delay the call to wl_egl_window_resize is still used
> if it determines that the buffer is dirty. There is an existing
> _cogl_framebuffer_mark_mid_scene call which was being used to track
> when the framebuffer becomes dirty since the last clear. This function
> is now also used to track a new flag to track whether something has
> been drawn since the last swap. It is called ‘mid_scene’ under the
> assumption that this may also be useful for other things later.
>
> cogl_framebuffer_clear has been slightly altered to always call
> _cogl_framebuffer_mark_mid_scene even if it determines that it doesn't
> need to clear because the framebuffer should still be considered to be
> in the middle of a scene. Adding a quad to the journal now also begins
> the scene.
>
> This also fixes a potential bug where it looks like pending_dx/dy were
> never cleared so they would always be accumulated even after the
> resize is flushed.
> ---
>  cogl/cogl-framebuffer-private.h       |  4 ++++
>  cogl/cogl-framebuffer.c               |  5 +++--
>  cogl/cogl-journal.c                   |  6 ++++++
>  cogl/cogl-onscreen.c                  |  2 ++
>  cogl/cogl-onscreen.h                  | 21 ++++++++++++--------
>  cogl/winsys/cogl-winsys-egl-wayland.c | 37 ++++++++++++++++++++++++++---------
>  6 files changed, 56 insertions(+), 19 deletions(-)
>
> diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
> index bc1b4c9..2dfcb6e 100644
> --- a/cogl/cogl-framebuffer-private.h
> +++ b/cogl/cogl-framebuffer-private.h
> @@ -170,6 +170,10 @@ struct _CoglFramebuffer
>    int                 clear_clip_y1;
>    CoglBool            clear_clip_dirty;
>
> +  /* Whether something has been drawn to the buffer since the last
> +   * swap buffers or swap region. */
> +  CoglBool            mid_scene;
> +
>    /* driver specific */
>    CoglBool            dirty_bitmasks;
>    CoglFramebufferBits bits;
> diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
> index a6a9a8d..4faad61 100644
> --- a/cogl/cogl-framebuffer.c
> +++ b/cogl/cogl-framebuffer.c
> @@ -228,6 +228,7 @@ void
>  _cogl_framebuffer_mark_mid_scene (CoglFramebuffer *framebuffer)
>  {
>    framebuffer->clear_clip_dirty = TRUE;
> +  framebuffer->mid_scene = TRUE;
>  }
>
>  void
> @@ -353,6 +354,8 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
>
>  cleared:
>
> +  _cogl_framebuffer_mark_mid_scene (framebuffer);
> +
>    if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
>      {
>        /* For our fast-path for reading back a single pixel of simple
> @@ -380,8 +383,6 @@ cleared:
>            /* FIXME: set degenerate clip */
>          }
>      }
> -  else
> -    _cogl_framebuffer_mark_mid_scene (framebuffer);
>  }
>
>  /* Note: the 'buffers' and 'color' arguments were switched around on
> diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
> index f651a55..518a797 100644
> --- a/cogl/cogl-journal.c
> +++ b/cogl/cogl-journal.c
> @@ -1445,6 +1445,12 @@ _cogl_journal_log_quad (CoglJournal  *journal,
>
>    COGL_TIMER_START (_cogl_uprof_context, log_timer);
>
> +  /* Adding something to the journal should mean that we are in the
> +   * middle of the scene. Although this will also end up being set
> +   * when the journal is actually flushed, we set it here explicitly
> +   * so that we will know sooner */
> +  _cogl_framebuffer_mark_mid_scene (framebuffer);
> +
>    /* If the framebuffer was previously empty then we'll take a
>       reference to the current framebuffer. This reference will be
>       removed when the journal is flushed */
> diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
> index 03c4849..9f4a215 100644
> --- a/cogl/cogl-onscreen.c
> +++ b/cogl/cogl-onscreen.c
> @@ -172,6 +172,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
>      }
>
>    onscreen->frame_counter++;
> +  framebuffer->mid_scene = FALSE;
>  }
>
>  void
> @@ -227,6 +228,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
>      }
>
>    onscreen->frame_counter++;
> +  framebuffer->mid_scene = FALSE;
>  }
>
>  int
> diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
> index 2bce1c4..2646d40 100644
> --- a/cogl/cogl-onscreen.h
> +++ b/cogl/cogl-onscreen.h
> @@ -212,12 +212,12 @@ cogl_wayland_onscreen_set_foreign_surface (CoglOnscreen *onscreen,
>   * @width: The desired width of the framebuffer
>   * @height: The desired height of the framebuffer
>   * @offset_x: A relative x offset for the new framebuffer
> - * @offset_y: A relative x offset for the new framebuffer
> + * @offset_y: A relative y offset for the new framebuffer
>   *
> - * Queues a resize of the given @onscreen framebuffer which will be applied
> - * during the next swap buffers request. Since a buffer is usually conceptually
> - * scaled with a center point the @offset_x and @offset_y arguments allow the
> - * newly allocated buffer to be positioned relative to the old buffer size.
> + * Resizes the backbuffer of the given @onscreen framebuffer to the
> + * given size. Since a buffer is usually conceptually scaled with a
> + * center point the @offset_x and @offset_y arguments allow the newly
> + * allocated buffer to be positioned relative to the old buffer size.
>   *
>   * For example a buffer that is being resized by moving the bottom right
>   * corner, and the top left corner is remaining static would use x and y
> @@ -228,9 +228,14 @@ cogl_wayland_onscreen_set_foreign_surface (CoglOnscreen *onscreen,
>   * x/y_size_increase is how many pixels bigger the buffer is on the x and y
>   * axis.
>   *
> - * If cogl_wayland_onscreen_resize() is called multiple times before the next
> - * swap buffers request then the relative x and y offsets accumulate instead of
> - * being replaced. The @width and @height values superseed the old values.
> + * Note that if some drawing commands have been applied to the
> + * framebuffer since the last swap buffers then the resize will be
> + * queued and will only take effect in the next swap buffers.
> + *
> + * If multiple calls to cogl_wayland_onscreen_resize() get queued
> + * before the next swap buffers request then the relative x and y
> + * offsets accumulate instead of being replaced. The @width and
> + * @height values superseed the old values.
>   *
>   * Since: 1.10
>   * Stability: unstable
> diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c
> index 95f3008..6732547 100644
> --- a/cogl/winsys/cogl-winsys-egl-wayland.c
> +++ b/cogl/winsys/cogl-winsys-egl-wayland.c
> @@ -419,15 +419,8 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
>  }
>
>  static void
> -_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
> -                                                const int *rectangles,
> -                                                int n_rectangles)
> +flush_pending_resize (CoglOnscreen *onscreen)
>  {
> -  CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
> -  CoglContext *context = fb->context;
> -  CoglRenderer *renderer = context->display->renderer;
> -  CoglRendererEGL *egl_renderer = renderer->winsys;
> -  CoglRendererWayland *wayland_renderer = egl_renderer->platform;
>    CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
>    CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;
>
> @@ -439,11 +432,28 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
>                              wayland_onscreen->pending_dx,
>                              wayland_onscreen->pending_dy);
>
> -      _cogl_framebuffer_winsys_update_size (fb,
> +      _cogl_framebuffer_winsys_update_size (COGL_FRAMEBUFFER (onscreen),
>                                              wayland_onscreen->pending_width,
>                                              wayland_onscreen->pending_height);
> +
> +      wayland_onscreen->pending_dx = 0;
> +      wayland_onscreen->pending_dy = 0;
>        wayland_onscreen->has_pending = FALSE;
>      }
> +}
> +
> +static void
> +_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
> +                                                const int *rectangles,
> +                                                int n_rectangles)
> +{
> +  CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
> +  CoglContext *context = fb->context;
> +  CoglRenderer *renderer = context->display->renderer;
> +  CoglRendererEGL *egl_renderer = renderer->winsys;
> +  CoglRendererWayland *wayland_renderer = egl_renderer->platform;
> +
> +  flush_pending_resize (onscreen);
>
>    parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
>                                                      rectangles,
> @@ -640,6 +650,15 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
>            wayland_onscreen->pending_dx += offset_x;
>            wayland_onscreen->pending_dy += offset_y;
>            wayland_onscreen->has_pending = TRUE;
> +
> +          /* If nothing has been drawn to the framebuffer since the
> +           * last swap then wl_egl_window_resize will take effect
> +           * immediately. Otherwise it might not take effect until the
> +           * next swap, depending on the version of Mesa. To keep
> +           * consistent behaviour we'll delay the resize until the
> +           * next swap unless we're sure nothing has been drawn */
> +          if (!fb->mid_scene)
> +            flush_pending_resize (onscreen);
>          }
>      }
>    else
> --
> 1.7.11.3.g3c3efa5
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl


More information about the Cogl mailing list