mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 20:32:16 +00:00
renderer-native: Resize legacy onscreen before panting
By creating a pending gbm/EGL surface pair, only setting it on swap-buffers, we would draw onto a buffer on the old surface, then swap the buffer from the new surface, causing the first frame after a hot-plug always having no content. This was in the past not very noticable since some non-deterministic but frequent side effect in gnome-shell caused hot-plugging to always render two new frames, but after "Introduce regional stage rendering", this side effect did not occur as often, thus making it more visible. This commit updates the current gbm/EGL surface pair before painting a frame, so that when the frame is painted, the surface with the correct size is used and the buffer from correct surface is swapped. https://bugzilla.gnome.org/show_bug.cgi?id=768976
This commit is contained in:
parent
aecd98b847
commit
e891a8b628
@ -71,9 +71,6 @@ typedef struct _MetaOnscreenNative
|
||||
struct gbm_bo *next_bo;
|
||||
gboolean pending_swap_notify;
|
||||
|
||||
EGLSurface *pending_egl_surface;
|
||||
struct gbm_surface *pending_surface;
|
||||
|
||||
gboolean pending_set_crtc;
|
||||
|
||||
MetaRendererView *view;
|
||||
@ -606,33 +603,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
view = onscreen_native->view;
|
||||
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
|
||||
|
||||
if (onscreen_native->pending_egl_surface)
|
||||
{
|
||||
CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
|
||||
|
||||
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
||||
egl_onscreen->egl_surface = onscreen_native->pending_egl_surface;
|
||||
onscreen_native->pending_egl_surface = NULL;
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (fb,
|
||||
view_layout.width,
|
||||
view_layout.height);
|
||||
cogl_context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
|
||||
}
|
||||
|
||||
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
|
||||
if (onscreen_native->pending_surface)
|
||||
{
|
||||
free_current_bo (onscreen);
|
||||
if (onscreen_native->surface)
|
||||
gbm_surface_destroy (onscreen_native->surface);
|
||||
onscreen_native->surface = onscreen_native->pending_surface;
|
||||
onscreen_native->pending_surface = NULL;
|
||||
}
|
||||
|
||||
/* Now we need to set the CRTC to whatever is the front buffer */
|
||||
onscreen_native->next_bo =
|
||||
gbm_surface_lock_front_buffer (onscreen_native->surface);
|
||||
@ -887,14 +861,27 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||
|
||||
if (width != view_layout.width || height != view_layout.height)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerKms *monitor_manager_kms =
|
||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_stage_view_get_framebuffer (stage_view);
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
struct gbm_surface *new_surface;
|
||||
EGLSurface new_egl_surface;
|
||||
|
||||
/*
|
||||
* Ensure we don't have any pending flips that will want
|
||||
* to swap the current buffer.
|
||||
*/
|
||||
while (onscreen_native->next_fb_id != 0)
|
||||
meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms);
|
||||
|
||||
/* Need to drop the GBM surface and create a new one */
|
||||
|
||||
if (!meta_renderer_native_create_surface (renderer_native,
|
||||
@ -904,29 +891,36 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (egl_onscreen->egl_surface)
|
||||
{
|
||||
_cogl_winsys_egl_make_current (cogl_display,
|
||||
egl_display->dummy_surface,
|
||||
egl_display->dummy_surface,
|
||||
egl_display->egl_context);
|
||||
eglDestroySurface (egl_renderer->edpy,
|
||||
egl_onscreen->egl_surface);
|
||||
}
|
||||
|
||||
if (onscreen_native->pending_egl_surface)
|
||||
eglDestroySurface (egl_renderer->edpy,
|
||||
onscreen_native->pending_egl_surface);
|
||||
if (onscreen_native->pending_surface)
|
||||
gbm_surface_destroy (onscreen_native->pending_surface);
|
||||
|
||||
/* If there's already a surface, wait until the next swap to switch
|
||||
* it out, otherwise, if we're just starting up we can use the new
|
||||
* surface right away.
|
||||
/*
|
||||
* Release the current buffer and destroy the associated surface. The
|
||||
* kernel will deal with keeping the actual buffer alive until its no
|
||||
* longer used.
|
||||
*/
|
||||
if (onscreen_native->surface != NULL)
|
||||
{
|
||||
onscreen_native->pending_surface = new_surface;
|
||||
onscreen_native->pending_egl_surface = new_egl_surface;
|
||||
}
|
||||
else
|
||||
{
|
||||
onscreen_native->surface = new_surface;
|
||||
egl_onscreen->egl_surface = new_egl_surface;
|
||||
free_current_bo (onscreen);
|
||||
g_clear_pointer (&onscreen_native->surface, gbm_surface_destroy);
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||
}
|
||||
/*
|
||||
* Update the active gbm and egl surfaces and make sure they they are
|
||||
* used for drawing the coming frame.
|
||||
*/
|
||||
onscreen_native->surface = new_surface;
|
||||
egl_onscreen->egl_surface = new_egl_surface;
|
||||
_cogl_winsys_egl_make_current (cogl_display,
|
||||
egl_onscreen->egl_surface,
|
||||
egl_onscreen->egl_surface,
|
||||
egl_display->egl_context);
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||
}
|
||||
|
||||
meta_renderer_native_queue_modes_reset (renderer_native);
|
||||
|
@ -43,6 +43,10 @@ struct _MetaStageNative
|
||||
|
||||
int64_t presented_frame_counter_sync;
|
||||
int64_t presented_frame_counter_complete;
|
||||
|
||||
gboolean pending_resize;
|
||||
int pending_width;
|
||||
int pending_height;
|
||||
};
|
||||
|
||||
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
||||
@ -164,35 +168,9 @@ meta_stage_native_legacy_set_size (MetaStageNative *stage_native,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
MetaRendererView *legacy_view;
|
||||
GError *error = NULL;
|
||||
cairo_rectangle_int_t view_layout;
|
||||
|
||||
legacy_view = get_legacy_view (renderer);
|
||||
if (!legacy_view)
|
||||
return;
|
||||
|
||||
if (!meta_renderer_native_set_legacy_view_size (renderer_native,
|
||||
legacy_view,
|
||||
width, height,
|
||||
&error))
|
||||
{
|
||||
meta_warning ("Applying display configuration failed: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
view_layout = (cairo_rectangle_int_t) {
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
g_object_set (G_OBJECT (legacy_view),
|
||||
"layout", &view_layout,
|
||||
NULL);
|
||||
stage_native->pending_resize = TRUE;
|
||||
stage_native->pending_width = width;
|
||||
stage_native->pending_height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -282,6 +260,56 @@ meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
|
||||
return meta_renderer_native_get_frame_counter (renderer_native);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_resize_legacy_view (MetaStageNative *stage_native)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
MetaRendererView *legacy_view;
|
||||
int width = stage_native->pending_width;
|
||||
int height = stage_native->pending_height;
|
||||
GError *error = NULL;
|
||||
cairo_rectangle_int_t view_layout;
|
||||
|
||||
if (!stage_native->pending_resize)
|
||||
return;
|
||||
stage_native->pending_resize = FALSE;
|
||||
|
||||
legacy_view = get_legacy_view (renderer);
|
||||
if (!legacy_view)
|
||||
return;
|
||||
|
||||
if (!meta_renderer_native_set_legacy_view_size (renderer_native,
|
||||
legacy_view,
|
||||
width, height,
|
||||
&error))
|
||||
{
|
||||
meta_warning ("Applying display configuration failed: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
view_layout = (cairo_rectangle_int_t) {
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
g_object_set (G_OBJECT (legacy_view),
|
||||
"layout", &view_layout,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_native_redraw (ClutterStageWindow *stage_window)
|
||||
{
|
||||
MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
|
||||
|
||||
maybe_resize_legacy_view (stage_native);
|
||||
|
||||
clutter_stage_window_parent_iface->redraw (stage_window);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_native_finish_frame (ClutterStageWindow *stage_window)
|
||||
{
|
||||
@ -315,5 +343,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||
iface->get_geometry = meta_stage_native_get_geometry;
|
||||
iface->get_views = meta_stage_native_get_views;
|
||||
iface->get_frame_counter = meta_stage_native_get_frame_counter;
|
||||
iface->redraw = meta_stage_native_redraw;
|
||||
iface->finish_frame = meta_stage_native_finish_frame;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user