diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index e8d74514a..67d0273b9 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -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); diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index c0b6d2449..2dadbb95b 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -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; }