mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
wayland: Don't delay resize if nothing is drawn since last swap
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. Reviewed-by: Robert Bragg <robert@linux.intel.com> (cherry picked from commit 945689a62903990a20abb87a85d2c96eb3985fe7)
This commit is contained in:
parent
2a42576fe7
commit
45e18e0fb7
@ -170,6 +170,10 @@ struct _CoglFramebuffer
|
|||||||
int clear_clip_y1;
|
int clear_clip_y1;
|
||||||
CoglBool clear_clip_dirty;
|
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 */
|
/* driver specific */
|
||||||
CoglBool dirty_bitmasks;
|
CoglBool dirty_bitmasks;
|
||||||
CoglFramebufferBits bits;
|
CoglFramebufferBits bits;
|
||||||
|
@ -236,6 +236,7 @@ void
|
|||||||
_cogl_framebuffer_mark_mid_scene (CoglFramebuffer *framebuffer)
|
_cogl_framebuffer_mark_mid_scene (CoglFramebuffer *framebuffer)
|
||||||
{
|
{
|
||||||
framebuffer->clear_clip_dirty = TRUE;
|
framebuffer->clear_clip_dirty = TRUE;
|
||||||
|
framebuffer->mid_scene = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -398,6 +399,8 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
|
|||||||
|
|
||||||
cleared:
|
cleared:
|
||||||
|
|
||||||
|
_cogl_framebuffer_mark_mid_scene (framebuffer);
|
||||||
|
|
||||||
if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
|
if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
|
||||||
{
|
{
|
||||||
/* For our fast-path for reading back a single pixel of simple
|
/* For our fast-path for reading back a single pixel of simple
|
||||||
@ -425,8 +428,6 @@ cleared:
|
|||||||
/* FIXME: set degenerate clip */
|
/* FIXME: set degenerate clip */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
_cogl_framebuffer_mark_mid_scene (framebuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: the 'buffers' and 'color' arguments were switched around on
|
/* Note: the 'buffers' and 'color' arguments were switched around on
|
||||||
|
@ -1455,6 +1455,12 @@ _cogl_journal_log_quad (CoglJournal *journal,
|
|||||||
|
|
||||||
COGL_TIMER_START (_cogl_uprof_context, log_timer);
|
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
|
/* If the framebuffer was previously empty then we'll take a
|
||||||
reference to the current framebuffer. This reference will be
|
reference to the current framebuffer. This reference will be
|
||||||
removed when the journal is flushed */
|
removed when the journal is flushed */
|
||||||
|
@ -205,6 +205,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
onscreen->frame_counter++;
|
onscreen->frame_counter++;
|
||||||
|
framebuffer->mid_scene = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -261,6 +262,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
onscreen->frame_counter++;
|
onscreen->frame_counter++;
|
||||||
|
framebuffer->mid_scene = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -212,12 +212,12 @@ cogl_wayland_onscreen_set_foreign_surface (CoglOnscreen *onscreen,
|
|||||||
* @width: The desired width of the framebuffer
|
* @width: The desired width of the framebuffer
|
||||||
* @height: The desired height of the framebuffer
|
* @height: The desired height of the framebuffer
|
||||||
* @offset_x: A relative x offset for the new 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
|
* Resizes the backbuffer of the given @onscreen framebuffer to the
|
||||||
* during the next swap buffers request. Since a buffer is usually conceptually
|
* given size. Since a buffer is usually conceptually scaled with a
|
||||||
* scaled with a center point the @offset_x and @offset_y arguments allow the
|
* center point the @offset_x and @offset_y arguments allow the newly
|
||||||
* newly allocated buffer to be positioned relative to the old buffer size.
|
* allocated buffer to be positioned relative to the old buffer size.
|
||||||
*
|
*
|
||||||
* For example a buffer that is being resized by moving the bottom right
|
* 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
|
* 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
|
* x/y_size_increase is how many pixels bigger the buffer is on the x and y
|
||||||
* axis.
|
* axis.
|
||||||
*
|
*
|
||||||
* If cogl_wayland_onscreen_resize() is called multiple times before the next
|
* Note that if some drawing commands have been applied to the
|
||||||
* swap buffers request then the relative x and y offsets accumulate instead of
|
* framebuffer since the last swap buffers then the resize will be
|
||||||
* being replaced. The @width and @height values superseed the old values.
|
* 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
|
* Since: 1.10
|
||||||
* Stability: unstable
|
* Stability: unstable
|
||||||
|
@ -420,15 +420,8 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
flush_pending_resize (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;
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;
|
CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;
|
||||||
|
|
||||||
@ -440,11 +433,28 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
wayland_onscreen->pending_dx,
|
wayland_onscreen->pending_dx,
|
||||||
wayland_onscreen->pending_dy);
|
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_width,
|
||||||
wayland_onscreen->pending_height);
|
wayland_onscreen->pending_height);
|
||||||
|
|
||||||
|
wayland_onscreen->pending_dx = 0;
|
||||||
|
wayland_onscreen->pending_dy = 0;
|
||||||
wayland_onscreen->has_pending = FALSE;
|
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,
|
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||||
rectangles,
|
rectangles,
|
||||||
@ -641,6 +651,15 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
|
|||||||
wayland_onscreen->pending_dx += offset_x;
|
wayland_onscreen->pending_dx += offset_x;
|
||||||
wayland_onscreen->pending_dy += offset_y;
|
wayland_onscreen->pending_dy += offset_y;
|
||||||
wayland_onscreen->has_pending = TRUE;
|
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
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user