summaryrefslogtreecommitdiff
path: root/src/backends/native/meta-renderer-native.c
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2016-07-06 13:17:34 +0800
committerJonas Ådahl <jadahl@gmail.com>2016-07-20 14:23:48 +0800
commite891a8b6282eb8617422d4c351d731c47edf373f (patch)
tree631f6253525d6f62df8929522ae62bef6c675154 /src/backends/native/meta-renderer-native.c
parentaecd98b847a7fdb83b4449ef2a58a9d61a165d5d (diff)
downloadmutter-e891a8b6282eb8617422d4c351d731c47edf373f.tar.gz
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
Diffstat (limited to 'src/backends/native/meta-renderer-native.c')
-rw-r--r--src/backends/native/meta-renderer-native.c86
1 files changed, 40 insertions, 46 deletions
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 (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.
- */
- if (onscreen_native->surface != NULL)
+ if (egl_onscreen->egl_surface)
{
- onscreen_native->pending_surface = new_surface;
- onscreen_native->pending_egl_surface = new_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);
}
- else
- {
- onscreen_native->surface = new_surface;
- egl_onscreen->egl_surface = new_egl_surface;
- _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
- }
+ /*
+ * Release the current buffer and destroy the associated surface. The
+ * kernel will deal with keeping the actual buffer alive until its no
+ * longer used.
+ */
+ free_current_bo (onscreen);
+ g_clear_pointer (&onscreen_native->surface, gbm_surface_destroy);
+
+ /*
+ * 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);