3760 lines
139 KiB
Diff
3760 lines
139 KiB
Diff
From 6b8d25eb6370a5040185ac83b44e32e3189e0533 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 10 Nov 2021 18:55:53 +0800
|
|
Subject: [PATCH 01/44] onscreen/native: Tidy up secondary GPU buffer tracking
|
|
|
|
The primary plane of a CRTC can only have one `current_fb` and therefore
|
|
only one `next_fb`, so don't confuse the situation by maintaining two of
|
|
each. In the past a single onscreen targeted multiple CRTCs meaning
|
|
separate tracking was necessary, but not anymore.
|
|
|
|
If we're using `COPY_MODE_ZERO` then the `imported_buffer` will reference
|
|
the importee internally. We don't need to keep a redundant reference to
|
|
the old buffer after importation.
|
|
|
|
If we're using `COPY_MODE_PRIMARY` or `COPY_MODE_SECONDARY_GPU` then we
|
|
only need to keep the final copy for the duration of scanout.
|
|
|
|
All of that happens before the flip so only one `next_fb` needs to live on
|
|
after the flip. And if there's only one `next_fb` then there's only one
|
|
`current_fb`.
|
|
|
|
In a related cleanup we now also ensure that `onscreen_native->gbm.next_fb`
|
|
is only assigned once per frame.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 193 +++++++++------------
|
|
1 file changed, 86 insertions(+), 107 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 3eb5503193..c41735d90b 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -67,8 +67,6 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
|
|
|
struct {
|
|
struct gbm_surface *surface;
|
|
- MetaDrmBuffer *current_fb;
|
|
- MetaDrmBuffer *next_fb;
|
|
} gbm;
|
|
|
|
struct {
|
|
@@ -117,41 +115,12 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
CoglOnscreen *onscreen,
|
|
GError **error);
|
|
|
|
-static void
|
|
-swap_secondary_drm_fb (CoglOnscreen *onscreen)
|
|
-{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
-
|
|
- secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
- if (!secondary_gpu_state)
|
|
- return;
|
|
-
|
|
- g_set_object (&secondary_gpu_state->gbm.current_fb,
|
|
- secondary_gpu_state->gbm.next_fb);
|
|
- g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
-}
|
|
-
|
|
-static void
|
|
-free_current_secondary_bo (CoglOnscreen *onscreen)
|
|
-{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
-
|
|
- secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
- if (!secondary_gpu_state)
|
|
- return;
|
|
-
|
|
- g_clear_object (&secondary_gpu_state->gbm.current_fb);
|
|
-}
|
|
-
|
|
static void
|
|
free_current_bo (CoglOnscreen *onscreen)
|
|
{
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
g_clear_object (&onscreen_native->gbm.current_fb);
|
|
- free_current_secondary_bo (onscreen);
|
|
}
|
|
|
|
static void
|
|
@@ -166,8 +135,6 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
|
|
|
g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
|
|
g_clear_object (&onscreen_native->gbm.next_fb);
|
|
-
|
|
- swap_secondary_drm_fb (onscreen);
|
|
}
|
|
|
|
static void
|
|
@@ -436,7 +403,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
MetaKmsDevice *kms_device;
|
|
MetaKms *kms;
|
|
MetaKmsUpdate *kms_update;
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL;
|
|
MetaDrmBuffer *buffer;
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
@@ -455,15 +421,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
switch (renderer_gpu_data->mode)
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
- if (gpu_kms == render_gpu)
|
|
- {
|
|
- buffer = onscreen_native->gbm.next_fb;
|
|
- }
|
|
- else
|
|
- {
|
|
- secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
- buffer = secondary_gpu_state->gbm.next_fb;
|
|
- }
|
|
+ buffer = onscreen_native->gbm.next_fb;
|
|
|
|
plane_assignment = meta_crtc_kms_assign_primary_plane (crtc_kms,
|
|
buffer,
|
|
@@ -566,8 +524,6 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
|
|
NULL);
|
|
}
|
|
|
|
- g_clear_object (&secondary_gpu_state->gbm.current_fb);
|
|
- g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy);
|
|
|
|
secondary_gpu_release_dumb (secondary_gpu_state);
|
|
@@ -575,11 +531,11 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
|
|
g_free (secondary_gpu_state);
|
|
}
|
|
|
|
-static gboolean
|
|
+static MetaDrmBuffer *
|
|
import_shared_framebuffer (CoglOnscreen *onscreen,
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
|
|
+ MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
+ MetaDrmBuffer *primary_gpu_fb)
|
|
{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
MetaRenderDevice *render_device;
|
|
g_autoptr (GError) error = NULL;
|
|
MetaDrmBuffer *imported_buffer;
|
|
@@ -587,7 +543,7 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
|
|
render_device = secondary_gpu_state->renderer_gpu_data->render_device;
|
|
imported_buffer =
|
|
meta_render_device_import_dma_buf (render_device,
|
|
- onscreen_native->gbm.next_fb,
|
|
+ primary_gpu_fb,
|
|
&error);
|
|
if (!imported_buffer)
|
|
{
|
|
@@ -601,16 +557,9 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
|
|
META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE);
|
|
secondary_gpu_state->import_status =
|
|
META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED;
|
|
- return FALSE;
|
|
+ return NULL;
|
|
}
|
|
|
|
- /*
|
|
- * next_fb may already contain a fallback buffer, so clear it only
|
|
- * when we are sure to succeed.
|
|
- */
|
|
- g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
- secondary_gpu_state->gbm.next_fb = imported_buffer;
|
|
-
|
|
if (secondary_gpu_state->import_status ==
|
|
META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE)
|
|
{
|
|
@@ -627,16 +576,16 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
|
|
|
|
secondary_gpu_state->import_status =
|
|
META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK;
|
|
- return TRUE;
|
|
+ return imported_buffer;
|
|
}
|
|
|
|
-static void
|
|
+static MetaDrmBuffer *
|
|
copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
MetaRendererNativeGpuData *renderer_gpu_data,
|
|
- gboolean *egl_context_changed)
|
|
+ gboolean *egl_context_changed,
|
|
+ MetaDrmBuffer *primary_gpu_fb)
|
|
{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
|
|
MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native);
|
|
@@ -652,9 +601,6 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu,
|
|
"FB Copy (secondary GPU)");
|
|
|
|
- g_warn_if_fail (secondary_gpu_state->gbm.next_fb == NULL);
|
|
- g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
-
|
|
render_device = renderer_gpu_data->render_device;
|
|
egl_display = meta_render_device_get_egl_display (render_device);
|
|
|
|
@@ -667,13 +613,13 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
{
|
|
g_warning ("Failed to make current: %s", error->message);
|
|
g_error_free (error);
|
|
- return;
|
|
+ return NULL;
|
|
}
|
|
|
|
*egl_context_changed = TRUE;
|
|
|
|
|
|
- buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb);
|
|
+ buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb);
|
|
bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
|
|
if (!meta_renderer_native_gles3_blit_shared_bo (egl,
|
|
gles3,
|
|
@@ -685,7 +631,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
{
|
|
g_warning ("Failed to blit shared framebuffer: %s", error->message);
|
|
g_error_free (error);
|
|
- return;
|
|
+ return NULL;
|
|
}
|
|
|
|
if (!meta_egl_swap_buffers (egl,
|
|
@@ -695,7 +641,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
{
|
|
g_warning ("Failed to swap buffers: %s", error->message);
|
|
g_error_free (error);
|
|
- return;
|
|
+ return NULL;
|
|
}
|
|
|
|
use_modifiers = meta_renderer_native_use_modifiers (renderer_native);
|
|
@@ -715,10 +661,10 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s",
|
|
error->message);
|
|
g_error_free (error);
|
|
- return;
|
|
+ return NULL;
|
|
}
|
|
|
|
- secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm);
|
|
+ return META_DRM_BUFFER (buffer_gbm);
|
|
}
|
|
|
|
static MetaDrmBufferDumb *
|
|
@@ -733,7 +679,7 @@ secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *seconda
|
|
return secondary_gpu_state->cpu.dumb_fbs[0];
|
|
}
|
|
|
|
-static gboolean
|
|
+static MetaDrmBuffer *
|
|
copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscreen,
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
const int *rectangles,
|
|
@@ -761,7 +707,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
|
|
primary_gpu_data =
|
|
meta_renderer_native_get_gpu_data (renderer_native, primary_gpu);
|
|
if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers)
|
|
- return FALSE;
|
|
+ return NULL;
|
|
|
|
buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
|
|
buffer = META_DRM_BUFFER (buffer_dumb);
|
|
@@ -784,7 +730,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
|
|
{
|
|
meta_topic (META_DEBUG_KMS,
|
|
"Failed to create DMA buffer: %s", error->message);
|
|
- return FALSE;
|
|
+ return NULL;
|
|
}
|
|
|
|
dmabuf_fb =
|
|
@@ -802,7 +748,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
|
|
meta_topic (META_DEBUG_KMS,
|
|
"Failed to create DMA buffer for blitting: %s",
|
|
error->message);
|
|
- return FALSE;
|
|
+ return NULL;
|
|
}
|
|
/* Limit the number of individual copies to 16 */
|
|
#define MAX_RECTS 16
|
|
@@ -815,7 +761,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
|
|
&error))
|
|
{
|
|
g_object_unref (dmabuf_fb);
|
|
- return FALSE;
|
|
+ return NULL;
|
|
}
|
|
}
|
|
else
|
|
@@ -832,20 +778,19 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
|
|
&error))
|
|
{
|
|
g_object_unref (dmabuf_fb);
|
|
- return FALSE;
|
|
+ return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_object_unref (dmabuf_fb);
|
|
|
|
- g_set_object (&secondary_gpu_state->gbm.next_fb, buffer);
|
|
secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
|
|
|
|
- return TRUE;
|
|
+ return g_object_ref (buffer);
|
|
}
|
|
|
|
-static void
|
|
+static MetaDrmBuffer *
|
|
copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
MetaRendererNativeGpuData *renderer_gpu_data)
|
|
@@ -897,17 +842,19 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
|
|
|
|
cogl_object_unref (dumb_bitmap);
|
|
|
|
- g_set_object (&secondary_gpu_state->gbm.next_fb, buffer);
|
|
secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
|
|
+
|
|
+ return g_object_ref (buffer);
|
|
}
|
|
|
|
-static void
|
|
+static MetaDrmBuffer *
|
|
update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
|
const int *rectangles,
|
|
int n_rectangles)
|
|
{
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
+ MetaDrmBuffer *copy = NULL;
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers,
|
|
"Onscreen (secondary gpu pre-swap-buffers)");
|
|
@@ -933,10 +880,11 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
|
/* prepare fallback */
|
|
G_GNUC_FALLTHROUGH;
|
|
case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY:
|
|
- if (!copy_shared_framebuffer_primary_gpu (onscreen,
|
|
- secondary_gpu_state,
|
|
- rectangles,
|
|
- n_rectangles))
|
|
+ copy = copy_shared_framebuffer_primary_gpu (onscreen,
|
|
+ secondary_gpu_state,
|
|
+ rectangles,
|
|
+ n_rectangles);
|
|
+ if (!copy)
|
|
{
|
|
if (!secondary_gpu_state->noted_primary_gpu_copy_failed)
|
|
{
|
|
@@ -946,9 +894,9 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
|
secondary_gpu_state->noted_primary_gpu_copy_failed = TRUE;
|
|
}
|
|
|
|
- copy_shared_framebuffer_cpu (onscreen,
|
|
- secondary_gpu_state,
|
|
- renderer_gpu_data);
|
|
+ copy = copy_shared_framebuffer_cpu (onscreen,
|
|
+ secondary_gpu_state,
|
|
+ renderer_gpu_data);
|
|
}
|
|
else if (!secondary_gpu_state->noted_primary_gpu_copy_ok)
|
|
{
|
|
@@ -960,11 +908,15 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
|
break;
|
|
}
|
|
}
|
|
+
|
|
+ return copy;
|
|
}
|
|
|
|
static void
|
|
-update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
|
- gboolean *egl_context_changed)
|
|
+update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
|
+ gboolean *egl_context_changed,
|
|
+ MetaDrmBuffer *primary_gpu_fb,
|
|
+ MetaDrmBuffer **secondary_gpu_fb)
|
|
{
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
|
@@ -977,6 +929,7 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
|
if (secondary_gpu_state)
|
|
{
|
|
MetaRendererNativeGpuData *renderer_gpu_data;
|
|
+ g_autoptr (MetaDrmBuffer) next_fb = NULL;
|
|
|
|
renderer_gpu_data =
|
|
meta_renderer_native_get_gpu_data (renderer_native,
|
|
@@ -984,23 +937,30 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
|
switch (renderer_gpu_data->secondary.copy_mode)
|
|
{
|
|
case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO:
|
|
- if (import_shared_framebuffer (onscreen, secondary_gpu_state))
|
|
+ next_fb = import_shared_framebuffer (onscreen,
|
|
+ secondary_gpu_state,
|
|
+ primary_gpu_fb);
|
|
+ if (next_fb)
|
|
break;
|
|
-
|
|
- /* The fallback was prepared in pre_swap_buffers */
|
|
+ /* The fallback was prepared in pre_swap_buffers and is currently
|
|
+ * in secondary_gpu_fb.
|
|
+ */
|
|
renderer_gpu_data->secondary.copy_mode =
|
|
META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY;
|
|
G_GNUC_FALLTHROUGH;
|
|
case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY:
|
|
- /* Done before eglSwapBuffers. */
|
|
+ next_fb = g_object_ref (*secondary_gpu_fb);
|
|
break;
|
|
case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU:
|
|
- copy_shared_framebuffer_gpu (onscreen,
|
|
- secondary_gpu_state,
|
|
- renderer_gpu_data,
|
|
- egl_context_changed);
|
|
+ next_fb = copy_shared_framebuffer_gpu (onscreen,
|
|
+ secondary_gpu_state,
|
|
+ renderer_gpu_data,
|
|
+ egl_context_changed,
|
|
+ primary_gpu_fb);
|
|
break;
|
|
}
|
|
+
|
|
+ g_set_object (secondary_gpu_fb, next_fb);
|
|
}
|
|
}
|
|
|
|
@@ -1050,6 +1010,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
g_autoptr (GError) error = NULL;
|
|
MetaDrmBufferFlags buffer_flags;
|
|
MetaDrmBufferGbm *buffer_gbm;
|
|
+ g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL;
|
|
+ g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL;
|
|
MetaKmsCrtc *kms_crtc;
|
|
MetaKmsDevice *kms_device;
|
|
MetaKmsUpdateFlag flags;
|
|
@@ -1059,9 +1021,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
|
"Onscreen (swap-buffers)");
|
|
|
|
- update_secondary_gpu_state_pre_swap_buffers (onscreen,
|
|
- rectangles,
|
|
- n_rectangles);
|
|
+ secondary_gpu_fb =
|
|
+ update_secondary_gpu_state_pre_swap_buffers (onscreen,
|
|
+ rectangles,
|
|
+ n_rectangles);
|
|
|
|
parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class);
|
|
parent_class->swap_buffers_with_damage (onscreen,
|
|
@@ -1077,9 +1040,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
switch (renderer_gpu_data->mode)
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
-
|
|
buffer_flags = META_DRM_BUFFER_FLAG_NONE;
|
|
if (!meta_renderer_native_use_modifiers (renderer_native))
|
|
buffer_flags |= META_DRM_BUFFER_FLAG_DISABLE_MODIFIERS;
|
|
@@ -1097,8 +1057,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
return;
|
|
}
|
|
|
|
- onscreen_native->gbm.next_fb = META_DRM_BUFFER (buffer_gbm);
|
|
-
|
|
+ primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm));
|
|
break;
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
g_assert_not_reached ();
|
|
@@ -1109,7 +1068,27 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
#endif
|
|
}
|
|
|
|
- update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
|
|
+ update_secondary_gpu_state_post_swap_buffers (onscreen,
|
|
+ &egl_context_changed,
|
|
+ primary_gpu_fb,
|
|
+ &secondary_gpu_fb);
|
|
+
|
|
+ switch (renderer_gpu_data->mode)
|
|
+ {
|
|
+ case META_RENDERER_NATIVE_MODE_GBM:
|
|
+ g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
+ if (onscreen_native->secondary_gpu_state)
|
|
+ g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb);
|
|
+ else
|
|
+ g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb);
|
|
+ break;
|
|
+ case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
+ break;
|
|
+#ifdef HAVE_EGL_DEVICE
|
|
+ case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
|
+ break;
|
|
+#endif
|
|
+ }
|
|
|
|
/*
|
|
* If we changed EGL context, cogl will have the wrong idea about what is
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 0c766c2cd903fc084dd186b4a30053ac3ca054d6 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 19 Jan 2022 18:43:15 +0800
|
|
Subject: [PATCH 02/44] onscreen/native: Hold primary GPU FBs for the secondary
|
|
scanout lifetime
|
|
|
|
This is out of an abundance of caution. In cases where we have copied the
|
|
primary GPU's buffer to a dumb buffer for secondary GPU (DisplayLink)
|
|
scanout, we don't really know how long OpenGL will take to complete that
|
|
copy in the background. And there is no swap buffers or locking of the
|
|
secondary GPU front buffer to guarantee when.
|
|
|
|
So to avoid needing `glFinish` or similar we now reference the original
|
|
source FB for the scanout lifetime of the secondary (dumb) buffer. This
|
|
is effectively identical to the pre-!2087 behaviour.
|
|
|
|
Although it's not theoretically optimal because the primary GPU FB is
|
|
not needed after scanout starts (`next_fb` is moved to `current_fb`),
|
|
this approach does give us the simplicity of only having to track the
|
|
lifetime of a single buffer after it is flipped.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 64 +++++++++++++++++++++-
|
|
1 file changed, 61 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index c41735d90b..55dbcfef7b 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -72,6 +72,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
|
struct {
|
|
MetaDrmBufferDumb *current_dumb_fb;
|
|
MetaDrmBufferDumb *dumb_fbs[2];
|
|
+ MetaDrmBuffer *source_fbs[2];
|
|
} cpu;
|
|
|
|
gboolean noted_primary_gpu_copy_ok;
|
|
@@ -493,13 +494,41 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen,
|
|
kms_update);
|
|
}
|
|
|
|
+static void
|
|
+hold_primary_gpu_fb_for_secondary_gpu_scanout (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
+ MetaDrmBuffer *primary_gpu_fb,
|
|
+ MetaDrmBuffer *secondary_gpu_fb)
|
|
+{
|
|
+ if (META_IS_DRM_BUFFER_DUMB (secondary_gpu_fb))
|
|
+ {
|
|
+ MetaDrmBufferDumb *dumb_fb = META_DRM_BUFFER_DUMB (secondary_gpu_fb);
|
|
+ int i;
|
|
+ const int n = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs);
|
|
+
|
|
+ for (i = 0; i < n; i++)
|
|
+ {
|
|
+ if (dumb_fb == secondary_gpu_state->cpu.dumb_fbs[i])
|
|
+ {
|
|
+ g_set_object (&secondary_gpu_state->cpu.source_fbs[i],
|
|
+ primary_gpu_fb);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_warn_if_fail (i < n);
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++)
|
|
- g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]);
|
|
+ {
|
|
+ g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]);
|
|
+ g_clear_object (&secondary_gpu_state->cpu.source_fbs[i]);
|
|
+ }
|
|
}
|
|
|
|
static void
|
|
@@ -1078,9 +1107,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
if (onscreen_native->secondary_gpu_state)
|
|
- g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb);
|
|
+ {
|
|
+ g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb);
|
|
+ hold_primary_gpu_fb_for_secondary_gpu_scanout (
|
|
+ onscreen_native->secondary_gpu_state,
|
|
+ primary_gpu_fb,
|
|
+ secondary_gpu_fb);
|
|
+ }
|
|
else
|
|
- g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb);
|
|
+ {
|
|
+ g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb);
|
|
+ }
|
|
break;
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
break;
|
|
@@ -1960,6 +1997,21 @@ pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen)
|
|
return DRM_FORMAT_INVALID;
|
|
}
|
|
|
|
+static void
|
|
+dumb_toggle_notify (gpointer data,
|
|
+ GObject *object,
|
|
+ gboolean is_last_ref)
|
|
+{
|
|
+ MetaDrmBuffer **source_fb = data;
|
|
+
|
|
+ g_return_if_fail (source_fb != NULL);
|
|
+ if (is_last_ref && *source_fb)
|
|
+ {
|
|
+ g_return_if_fail (META_IS_DRM_BUFFER (*source_fb));
|
|
+ g_clear_object (source_fb);
|
|
+ }
|
|
+}
|
|
+
|
|
static gboolean
|
|
init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_native,
|
|
CoglOnscreen *onscreen,
|
|
@@ -2016,6 +2068,12 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat
|
|
}
|
|
|
|
secondary_gpu_state->cpu.dumb_fbs[i] = META_DRM_BUFFER_DUMB (dumb_buffer);
|
|
+ g_object_add_toggle_ref (G_OBJECT (dumb_buffer),
|
|
+ dumb_toggle_notify,
|
|
+ &secondary_gpu_state->cpu.source_fbs[i]);
|
|
+
|
|
+ /* It was incremented higher than we need by add_toggle_ref */
|
|
+ g_object_unref (dumb_buffer);
|
|
}
|
|
|
|
/*
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 0a839e19f861390be42f10dc184f187bb163c8e2 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Mon, 16 Aug 2021 17:06:43 +0800
|
|
Subject: [PATCH 03/44] kms/update: Hold a reference to the buffer used in a
|
|
plane assignment
|
|
|
|
---
|
|
src/backends/native/meta-kms-update.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
|
|
index 53fc92eb86..2889338ec5 100644
|
|
--- a/src/backends/native/meta-kms-update.c
|
|
+++ b/src/backends/native/meta-kms-update.c
|
|
@@ -149,6 +149,7 @@ static void
|
|
meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment)
|
|
{
|
|
g_clear_pointer (&plane_assignment->fb_damage, meta_kms_fb_damage_free);
|
|
+ g_clear_object (&plane_assignment->buffer);
|
|
g_free (plane_assignment);
|
|
}
|
|
|
|
@@ -228,7 +229,7 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
|
|
.update = update,
|
|
.crtc = crtc,
|
|
.plane = plane,
|
|
- .buffer = buffer,
|
|
+ .buffer = g_object_ref (buffer),
|
|
.src_rect = src_rect,
|
|
.dst_rect = dst_rect,
|
|
.flags = flags,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 4a47a2221ef11c8e88d652860c189565536b7422 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Mon, 16 Aug 2021 18:04:10 +0800
|
|
Subject: [PATCH 04/44] kms/crtc: Add an API to hold references to buffers
|
|
while asssigned to planes
|
|
|
|
---
|
|
src/backends/native/meta-kms-crtc.c | 80 +++++++++++++++++++++++++++++
|
|
src/backends/native/meta-kms-crtc.h | 9 ++++
|
|
2 files changed, 89 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
|
|
index 685a3737ca..45c7eb78ee 100644
|
|
--- a/src/backends/native/meta-kms-crtc.c
|
|
+++ b/src/backends/native/meta-kms-crtc.c
|
|
@@ -32,6 +32,12 @@ typedef struct _MetaKmsCrtcPropTable
|
|
MetaKmsProp props[META_KMS_CRTC_N_PROPS];
|
|
} MetaKmsCrtcPropTable;
|
|
|
|
+typedef struct
|
|
+{
|
|
+ MetaDrmBuffer *front, *back;
|
|
+ gboolean back_is_set;
|
|
+} PlaneState;
|
|
+
|
|
struct _MetaKmsCrtc
|
|
{
|
|
GObject parent;
|
|
@@ -44,6 +50,8 @@ struct _MetaKmsCrtc
|
|
MetaKmsCrtcState current_state;
|
|
|
|
MetaKmsCrtcPropTable prop_table;
|
|
+
|
|
+ GHashTable *plane_states;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
|
|
@@ -441,20 +449,91 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
|
|
return crtc;
|
|
}
|
|
|
|
+void
|
|
+meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc,
|
|
+ uint32_t plane_id,
|
|
+ MetaDrmBuffer *buffer)
|
|
+{
|
|
+ gpointer key = GUINT_TO_POINTER (plane_id);
|
|
+ PlaneState *plane_state;
|
|
+
|
|
+ plane_state = g_hash_table_lookup (crtc->plane_states, key);
|
|
+ if (plane_state == NULL)
|
|
+ {
|
|
+ plane_state = g_new0 (PlaneState, 1);
|
|
+ g_hash_table_insert (crtc->plane_states, key, plane_state);
|
|
+ }
|
|
+
|
|
+ plane_state->back_is_set = TRUE; /* note buffer may be NULL */
|
|
+ g_set_object (&plane_state->back, buffer);
|
|
+}
|
|
+
|
|
+static void
|
|
+swap_plane_buffers (gpointer key,
|
|
+ gpointer value,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ PlaneState *plane_state = value;
|
|
+
|
|
+ if (plane_state->back_is_set)
|
|
+ {
|
|
+ g_set_object (&plane_state->front, plane_state->back);
|
|
+ g_clear_object (&plane_state->back);
|
|
+ plane_state->back_is_set = FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc)
|
|
+{
|
|
+ g_hash_table_foreach (crtc->plane_states, swap_plane_buffers, NULL);
|
|
+}
|
|
+
|
|
+void
|
|
+meta_kms_crtc_release_buffers (MetaKmsCrtc *crtc)
|
|
+{
|
|
+ g_hash_table_remove_all (crtc->plane_states);
|
|
+}
|
|
+
|
|
+static void
|
|
+meta_kms_crtc_dispose (GObject *object)
|
|
+{
|
|
+ MetaKmsCrtc *crtc = META_KMS_CRTC (object);
|
|
+
|
|
+ meta_kms_crtc_release_buffers (crtc);
|
|
+
|
|
+ G_OBJECT_CLASS (meta_kms_crtc_parent_class)->dispose (object);
|
|
+}
|
|
+
|
|
static void
|
|
meta_kms_crtc_finalize (GObject *object)
|
|
{
|
|
MetaKmsCrtc *crtc = META_KMS_CRTC (object);
|
|
|
|
clear_gamma_state (&crtc->current_state);
|
|
+ g_hash_table_unref (crtc->plane_states);
|
|
|
|
G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object);
|
|
}
|
|
|
|
+static void
|
|
+destroy_plane_state (gpointer data)
|
|
+{
|
|
+ PlaneState *plane_state = data;
|
|
+
|
|
+ g_clear_object (&plane_state->front);
|
|
+ g_clear_object (&plane_state->back);
|
|
+ g_free (plane_state);
|
|
+}
|
|
+
|
|
static void
|
|
meta_kms_crtc_init (MetaKmsCrtc *crtc)
|
|
{
|
|
crtc->current_state.gamma.size = 0;
|
|
+ crtc->plane_states = g_hash_table_new_full (NULL,
|
|
+ NULL,
|
|
+ NULL,
|
|
+ destroy_plane_state);
|
|
}
|
|
|
|
static void
|
|
@@ -462,5 +541,6 @@ meta_kms_crtc_class_init (MetaKmsCrtcClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
+ object_class->dispose = meta_kms_crtc_dispose;
|
|
object_class->finalize = meta_kms_crtc_finalize;
|
|
}
|
|
diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h
|
|
index 218bec9a15..29fdfcb5dd 100644
|
|
--- a/src/backends/native/meta-kms-crtc.h
|
|
+++ b/src/backends/native/meta-kms-crtc.h
|
|
@@ -25,6 +25,7 @@
|
|
#include <xf86drmMode.h>
|
|
|
|
#include "backends/native/meta-kms-types.h"
|
|
+#include "backends/native/meta-drm-buffer.h"
|
|
#include "core/util-private.h"
|
|
#include "meta/boxes.h"
|
|
|
|
@@ -82,4 +83,12 @@ MetaKmsCrtcGamma * meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc,
|
|
const uint16_t *green,
|
|
const uint16_t *blue);
|
|
|
|
+void meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc,
|
|
+ uint32_t plane_id,
|
|
+ MetaDrmBuffer *buffer);
|
|
+
|
|
+void meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc);
|
|
+
|
|
+void meta_kms_crtc_release_buffers (MetaKmsCrtc *crtc);
|
|
+
|
|
#endif /* META_KMS_CRTC_H */
|
|
--
|
|
GitLab
|
|
|
|
|
|
From f9c6c62942cd3f7a849338b1b325f15d47619d7f Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 17 Aug 2021 16:35:18 +0800
|
|
Subject: [PATCH 05/44] kms/page-flip: Pump the CRTC's buffer reference queue
|
|
on scanout
|
|
|
|
Precise timing of this call is not important. We only need to notify
|
|
that the *previous* scanout is definitely no longer happening. So any
|
|
old buffers no longer used in the latest scanout can be released.
|
|
---
|
|
src/backends/native/meta-kms-page-flip.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c
|
|
index 817f4e7c8d..148d237400 100644
|
|
--- a/src/backends/native/meta-kms-page-flip.c
|
|
+++ b/src/backends/native/meta-kms-page-flip.c
|
|
@@ -24,6 +24,7 @@
|
|
#include "backends/native/meta-kms-impl.h"
|
|
#include "backends/native/meta-kms-private.h"
|
|
#include "backends/native/meta-kms-update.h"
|
|
+#include "backends/native/meta-kms-crtc.h"
|
|
|
|
typedef struct _MetaKmsPageFlipClosure
|
|
{
|
|
@@ -149,6 +150,8 @@ meta_kms_page_flip_data_flipped (MetaKms *kms,
|
|
|
|
meta_assert_not_in_kms_impl (kms);
|
|
|
|
+ meta_kms_crtc_on_scanout_started (page_flip_data->crtc);
|
|
+
|
|
for (l = page_flip_data->closures; l; l = l->next)
|
|
{
|
|
MetaKmsPageFlipClosure *closure = l->data;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 10f25bb169e66ca36c63be37aa859514295adc1b Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 9 Feb 2022 16:44:09 +0800
|
|
Subject: [PATCH 06/44] kms/impl-device: Release buffers from MetaKmsCrtc in
|
|
prepare_shutdown
|
|
|
|
This allows them to release their buffers cleanly while all the
|
|
associated resources to do the release still exist. Otherwise we
|
|
might crash later in meta_drm_buffer_finalize.
|
|
---
|
|
src/backends/native/meta-kms-impl-device.c | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
|
|
index b05bf5fdab..1177707fae 100644
|
|
--- a/src/backends/native/meta-kms-impl-device.c
|
|
+++ b/src/backends/native/meta-kms-impl-device.c
|
|
@@ -1022,8 +1022,12 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device,
|
|
void
|
|
meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device)
|
|
{
|
|
+ MetaKmsImplDevicePrivate *priv =
|
|
+ meta_kms_impl_device_get_instance_private (impl_device);
|
|
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
|
|
|
+ g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_release_buffers, NULL);
|
|
+
|
|
if (klass->prepare_shutdown)
|
|
klass->prepare_shutdown (impl_device);
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 5337749757f0873603c05ef7d361e15007d256e5 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Dec 2021 18:31:16 +0800
|
|
Subject: [PATCH 07/44] kms/impl-device/simple: Pump the CRTC's buffer
|
|
reference queue on scanout
|
|
|
|
In this case "on scanout" means when `drmModeSetCrtc` succeeds. This is
|
|
the only case where there won't be a `meta_kms_page_flip_data_flipped` to
|
|
do it for us.
|
|
---
|
|
src/backends/native/meta-kms-impl-device-simple.c | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c
|
|
index 882cd97cc9..6f9dfee7ea 100644
|
|
--- a/src/backends/native/meta-kms-impl-device-simple.c
|
|
+++ b/src/backends/native/meta-kms-impl-device-simple.c
|
|
@@ -470,6 +470,8 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
|
return FALSE;
|
|
}
|
|
|
|
+ meta_kms_crtc_on_scanout_started (crtc);
|
|
+
|
|
if (drm_mode)
|
|
{
|
|
g_hash_table_replace (impl_device_simple->cached_mode_sets,
|
|
@@ -859,6 +861,8 @@ mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple,
|
|
return FALSE;
|
|
}
|
|
|
|
+ meta_kms_crtc_on_scanout_started (crtc);
|
|
+
|
|
if (!impl_device_simple->mode_set_fallback_feedback_source)
|
|
{
|
|
GSource *source;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 40b469b97e30923453c2293549efd86eb9ffa5eb Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 17 Aug 2021 17:40:57 +0800
|
|
Subject: [PATCH 08/44] kms/impl-device/simple: Keep a reference to buffers
|
|
assigned to planes
|
|
|
|
The MetaKmsCrtc will hold these references during future scanouts until
|
|
such time as a new buffer is assigned to the plane AND another scanout
|
|
has occurred after that.
|
|
---
|
|
src/backends/native/meta-kms-impl-device-simple.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c
|
|
index 6f9dfee7ea..c1e2707537 100644
|
|
--- a/src/backends/native/meta-kms-impl-device-simple.c
|
|
+++ b/src/backends/native/meta-kms-impl-device-simple.c
|
|
@@ -1294,7 +1294,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
{
|
|
case META_KMS_PLANE_TYPE_PRIMARY:
|
|
/* Handled as part of the mode-set and page flip. */
|
|
- return TRUE;
|
|
+ goto assigned;
|
|
case META_KMS_PLANE_TYPE_CURSOR:
|
|
if (!process_cursor_plane_assignment (impl_device, update,
|
|
plane_assignment,
|
|
@@ -1308,7 +1308,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
}
|
|
else
|
|
{
|
|
- return TRUE;
|
|
+ goto assigned;
|
|
}
|
|
case META_KMS_PLANE_TYPE_OVERLAY:
|
|
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
@@ -1321,6 +1321,12 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
}
|
|
|
|
g_assert_not_reached ();
|
|
+
|
|
+assigned:
|
|
+ meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc,
|
|
+ meta_kms_plane_get_id (plane),
|
|
+ plane_assignment->buffer);
|
|
+ return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 2d8ac9727a89aac439c14d965a158f208571303e Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Dec 2021 17:54:15 +0800
|
|
Subject: [PATCH 09/44] kms/impl-device/simple: Keep a reference to buffers
|
|
needed in retries
|
|
|
|
---
|
|
.../native/meta-kms-impl-device-simple.c | 24 ++++++++++++-------
|
|
1 file changed, 15 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c
|
|
index c1e2707537..8aa78343a7 100644
|
|
--- a/src/backends/native/meta-kms-impl-device-simple.c
|
|
+++ b/src/backends/native/meta-kms-impl-device-simple.c
|
|
@@ -536,7 +536,7 @@ is_timestamp_earlier_than (uint64_t ts1,
|
|
typedef struct _RetryPageFlipData
|
|
{
|
|
MetaKmsCrtc *crtc;
|
|
- uint32_t fb_id;
|
|
+ MetaDrmBuffer *fb;
|
|
MetaKmsPageFlipData *page_flip_data;
|
|
float refresh_rate;
|
|
uint64_t retry_time_us;
|
|
@@ -549,6 +549,7 @@ retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
|
|
g_assert (!retry_page_flip_data->page_flip_data);
|
|
g_clear_pointer (&retry_page_flip_data->custom_page_flip,
|
|
meta_kms_custom_page_flip_free);
|
|
+ g_clear_object (&retry_page_flip_data->fb);
|
|
g_free (retry_page_flip_data);
|
|
}
|
|
|
|
@@ -616,16 +617,21 @@ retry_page_flips (gpointer user_data)
|
|
}
|
|
else
|
|
{
|
|
+ uint32_t fb_id =
|
|
+ retry_page_flip_data->fb ?
|
|
+ meta_drm_buffer_get_fb_id (retry_page_flip_data->fb) :
|
|
+ 0;
|
|
+
|
|
meta_topic (META_DEBUG_KMS,
|
|
"[simple] Retrying page flip on CRTC %u (%s) with %u",
|
|
meta_kms_crtc_get_id (crtc),
|
|
meta_kms_impl_device_get_path (impl_device),
|
|
- retry_page_flip_data->fb_id);
|
|
+ fb_id);
|
|
|
|
fd = meta_kms_impl_device_get_fd (impl_device);
|
|
ret = drmModePageFlip (fd,
|
|
meta_kms_crtc_get_id (crtc),
|
|
- retry_page_flip_data->fb_id,
|
|
+ fb_id,
|
|
DRM_MODE_PAGE_FLIP_EVENT,
|
|
retry_page_flip_data->page_flip_data);
|
|
}
|
|
@@ -712,7 +718,7 @@ retry_page_flips (gpointer user_data)
|
|
static void
|
|
schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple,
|
|
MetaKmsCrtc *crtc,
|
|
- uint32_t fb_id,
|
|
+ MetaDrmBuffer *fb,
|
|
float refresh_rate,
|
|
MetaKmsPageFlipData *page_flip_data,
|
|
MetaKmsCustomPageFlip *custom_page_flip)
|
|
@@ -727,7 +733,7 @@ schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple,
|
|
retry_page_flip_data = g_new0 (RetryPageFlipData, 1);
|
|
*retry_page_flip_data = (RetryPageFlipData) {
|
|
.crtc = crtc,
|
|
- .fb_id = fb_id,
|
|
+ .fb = fb ? g_object_ref (fb) : NULL,
|
|
.page_flip_data = page_flip_data,
|
|
.refresh_rate = refresh_rate,
|
|
.retry_time_us = retry_time_us,
|
|
@@ -987,20 +993,20 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
|
|
cached_mode_set = get_cached_mode_set (impl_device_simple, crtc);
|
|
if (cached_mode_set)
|
|
{
|
|
- uint32_t fb_id;
|
|
+ MetaDrmBuffer *fb;
|
|
drmModeModeInfo *drm_mode;
|
|
float refresh_rate;
|
|
|
|
if (plane_assignment)
|
|
- fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer);
|
|
+ fb = plane_assignment->buffer;
|
|
else
|
|
- fb_id = 0;
|
|
+ fb = NULL;
|
|
drm_mode = cached_mode_set->drm_mode;
|
|
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
|
meta_kms_impl_device_hold_fd (impl_device);
|
|
schedule_retry_page_flip (impl_device_simple,
|
|
crtc,
|
|
- fb_id,
|
|
+ fb,
|
|
refresh_rate,
|
|
page_flip_data,
|
|
g_steal_pointer (&custom_page_flip));
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 84e908dc6707efd1befa1132d3264a8c28bec43f Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 17 Aug 2021 16:36:25 +0800
|
|
Subject: [PATCH 10/44] kms/impl-device/atomic: Keep a reference to buffers
|
|
assigned to planes
|
|
|
|
The MetaKmsCrtc will hold these references during future scanouts until
|
|
such time as a new buffer is assigned to the plane AND another scanout
|
|
has occurred after that.
|
|
---
|
|
src/backends/native/meta-kms-impl-device-atomic.c | 9 ++++++++-
|
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c
|
|
index 73dd8e6971..787d05acda 100644
|
|
--- a/src/backends/native/meta-kms-impl-device-atomic.c
|
|
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
|
|
@@ -431,6 +431,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
{
|
|
MetaKmsPlaneAssignment *plane_assignment = update_entry;
|
|
MetaKmsPlane *plane = plane_assignment->plane;
|
|
+ MetaKmsUpdateFlag flags = (MetaKmsUpdateFlag) user_data;
|
|
MetaDrmBuffer *buffer;
|
|
MetaKmsFbDamage *fb_damage;
|
|
uint32_t prop_id;
|
|
@@ -586,6 +587,12 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
error))
|
|
return FALSE;
|
|
}
|
|
+
|
|
+ if (!(flags & META_KMS_UPDATE_FLAG_TEST_ONLY))
|
|
+ meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc,
|
|
+ meta_kms_plane_get_id (plane),
|
|
+ buffer);
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -963,7 +970,7 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
|
|
req,
|
|
blob_ids,
|
|
meta_kms_update_get_plane_assignments (update),
|
|
- NULL,
|
|
+ GUINT_TO_POINTER (flags),
|
|
process_plane_assignment,
|
|
&error))
|
|
goto err;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 7891754a97fcb96f6d3b4103fd4d4482db10f70f Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 18 Aug 2021 15:04:27 +0800
|
|
Subject: [PATCH 11/44] onscreen/native: Stop holding the current onscreen
|
|
buffer
|
|
|
|
The scanout lifetime of the buffer is now automatically managed via
|
|
meta_crtc_kms_assign_primary_plane. Se we don't need `current_fb` at
|
|
all, and `next_fb` can be unreferenced as soon as we've passed it to
|
|
meta_crtc_kms_assign_primary_plane.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 34 +++-------------------
|
|
1 file changed, 4 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 55dbcfef7b..ac073901c4 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -93,7 +93,6 @@ struct _MetaOnscreenNative
|
|
|
|
struct {
|
|
struct gbm_surface *surface;
|
|
- MetaDrmBuffer *current_fb;
|
|
MetaDrmBuffer *next_fb;
|
|
} gbm;
|
|
|
|
@@ -116,28 +115,6 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
CoglOnscreen *onscreen,
|
|
GError **error);
|
|
|
|
-static void
|
|
-free_current_bo (CoglOnscreen *onscreen)
|
|
-{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
-
|
|
- g_clear_object (&onscreen_native->gbm.current_fb);
|
|
-}
|
|
-
|
|
-static void
|
|
-meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
|
-{
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
-
|
|
- if (!onscreen_native->gbm.next_fb)
|
|
- return;
|
|
-
|
|
- free_current_bo (onscreen);
|
|
-
|
|
- g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
-}
|
|
-
|
|
static void
|
|
maybe_update_frame_info (MetaCrtc *crtc,
|
|
CoglFrameInfo *frame_info,
|
|
@@ -202,7 +179,6 @@ notify_view_crtc_presented (MetaRendererView *view,
|
|
maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence);
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
}
|
|
|
|
static int64_t
|
|
@@ -313,7 +289,6 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
}
|
|
|
|
static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = {
|
|
@@ -378,8 +353,9 @@ void
|
|
meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen)
|
|
{
|
|
CoglFrameInfo *frame_info;
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
+ g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
frame_info = cogl_onscreen_peek_tail_frame_info (onscreen);
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
@@ -404,7 +380,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
MetaKmsDevice *kms_device;
|
|
MetaKms *kms;
|
|
MetaKmsUpdate *kms_update;
|
|
- MetaDrmBuffer *buffer;
|
|
+ g_autoptr (MetaDrmBuffer) buffer = NULL;
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
|
|
@@ -422,7 +398,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
switch (renderer_gpu_data->mode)
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
- buffer = onscreen_native->gbm.next_fb;
|
|
+ buffer = g_steal_pointer (&onscreen_native->gbm.next_fb);
|
|
|
|
plane_assignment = meta_crtc_kms_assign_primary_plane (crtc_kms,
|
|
buffer,
|
|
@@ -1374,7 +1350,6 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
|
G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
|
|
break;
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
g_propagate_error (error, g_error_copy (feedback_error));
|
|
return FALSE;
|
|
}
|
|
@@ -2174,7 +2149,6 @@ meta_onscreen_native_dispose (GObject *object)
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
g_clear_object (&onscreen_native->gbm.next_fb);
|
|
- free_current_bo (onscreen);
|
|
break;
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
g_assert_not_reached ();
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 210e53d132a3a494d70533c1a6c6b4839bd3661a Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 24 Sep 2021 21:49:45 +0800
|
|
Subject: [PATCH 12/44] onscreen/native: Keep the onscreen alive longer than
|
|
`MetaDrmBufferGbm`
|
|
|
|
Because `MetaDrmBufferGbm` uses `gbm_surface` in its destructor and
|
|
`gbm_surface` can't be refcounted directly. So we reference its owner
|
|
(the onscreen) instead.
|
|
|
|
This avoids a crash that can otherwise occur when hotplugging monitors as
|
|
the old onscreen might get disposed before the new onscreen has presented
|
|
a replacement frame on the same `MetaKmsCrtc`.
|
|
|
|
We could instead wrap and refcount all users of `gbm_surface`, but that
|
|
would be a lot more work for no additional benefit right now.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 6 ++++++
|
|
1 file changed, 6 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index ac073901c4..8d36eb10c8 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1063,6 +1063,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
}
|
|
|
|
primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm));
|
|
+
|
|
+ g_object_set_data_full (G_OBJECT (primary_gpu_fb),
|
|
+ "gbm_surface owner",
|
|
+ g_object_ref (onscreen),
|
|
+ (GDestroyNotify) g_object_unref);
|
|
+
|
|
break;
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
g_assert_not_reached ();
|
|
--
|
|
GitLab
|
|
|
|
|
|
From aa7b39fa8775db7c1bae839a38047bb816d572b0 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 18 Aug 2021 15:59:16 +0800
|
|
Subject: [PATCH 13/44] cursor-renderer/native: Stop holding onto historical
|
|
cursor buffers
|
|
|
|
Their scanout lifetimes are now managed automatically via the call
|
|
to meta_kms_update_assign_plane.
|
|
---
|
|
.../native/meta-cursor-renderer-native.c | 83 ++++---------------
|
|
1 file changed, 14 insertions(+), 69 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
|
|
index df5862c4c0..b27afc8e6d 100644
|
|
--- a/src/backends/native/meta-cursor-renderer-native.c
|
|
+++ b/src/backends/native/meta-cursor-renderer-native.c
|
|
@@ -64,19 +64,6 @@
|
|
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
|
#endif
|
|
|
|
-/* When animating a cursor, we usually call drmModeSetCursor2 once per frame.
|
|
- * Though, testing shows that we need to triple buffer the cursor buffer in
|
|
- * order to avoid glitches when animating the cursor, at least when running on
|
|
- * Intel. The reason for this might be (but is not confirmed to be) due to
|
|
- * the user space gbm_bo cache, making us reuse and overwrite the kernel side
|
|
- * buffer content before it was scanned out. To avoid this, we keep a user space
|
|
- * reference to each buffer we set until at least one frame after it was drawn.
|
|
- * In effect, this means we three active cursor gbm_bo's: one that that just has
|
|
- * been set, one that was previously set and may or may not have been scanned
|
|
- * out, and one pending that will be replaced if the cursor sprite changes.
|
|
- */
|
|
-#define HW_CURSOR_BUFFER_COUNT 3
|
|
-
|
|
static GQuark quark_cursor_sprite = 0;
|
|
|
|
typedef struct _CrtcCursorData
|
|
@@ -120,9 +107,8 @@ typedef enum _MetaCursorBufferState
|
|
typedef struct _MetaCursorNativeGpuState
|
|
{
|
|
MetaGpu *gpu;
|
|
- unsigned int active_buffer_idx;
|
|
MetaCursorBufferState pending_buffer_state;
|
|
- MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT];
|
|
+ MetaDrmBuffer *buffer;
|
|
} MetaCursorNativeGpuState;
|
|
|
|
typedef struct _MetaCursorNativePrivate
|
|
@@ -199,43 +185,17 @@ meta_cursor_renderer_native_finalize (GObject *object)
|
|
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
|
|
}
|
|
|
|
-static unsigned int
|
|
-get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
-{
|
|
- return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT;
|
|
-}
|
|
-
|
|
-static MetaDrmBuffer *
|
|
-get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
-{
|
|
- unsigned int pending_buffer_idx;
|
|
-
|
|
- pending_buffer_idx =
|
|
- get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
- return cursor_gpu_state->buffers[pending_buffer_idx];
|
|
-}
|
|
-
|
|
-static MetaDrmBuffer *
|
|
-get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
-{
|
|
- return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx];
|
|
-}
|
|
-
|
|
static void
|
|
-set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
- MetaGpuKms *gpu_kms,
|
|
- MetaDrmBuffer *buffer)
|
|
+set_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
+ MetaGpuKms *gpu_kms,
|
|
+ MetaDrmBuffer *buffer)
|
|
{
|
|
MetaCursorNativePrivate *cursor_priv;
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
|
- unsigned int pending_buffer_idx;
|
|
|
|
cursor_priv = ensure_cursor_priv (cursor_sprite);
|
|
cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
-
|
|
- pending_buffer_idx =
|
|
- get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
- cursor_gpu_state->buffers[pending_buffer_idx] = buffer;
|
|
+ cursor_gpu_state->buffer = buffer;
|
|
cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET;
|
|
}
|
|
|
|
@@ -311,10 +271,7 @@ assign_cursor_plane (MetaCursorRendererNative *native,
|
|
MetaKmsUpdate *kms_update;
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
- if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
|
- buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state);
|
|
- else
|
|
- buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
|
+ buffer = cursor_gpu_state->buffer;
|
|
|
|
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
@@ -365,13 +322,6 @@ assign_cursor_plane (MetaCursorRendererNative *native,
|
|
native);
|
|
|
|
crtc_cursor_data->buffer = buffer;
|
|
-
|
|
- if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
|
- {
|
|
- cursor_gpu_state->active_buffer_idx =
|
|
- (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT;
|
|
- cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE;
|
|
- }
|
|
}
|
|
|
|
static float
|
|
@@ -602,7 +552,7 @@ has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
switch (cursor_gpu_state->pending_buffer_state)
|
|
{
|
|
case META_CURSOR_BUFFER_STATE_NONE:
|
|
- return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL;
|
|
+ return cursor_gpu_state->buffer != NULL;
|
|
case META_CURSOR_BUFFER_STATE_SET:
|
|
return TRUE;
|
|
case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
|
@@ -1115,16 +1065,14 @@ unset_crtc_cursor_renderer_privates (MetaGpu *gpu,
|
|
static void
|
|
cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
{
|
|
- int i;
|
|
MetaDrmBuffer *active_buffer;
|
|
|
|
- active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
|
+ active_buffer = cursor_gpu_state->buffer;
|
|
if (active_buffer)
|
|
unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu,
|
|
active_buffer);
|
|
|
|
- for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
|
|
- g_clear_object (&cursor_gpu_state->buffers[i]);
|
|
+ g_clear_object (&cursor_gpu_state->buffer);
|
|
g_free (cursor_gpu_state);
|
|
}
|
|
|
|
@@ -1162,10 +1110,7 @@ invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite)
|
|
g_hash_table_iter_init (&iter, cursor_priv->gpu_states);
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state))
|
|
{
|
|
- unsigned int pending_buffer_idx;
|
|
-
|
|
- pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
- g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]);
|
|
+ g_clear_object (&cursor_gpu_state->buffer);
|
|
cursor_gpu_state->pending_buffer_state =
|
|
META_CURSOR_BUFFER_STATE_INVALIDATED;
|
|
}
|
|
@@ -1306,8 +1251,8 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
|
|
return;
|
|
}
|
|
|
|
- set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
- META_DRM_BUFFER (buffer_gbm));
|
|
+ set_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
+ META_DRM_BUFFER (buffer_gbm));
|
|
}
|
|
else
|
|
{
|
|
@@ -1649,8 +1594,8 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
|
return;
|
|
}
|
|
|
|
- set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
- META_DRM_BUFFER (buffer_gbm));
|
|
+ set_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
+ META_DRM_BUFFER (buffer_gbm));
|
|
}
|
|
}
|
|
#endif
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 00843efcc6f10befbefb34b2ce15a06071014212 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 18 Aug 2021 16:12:24 +0800
|
|
Subject: [PATCH 14/44] cursor-renderer/native: Remove MetaCursorBufferState
|
|
|
|
It was theoretically useful for flagging when a NULL buffer had been
|
|
SET, but in practice set_cursor_sprite_buffer is never called when the
|
|
buffer is NULL. So we can instead just compare the buffer with NULL to
|
|
tell when it is valid.
|
|
---
|
|
.../native/meta-cursor-renderer-native.c | 61 ++-----------------
|
|
1 file changed, 4 insertions(+), 57 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
|
|
index b27afc8e6d..998af173d3 100644
|
|
--- a/src/backends/native/meta-cursor-renderer-native.c
|
|
+++ b/src/backends/native/meta-cursor-renderer-native.c
|
|
@@ -97,17 +97,9 @@ typedef struct _MetaCursorRendererNativeGpuData
|
|
uint64_t cursor_height;
|
|
} MetaCursorRendererNativeGpuData;
|
|
|
|
-typedef enum _MetaCursorBufferState
|
|
-{
|
|
- META_CURSOR_BUFFER_STATE_NONE,
|
|
- META_CURSOR_BUFFER_STATE_SET,
|
|
- META_CURSOR_BUFFER_STATE_INVALIDATED,
|
|
-} MetaCursorBufferState;
|
|
-
|
|
typedef struct _MetaCursorNativeGpuState
|
|
{
|
|
MetaGpu *gpu;
|
|
- MetaCursorBufferState pending_buffer_state;
|
|
MetaDrmBuffer *buffer;
|
|
} MetaCursorNativeGpuState;
|
|
|
|
@@ -196,7 +188,6 @@ set_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
cursor_priv = ensure_cursor_priv (cursor_sprite);
|
|
cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
cursor_gpu_state->buffer = buffer;
|
|
- cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET;
|
|
}
|
|
|
|
static void
|
|
@@ -549,19 +540,7 @@ has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
if (!cursor_gpu_state)
|
|
return FALSE;
|
|
|
|
- switch (cursor_gpu_state->pending_buffer_state)
|
|
- {
|
|
- case META_CURSOR_BUFFER_STATE_NONE:
|
|
- return cursor_gpu_state->buffer != NULL;
|
|
- case META_CURSOR_BUFFER_STATE_SET:
|
|
- return TRUE;
|
|
- case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- g_assert_not_reached ();
|
|
-
|
|
- return FALSE;
|
|
+ return cursor_gpu_state->buffer != NULL;
|
|
}
|
|
|
|
static void
|
|
@@ -1109,11 +1088,7 @@ invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite)
|
|
|
|
g_hash_table_iter_init (&iter, cursor_priv->gpu_states);
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state))
|
|
- {
|
|
- g_clear_object (&cursor_gpu_state->buffer);
|
|
- cursor_gpu_state->pending_buffer_state =
|
|
- META_CURSOR_BUFFER_STATE_INVALIDATED;
|
|
- }
|
|
+ g_clear_object (&cursor_gpu_state->buffer);
|
|
}
|
|
|
|
static void
|
|
@@ -1260,34 +1235,6 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
|
|
}
|
|
}
|
|
|
|
-static gboolean
|
|
-is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
|
|
- MetaGpuKms *gpu_kms)
|
|
-{
|
|
- MetaCursorNativePrivate *cursor_priv;
|
|
- MetaCursorNativeGpuState *cursor_gpu_state;
|
|
-
|
|
- cursor_priv = get_cursor_priv (cursor_sprite);
|
|
- if (!cursor_priv)
|
|
- return FALSE;
|
|
-
|
|
- cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
- if (!cursor_gpu_state)
|
|
- return FALSE;
|
|
-
|
|
- switch (cursor_gpu_state->pending_buffer_state)
|
|
- {
|
|
- case META_CURSOR_BUFFER_STATE_SET:
|
|
- case META_CURSOR_BUFFER_STATE_NONE:
|
|
- return TRUE;
|
|
- case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- g_assert_not_reached ();
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
static gboolean
|
|
is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer,
|
|
MetaCursorSprite *cursor_sprite)
|
|
@@ -1452,7 +1399,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
|
return;
|
|
|
|
- if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
+ if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) &&
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
|
return;
|
|
|
|
@@ -1619,7 +1566,7 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
|
return;
|
|
|
|
- if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
+ if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) &&
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
|
return;
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 4ee68afa39563ad62e4dfd4fc0ebdb3996cc6872 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 17 Sep 2021 17:48:20 +0800
|
|
Subject: [PATCH 15/44] cogl/onscreen: Add function
|
|
cogl_onscreen_count_pending_frames
|
|
|
|
---
|
|
cogl/cogl/cogl-onscreen-private.h | 3 +++
|
|
cogl/cogl/cogl-onscreen.c | 8 ++++++++
|
|
2 files changed, 11 insertions(+)
|
|
|
|
diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h
|
|
index dffe018d2e..e0215f750d 100644
|
|
--- a/cogl/cogl/cogl-onscreen-private.h
|
|
+++ b/cogl/cogl/cogl-onscreen-private.h
|
|
@@ -97,4 +97,7 @@ cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen);
|
|
COGL_EXPORT CoglFrameInfo *
|
|
cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen);
|
|
|
|
+COGL_EXPORT unsigned int
|
|
+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen);
|
|
+
|
|
#endif /* __COGL_ONSCREEN_PRIVATE_H */
|
|
diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c
|
|
index ff9e1749a7..b25b4af4ab 100644
|
|
--- a/cogl/cogl/cogl-onscreen.c
|
|
+++ b/cogl/cogl/cogl-onscreen.c
|
|
@@ -510,6 +510,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen)
|
|
return g_queue_pop_head (&priv->pending_frame_infos);
|
|
}
|
|
|
|
+unsigned int
|
|
+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen)
|
|
+{
|
|
+ CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
|
|
+
|
|
+ return g_queue_get_length (&priv->pending_frame_infos);
|
|
+}
|
|
+
|
|
CoglFrameClosure *
|
|
cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen,
|
|
CoglFrameCallback callback,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 4e3140f981374e88ede3ad25d4a14fb517786e63 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 26 Oct 2021 18:50:50 +0800
|
|
Subject: [PATCH 16/44] renderer/native: Avoid requeuing the same onscreen for
|
|
a power save flip
|
|
|
|
This is a case that triple buffering will encounter. We don't want it
|
|
to queue the same onscreen multiple times because that would represent
|
|
multiple flips occurring simultaneously.
|
|
|
|
It's a linear search but the list length is typically only 1 or 2 so
|
|
no need for anything fancier yet.
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index 41bf04d665..4e23121d1c 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -678,6 +678,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na
|
|
{
|
|
const unsigned int timeout_ms = 100;
|
|
|
|
+ if (g_list_find (renderer_native->power_save_page_flip_onscreens, onscreen))
|
|
+ return;
|
|
+
|
|
if (!renderer_native->power_save_page_flip_source_id)
|
|
{
|
|
renderer_native->power_save_page_flip_source_id =
|
|
--
|
|
GitLab
|
|
|
|
|
|
From aa1039da9f0b5dbf87c42cbca8655025cb5bf693 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Mon, 1 Nov 2021 19:35:34 +0800
|
|
Subject: [PATCH 17/44] renderer/native: Steal the power save flip list before
|
|
iterating over it
|
|
|
|
Because a single iteration might also grow the list again.
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index 4e23121d1c..a4ef05682d 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -661,12 +661,18 @@ static gboolean
|
|
dummy_power_save_page_flip_cb (gpointer user_data)
|
|
{
|
|
MetaRendererNative *renderer_native = user_data;
|
|
+ GList *old_list =
|
|
+ g_steal_pointer (&renderer_native->power_save_page_flip_onscreens);
|
|
|
|
- g_list_foreach (renderer_native->power_save_page_flip_onscreens,
|
|
+ g_list_foreach (old_list,
|
|
(GFunc) meta_onscreen_native_dummy_power_save_page_flip,
|
|
NULL);
|
|
- g_clear_list (&renderer_native->power_save_page_flip_onscreens,
|
|
+ g_clear_list (&old_list,
|
|
g_object_unref);
|
|
+
|
|
+ if (renderer_native->power_save_page_flip_onscreens != NULL)
|
|
+ return G_SOURCE_CONTINUE;
|
|
+
|
|
renderer_native->power_save_page_flip_source_id = 0;
|
|
|
|
return G_SOURCE_REMOVE;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 9b1317cc05fc629192fe84a23b07f2652977136e Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 10 Dec 2021 16:40:58 +0800
|
|
Subject: [PATCH 18/44] onscreen/native: Log swapbuffers and N-buffering when
|
|
MUTTER_DEBUG=kms
|
|
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 13 +++++++++++++
|
|
1 file changed, 13 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 8d36eb10c8..1a25156007 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1026,6 +1026,19 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
|
"Onscreen (swap-buffers)");
|
|
|
|
+ if (meta_is_topic_enabled (META_DEBUG_KMS))
|
|
+ {
|
|
+ unsigned int frames_pending =
|
|
+ cogl_onscreen_count_pending_frames (onscreen);
|
|
+
|
|
+ meta_topic (META_DEBUG_KMS,
|
|
+ "Swap buffers: %u frames pending (%s-buffering)",
|
|
+ frames_pending,
|
|
+ frames_pending == 1 ? "double" :
|
|
+ frames_pending == 2 ? "triple" :
|
|
+ "?");
|
|
+ }
|
|
+
|
|
secondary_gpu_fb =
|
|
update_secondary_gpu_state_pre_swap_buffers (onscreen,
|
|
rectangles,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 7c0f2b01e54f4cfad3813e28e0a3bce5339ca755 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 28 Jul 2021 16:35:56 +0800
|
|
Subject: [PATCH 19/44] onscreen/native: Replace an assertion that double
|
|
buffering is the maximum
|
|
|
|
Because it soon won't be the maximum. But we do want to verify that the
|
|
frame info queue is not empty, to avoid NULL dereferencing and catch logic
|
|
errors.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 1a25156007..6ff80d29c8 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -150,7 +150,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen)
|
|
|
|
info = cogl_onscreen_pop_head_frame_info (onscreen);
|
|
|
|
- g_assert (!cogl_onscreen_peek_head_frame_info (onscreen));
|
|
+ g_assert (info);
|
|
|
|
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
|
_cogl_onscreen_notify_complete (onscreen, info);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From ab849f90f3eb16715a279abdfc65697ea3f31654 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 16 Sep 2021 16:26:25 +0800
|
|
Subject: [PATCH 20/44] onscreen/native: Deduplicate calls to
|
|
clutter_frame_set_result
|
|
|
|
All paths out of `meta_onscreen_native_swap_buffers_with_damage` from
|
|
here onward would set the same `CLUTTER_FRAME_RESULT_PENDING_PRESENTED`
|
|
(or terminate with `g_assert_not_reached`).
|
|
|
|
Even failed posts set this result because they will do a
|
|
`meta_onscreen_native_notify_frame_complete` in
|
|
`page_flip_feedback_discarded`.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 17 +++--------------
|
|
1 file changed, 3 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 6ff80d29c8..ea13e60c90 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1122,6 +1122,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
#endif
|
|
}
|
|
|
|
+ clutter_frame_set_result (frame,
|
|
+ CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
+
|
|
/*
|
|
* If we changed EGL context, cogl will have the wrong idea about what is
|
|
* current, making it fail to set it when it needs to. Avoid that by making
|
|
@@ -1146,8 +1149,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
{
|
|
meta_renderer_native_queue_power_save_page_flip (renderer_native,
|
|
onscreen);
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
return;
|
|
}
|
|
|
|
@@ -1165,9 +1166,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
"Postponing primary plane composite update for CRTC %u (%s)",
|
|
meta_kms_crtc_get_id (kms_crtc),
|
|
meta_kms_device_get_path (kms_device));
|
|
-
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
return;
|
|
}
|
|
else if (meta_renderer_native_has_pending_mode_set (renderer_native))
|
|
@@ -1177,8 +1175,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
|
meta_renderer_native_notify_mode_sets_reset (renderer_native);
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
return;
|
|
}
|
|
break;
|
|
@@ -1191,8 +1187,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
{
|
|
meta_renderer_native_notify_mode_sets_reset (renderer_native);
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
return;
|
|
}
|
|
break;
|
|
@@ -1210,13 +1204,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
{
|
|
case META_KMS_FEEDBACK_PASSED:
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
break;
|
|
case META_KMS_FEEDBACK_FAILED:
|
|
- clutter_frame_set_result (frame,
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
-
|
|
feedback_error = meta_kms_feedback_get_error (kms_feedback);
|
|
if (!g_error_matches (feedback_error,
|
|
G_IO_ERROR,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 54a13dcb6e3f8a29752239573a8ee0a0fee14123 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 28 Jul 2021 16:29:27 +0800
|
|
Subject: [PATCH 21/44] onscreen/native: Split swap_buffers_with_damage into
|
|
two functions
|
|
|
|
1. The EGL part: meta_onscreen_native_swap_buffers_with_damage
|
|
2. The KMS part: post_latest_swap
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 60 +++++++++++++++++-----
|
|
1 file changed, 46 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index ea13e60c90..1649a9383a 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -105,11 +105,19 @@ struct _MetaOnscreenNative
|
|
#endif
|
|
|
|
MetaRendererView *view;
|
|
+
|
|
+ struct {
|
|
+ int *rectangles; /* 4 x n_rectangles */
|
|
+ int n_rectangles;
|
|
+ } next_post;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
|
COGL_TYPE_ONSCREEN_EGL)
|
|
|
|
+static void
|
|
+post_latest_swap (CoglOnscreen *onscreen);
|
|
+
|
|
static gboolean
|
|
init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
CoglOnscreen *onscreen,
|
|
@@ -999,29 +1007,18 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
|
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
|
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
- MetaRenderer *renderer = META_RENDERER (renderer_native);
|
|
- MetaBackend *backend = meta_renderer_get_backend (renderer);
|
|
- MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
|
- MetaMonitorManager *monitor_manager =
|
|
- meta_backend_get_monitor_manager (backend);
|
|
- MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
|
MetaDeviceFile *render_device_file;
|
|
ClutterFrame *frame = user_data;
|
|
CoglOnscreenClass *parent_class;
|
|
gboolean egl_context_changed = FALSE;
|
|
- MetaPowerSave power_save_mode;
|
|
g_autoptr (GError) error = NULL;
|
|
MetaDrmBufferFlags buffer_flags;
|
|
MetaDrmBufferGbm *buffer_gbm;
|
|
g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL;
|
|
g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL;
|
|
- MetaKmsCrtc *kms_crtc;
|
|
- MetaKmsDevice *kms_device;
|
|
- MetaKmsUpdateFlag flags;
|
|
- g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
- const GError *feedback_error;
|
|
+ size_t rectangles_size;
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
|
"Onscreen (swap-buffers)");
|
|
@@ -1134,6 +1131,39 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
if (egl_context_changed)
|
|
_cogl_winsys_egl_ensure_current (cogl_display);
|
|
|
|
+ rectangles_size = n_rectangles * 4 * sizeof (int);
|
|
+ onscreen_native->next_post.rectangles =
|
|
+ g_realloc (onscreen_native->next_post.rectangles, rectangles_size);
|
|
+ memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size);
|
|
+ onscreen_native->next_post.n_rectangles = n_rectangles;
|
|
+
|
|
+ post_latest_swap (onscreen);
|
|
+}
|
|
+
|
|
+static void
|
|
+post_latest_swap (CoglOnscreen *onscreen)
|
|
+{
|
|
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
+ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
|
+ CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
|
+ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
|
+ MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
|
+ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
+ MetaRenderer *renderer = META_RENDERER (renderer_native);
|
|
+ MetaBackend *backend = meta_renderer_get_backend (renderer);
|
|
+ MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
|
+ MetaMonitorManager *monitor_manager =
|
|
+ meta_backend_get_monitor_manager (backend);
|
|
+ MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
+ MetaPowerSave power_save_mode;
|
|
+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
+ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
+ MetaKmsUpdateFlag flags;
|
|
+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
+ const GError *feedback_error;
|
|
+
|
|
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
|
|
if (power_save_mode == META_POWER_SAVE_ON)
|
|
{
|
|
@@ -1142,8 +1172,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
onscreen_native->view,
|
|
onscreen_native->crtc,
|
|
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE,
|
|
- rectangles,
|
|
- n_rectangles);
|
|
+ onscreen_native->next_post.rectangles,
|
|
+ onscreen_native->next_post.n_rectangles);
|
|
}
|
|
else
|
|
{
|
|
@@ -2187,6 +2217,8 @@ meta_onscreen_native_dispose (GObject *object)
|
|
g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy);
|
|
g_clear_pointer (&onscreen_native->secondary_gpu_state,
|
|
secondary_gpu_state_free);
|
|
+ g_clear_pointer (&onscreen_native->next_post.rectangles, g_free);
|
|
+ onscreen_native->next_post.n_rectangles = 0;
|
|
}
|
|
|
|
static void
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 9621511d643cf361e877406866c9c6e0c227cd51 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 12 Aug 2021 18:28:57 +0800
|
|
Subject: [PATCH 22/44] onscreen/native: Warn instead of crashing if posting
|
|
without an update
|
|
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 1649a9383a..4fa354052c 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1230,6 +1230,7 @@ post_latest_swap (CoglOnscreen *onscreen)
|
|
|
|
flags = META_KMS_UPDATE_FLAG_NONE;
|
|
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
|
|
+ g_return_if_fail (kms_feedback != NULL);
|
|
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
{
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 6b22f7a3a2f36c3bdc1ccc5996810fcb21f6c75d Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 28 Oct 2021 17:24:11 +0800
|
|
Subject: [PATCH 23/44] onscreen/native: Add a missing frame notification
|
|
|
|
In the unlikely event that swap_buffers_with_damage drops the previous swap
|
|
it was forgetting to notify about the discarded frame. That could lead to
|
|
frame clock freezes.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 9 +++++++++
|
|
1 file changed, 9 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 4fa354052c..46e1672b53 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1098,6 +1098,15 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
+ if (onscreen_native->gbm.next_fb != NULL)
|
|
+ {
|
|
+ CoglFrameInfo *frame_info;
|
|
+
|
|
+ frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
|
+ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
+ meta_onscreen_native_notify_frame_complete (onscreen);
|
|
+ }
|
|
+
|
|
if (onscreen_native->secondary_gpu_state)
|
|
{
|
|
g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 86ac0c3a22246cac8be1a53f305d081d4d578555 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 17 Sep 2021 17:59:28 +0800
|
|
Subject: [PATCH 24/44] onscreen/native: Defer posting if there's already a
|
|
post in progress
|
|
|
|
And when the number of pending posts decreases we know it's safe to submit
|
|
a new one. Since KMS generally only supports one outstanding post right now,
|
|
"decreases" means equal to zero.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 83 ++++++++++++++++++----
|
|
1 file changed, 70 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 46e1672b53..dc996001d7 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -94,6 +94,7 @@ struct _MetaOnscreenNative
|
|
struct {
|
|
struct gbm_surface *surface;
|
|
MetaDrmBuffer *next_fb;
|
|
+ MetaDrmBuffer *stalled_fb;
|
|
} gbm;
|
|
|
|
#ifdef HAVE_EGL_DEVICE
|
|
@@ -106,6 +107,7 @@ struct _MetaOnscreenNative
|
|
|
|
MetaRendererView *view;
|
|
|
|
+ unsigned int swaps_pending;
|
|
struct {
|
|
int *rectangles; /* 4 x n_rectangles */
|
|
int n_rectangles;
|
|
@@ -116,7 +118,7 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
|
COGL_TYPE_ONSCREEN_EGL)
|
|
|
|
static void
|
|
-post_latest_swap (CoglOnscreen *onscreen);
|
|
+try_post_latest_swap (CoglOnscreen *onscreen);
|
|
|
|
static gboolean
|
|
init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
@@ -187,6 +189,7 @@ notify_view_crtc_presented (MetaRendererView *view,
|
|
maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence);
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
+ try_post_latest_swap (onscreen);
|
|
}
|
|
|
|
static int64_t
|
|
@@ -248,6 +251,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc,
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
+ try_post_latest_swap (onscreen);
|
|
}
|
|
|
|
static void
|
|
@@ -297,6 +301,7 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
+ try_post_latest_swap (onscreen);
|
|
}
|
|
|
|
static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = {
|
|
@@ -357,19 +362,40 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data,
|
|
}
|
|
#endif /* HAVE_EGL_DEVICE */
|
|
|
|
-void
|
|
-meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen)
|
|
+static void
|
|
+drop_stalled_swap (CoglOnscreen *onscreen)
|
|
{
|
|
- CoglFrameInfo *frame_info;
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
+ CoglFrameInfo *frame_info;
|
|
+
|
|
+ /* Remember we can't compare stalled_fb because it's not used by
|
|
+ * META_RENDERER_NATIVE_MODE_EGL_DEVICE. So we judge stalled to be whenever
|
|
+ * swaps_pending > 1.
|
|
+ */
|
|
+ if (onscreen_native->swaps_pending <= 1)
|
|
+ return;
|
|
+
|
|
+ onscreen_native->swaps_pending--;
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
+ g_clear_object (&onscreen_native->gbm.stalled_fb);
|
|
|
|
frame_info = cogl_onscreen_peek_tail_frame_info (onscreen);
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
}
|
|
|
|
+void
|
|
+meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen)
|
|
+{
|
|
+ drop_stalled_swap (onscreen);
|
|
+
|
|
+ /* If the monitor just woke up and the shell is fully idle (has nothing
|
|
+ * more to swap) then we just woke to an indefinitely black screen. Let's
|
|
+ * fix that using the last swap (which is never classified as "stalled").
|
|
+ */
|
|
+ try_post_latest_swap (onscreen);
|
|
+}
|
|
+
|
|
static void
|
|
meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
MetaRendererView *view,
|
|
@@ -1097,14 +1123,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
switch (renderer_gpu_data->mode)
|
|
{
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
if (onscreen_native->gbm.next_fb != NULL)
|
|
{
|
|
- CoglFrameInfo *frame_info;
|
|
-
|
|
- frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
|
- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
- meta_onscreen_native_notify_frame_complete (onscreen);
|
|
+ g_warn_if_fail (onscreen_native->gbm.stalled_fb == NULL);
|
|
+ drop_stalled_swap (onscreen);
|
|
+ g_assert (onscreen_native->gbm.stalled_fb == NULL);
|
|
+ onscreen_native->gbm.stalled_fb =
|
|
+ g_steal_pointer (&onscreen_native->gbm.next_fb);
|
|
}
|
|
|
|
if (onscreen_native->secondary_gpu_state)
|
|
@@ -1146,11 +1171,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size);
|
|
onscreen_native->next_post.n_rectangles = n_rectangles;
|
|
|
|
- post_latest_swap (onscreen);
|
|
+ onscreen_native->swaps_pending++;
|
|
+ try_post_latest_swap (onscreen);
|
|
}
|
|
|
|
static void
|
|
-post_latest_swap (CoglOnscreen *onscreen)
|
|
+try_post_latest_swap (CoglOnscreen *onscreen)
|
|
{
|
|
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
|
@@ -1172,10 +1198,26 @@ post_latest_swap (CoglOnscreen *onscreen)
|
|
MetaKmsUpdateFlag flags;
|
|
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
const GError *feedback_error;
|
|
+ unsigned int frames_pending = cogl_onscreen_count_pending_frames (onscreen);
|
|
+
|
|
+ if (onscreen_native->swaps_pending == 0)
|
|
+ return;
|
|
+
|
|
+ g_assert (frames_pending >= onscreen_native->swaps_pending);
|
|
|
|
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
|
|
if (power_save_mode == META_POWER_SAVE_ON)
|
|
{
|
|
+ unsigned int posts_pending;
|
|
+
|
|
+ posts_pending = frames_pending - onscreen_native->swaps_pending;
|
|
+ if (posts_pending > 0)
|
|
+ return; /* wait for the next frame notification and then try again */
|
|
+
|
|
+ drop_stalled_swap (onscreen);
|
|
+ g_return_if_fail (onscreen_native->swaps_pending > 0);
|
|
+ onscreen_native->swaps_pending--;
|
|
+
|
|
ensure_crtc_modes (onscreen);
|
|
meta_onscreen_native_flip_crtc (onscreen,
|
|
onscreen_native->view,
|
|
@@ -1332,6 +1374,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
|
return FALSE;
|
|
}
|
|
|
|
+ /* Our direct scanout frame counts as 1, so more than that means we would
|
|
+ * be jumping the queue (and post would fail).
|
|
+ */
|
|
+ if (cogl_onscreen_count_pending_frames (onscreen) > 1)
|
|
+ {
|
|
+ g_set_error_literal (error,
|
|
+ COGL_SCANOUT_ERROR,
|
|
+ COGL_SCANOUT_ERROR_INHIBITED,
|
|
+ "Direct scanout is inhibited during triple buffering");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
|
render_gpu);
|
|
|
|
@@ -1433,6 +1487,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
|
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
const GError *error;
|
|
|
|
+ if (cogl_onscreen_count_pending_frames (onscreen) > 0)
|
|
+ return;
|
|
+
|
|
kms_update = meta_kms_get_pending_update (kms, kms_device);
|
|
if (!kms_update)
|
|
{
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 73bbe3d6959e1ec49425127b6ed265665648bde3 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 2 Nov 2021 19:04:04 +0800
|
|
Subject: [PATCH 25/44] onscreen/native: Keep a reference to the CRTC used
|
|
|
|
Otherwise it may get destroyed during hotplug events. Meanwhile we're
|
|
still active and might try using it in the next/final frame notification
|
|
callbacks.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index dc996001d7..86d191ee14 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -2233,7 +2233,7 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
|
onscreen_native->renderer_native = renderer_native;
|
|
onscreen_native->render_gpu = render_gpu;
|
|
onscreen_native->output = output;
|
|
- onscreen_native->crtc = crtc;
|
|
+ onscreen_native->crtc = g_object_ref (crtc);
|
|
|
|
return onscreen_native;
|
|
}
|
|
@@ -2281,6 +2281,7 @@ meta_onscreen_native_dispose (GObject *object)
|
|
|
|
G_OBJECT_CLASS (meta_onscreen_native_parent_class)->dispose (object);
|
|
|
|
+ g_clear_object (&onscreen_native->crtc);
|
|
g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy);
|
|
g_clear_pointer (&onscreen_native->secondary_gpu_state,
|
|
secondary_gpu_state_free);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 1644e8ac2254e46f8e7de3495f9f2bb5662e4447 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 4 Nov 2021 16:09:26 +0800
|
|
Subject: [PATCH 26/44] onscreen/native: Add function
|
|
meta_onscreen_native_discard_pending_swaps
|
|
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 11 +++++++++++
|
|
src/backends/native/meta-onscreen-native.h | 2 ++
|
|
2 files changed, 13 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index 86d191ee14..fb42ba7f4b 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -1529,6 +1529,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
|
}
|
|
}
|
|
|
|
+void
|
|
+meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen)
|
|
+{
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
+
|
|
+ onscreen_native->swaps_pending = 0;
|
|
+
|
|
+ g_clear_object (&onscreen_native->gbm.stalled_fb);
|
|
+ g_clear_object (&onscreen_native->gbm.next_fb);
|
|
+}
|
|
+
|
|
static gboolean
|
|
should_surface_be_sharable (CoglOnscreen *onscreen)
|
|
{
|
|
diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h
|
|
index 3a85ace267..676c4c4459 100644
|
|
--- a/src/backends/native/meta-onscreen-native.h
|
|
+++ b/src/backends/native/meta-onscreen-native.h
|
|
@@ -40,6 +40,8 @@ void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
|
|
|
void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen);
|
|
|
|
+void meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen);
|
|
+
|
|
gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
|
MetaDrmBuffer *fb);
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From eeb77174132bccdf585ffb01a8681a0e86579d2c Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 4 Nov 2021 16:09:52 +0800
|
|
Subject: [PATCH 27/44] renderer/native: Discard pending swaps when rebuilding
|
|
views
|
|
|
|
It's analogous to discard_pending_page_flips but represents swaps that
|
|
might become flips after the next frame notification callbacks, thanks
|
|
to triple buffering. Since the views are being rebuilt and their onscreens
|
|
are about to be destroyed, turning those swaps into more flips/posts would
|
|
just lead to unexpected behaviour (like trying to flip on a half-destroyed
|
|
inactive CRTC).
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 21 +++++++++++++++++++++
|
|
1 file changed, 21 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index a4ef05682d..58e6339a8c 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -1395,6 +1395,26 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
|
return view;
|
|
}
|
|
|
|
+static void
|
|
+discard_pending_swaps (MetaRenderer *renderer)
|
|
+{
|
|
+ GList *views = meta_renderer_get_views (renderer);;
|
|
+ GList *l;
|
|
+
|
|
+ for (l = views; l; l = l->next)
|
|
+ {
|
|
+ ClutterStageView *stage_view = l->data;
|
|
+ CoglFramebuffer *fb = clutter_stage_view_get_onscreen (stage_view);
|
|
+ CoglOnscreen *onscreen;
|
|
+
|
|
+ if (!COGL_IS_ONSCREEN (fb))
|
|
+ continue;
|
|
+
|
|
+ onscreen = COGL_ONSCREEN (fb);
|
|
+ meta_onscreen_native_discard_pending_swaps (onscreen);
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
keep_current_onscreens_alive (MetaRenderer *renderer)
|
|
{
|
|
@@ -1423,6 +1443,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer)
|
|
MetaRendererClass *parent_renderer_class =
|
|
META_RENDERER_CLASS (meta_renderer_native_parent_class);
|
|
|
|
+ discard_pending_swaps (renderer);
|
|
meta_kms_discard_pending_page_flips (kms);
|
|
meta_kms_discard_pending_updates (kms);
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 5d93028632ebea30d2862f9415dfab97d58910a7 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 10 Aug 2021 17:46:49 +0800
|
|
Subject: [PATCH 28/44] clutter/frame-clock: Lower the threshold for disabling
|
|
error diffusion
|
|
|
|
Error diffusion was introduced in 0555a5bbc15 for Nvidia where last
|
|
presentation time is always unknown (zero). Dispatch times would drift
|
|
apart always being a fraction of a frame late, and accumulated to cause
|
|
periodic frame skips. So error diffusion corrected that precisely and
|
|
avoided the skips.
|
|
|
|
That works great with double buffering but less great with triple
|
|
buffering. It's certainly still needed with triple buffering but
|
|
correcting for a lateness of many milliseconds isn't a good idea. That's
|
|
because a dispatch being that late is not due to main loop jitter but due
|
|
to Nvidia's swap buffers blocking when the queue is full. So scheduling
|
|
the next frame even earlier using last_dispatch_lateness_us would just
|
|
perpetuate the problem of swap buffers blocking for too long.
|
|
|
|
So now we lower the threshold of when error diffusion gets disabled. It's
|
|
still high enough to fix the original smoothness problem it was for, but
|
|
now low enough to detect Nvidia's occasionally blocking swaps and backs
|
|
off in that case.
|
|
|
|
Since the average duration of a blocking swap is half a frame interval
|
|
and we want to distinguish between that and sub-millisecond jitter, the
|
|
logical threshold is halfway again: refresh_interval_us/4.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index 6fa2b25887..bf6cf3ef4c 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -670,7 +670,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
frame_clock->refresh_interval_us;
|
|
|
|
lateness_us = time_us - ideal_dispatch_time_us;
|
|
- if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
|
|
+ if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us / 4)
|
|
frame_clock->last_dispatch_lateness_us = 0;
|
|
else
|
|
frame_clock->last_dispatch_lateness_us = lateness_us;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From e9f53325961918e8bc4522494ed99a98a1c9e5eb Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 24 Jul 2020 14:13:11 +0800
|
|
Subject: [PATCH 29/44] clutter/frame-clock: Merge states DISPATCHING and
|
|
PENDING_PRESENTED
|
|
|
|
Chronologically they already overlap in time as presentation may
|
|
complete in the middle of the dispatch function, otherwise they are
|
|
contiguous in time. And most switch statements treated the two states
|
|
the same already so they're easy to merge into a single `DISPATCHED`
|
|
state.
|
|
|
|
Having fewer states now will make life easier when we add more states
|
|
later.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 26 ++++++++++----------------
|
|
1 file changed, 10 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index bf6cf3ef4c..26f2f681e5 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -65,8 +65,7 @@ typedef enum _ClutterFrameClockState
|
|
CLUTTER_FRAME_CLOCK_STATE_INIT,
|
|
CLUTTER_FRAME_CLOCK_STATE_IDLE,
|
|
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
|
|
- CLUTTER_FRAME_CLOCK_STATE_DISPATCHING,
|
|
- CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED,
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED,
|
|
} ClutterFrameClockState;
|
|
|
|
struct _ClutterFrameClock
|
|
@@ -317,8 +316,7 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
g_warn_if_reached ();
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
@@ -337,8 +335,7 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
g_warn_if_reached ();
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
@@ -558,8 +555,7 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
|
frame_clock->pending_reschedule = TRUE;
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
break;
|
|
}
|
|
|
|
@@ -598,8 +594,7 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
return;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
frame_clock->pending_reschedule = TRUE;
|
|
frame_clock->pending_reschedule_now = TRUE;
|
|
return;
|
|
@@ -637,8 +632,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
return;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
frame_clock->pending_reschedule = TRUE;
|
|
return;
|
|
}
|
|
@@ -678,7 +672,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
frame_clock->last_dispatch_time_us = time_us;
|
|
g_source_set_ready_time (frame_clock->source, -1);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED;
|
|
|
|
frame_count = frame_clock->frame_count++;
|
|
|
|
@@ -706,19 +700,19 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
switch (frame_clock->state)
|
|
{
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
g_warn_if_reached ();
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
+ /* Presentation completed synchronously in the above listener */
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
switch (result)
|
|
{
|
|
case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED;
|
|
break;
|
|
case CLUTTER_FRAME_RESULT_IDLE:
|
|
+ /* The frame was aborted; nothing to paint/present */
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 856b06a53a6c74b5b7d7e2f52ae8c8f0072b03a5 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 10 Sep 2020 16:34:53 +0800
|
|
Subject: [PATCH 30/44] clutter/frame-clock: Add triple buffering support
|
|
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 101 ++++++++++++++++++++------
|
|
1 file changed, 80 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index 26f2f681e5..cacd4f6362 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -65,7 +65,9 @@ typedef enum _ClutterFrameClockState
|
|
CLUTTER_FRAME_CLOCK_STATE_INIT,
|
|
CLUTTER_FRAME_CLOCK_STATE_IDLE,
|
|
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
|
|
- CLUTTER_FRAME_CLOCK_STATE_DISPATCHED,
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE,
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED,
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO,
|
|
} ClutterFrameClockState;
|
|
|
|
struct _ClutterFrameClock
|
|
@@ -316,10 +318,18 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
g_warn_if_reached ();
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
@@ -335,10 +345,18 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
g_warn_if_reached ();
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
@@ -555,7 +573,12 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
|
frame_clock->pending_reschedule = TRUE;
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
break;
|
|
}
|
|
|
|
@@ -591,10 +614,17 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
next_update_time_us = g_get_monotonic_time ();
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
return;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ next_update_time_us = g_get_monotonic_time ();
|
|
+ frame_clock->state =
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
frame_clock->pending_reschedule = TRUE;
|
|
frame_clock->pending_reschedule_now = TRUE;
|
|
return;
|
|
@@ -603,7 +633,6 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
|
g_warn_if_fail (next_update_time_us != -1);
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
frame_clock->is_next_presentation_time_valid = FALSE;
|
|
}
|
|
|
|
@@ -622,6 +651,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
{
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
next_update_time_us = g_get_monotonic_time ();
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
calculate_next_update_time_us (frame_clock,
|
|
@@ -629,10 +659,20 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
&frame_clock->next_presentation_time_us);
|
|
frame_clock->is_next_presentation_time_valid =
|
|
(frame_clock->next_presentation_time_us != 0);
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
break;
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
return;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ calculate_next_update_time_us (frame_clock,
|
|
+ &next_update_time_us,
|
|
+ &frame_clock->next_presentation_time_us);
|
|
+ frame_clock->is_next_presentation_time_valid =
|
|
+ (frame_clock->next_presentation_time_us != 0);
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
frame_clock->pending_reschedule = TRUE;
|
|
return;
|
|
}
|
|
@@ -640,7 +680,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
g_warn_if_fail (next_update_time_us != -1);
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
}
|
|
|
|
static void
|
|
@@ -672,7 +711,21 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
frame_clock->last_dispatch_time_us = time_us;
|
|
g_source_set_ready_time (frame_clock->source, -1);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED;
|
|
+ switch (frame_clock->state)
|
|
+ {
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
+ g_warn_if_reached ();
|
|
+ return;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO;
|
|
+ break;
|
|
+ }
|
|
|
|
frame_count = frame_clock->frame_count++;
|
|
|
|
@@ -697,25 +750,31 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
frame_clock->listener.user_data);
|
|
COGL_TRACE_END (ClutterFrameClockFrame);
|
|
|
|
- switch (frame_clock->state)
|
|
+ switch (result)
|
|
{
|
|
- case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
- g_warn_if_reached ();
|
|
+ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
- /* Presentation completed synchronously in the above listener */
|
|
- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
- break;
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED:
|
|
- switch (result)
|
|
+ case CLUTTER_FRAME_RESULT_IDLE:
|
|
+ /* The frame was aborted; nothing to paint/present */
|
|
+ switch (frame_clock->state)
|
|
{
|
|
- case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
+ g_warn_if_reached ();
|
|
break;
|
|
- case CLUTTER_FRAME_RESULT_IDLE:
|
|
- /* The frame was aborted; nothing to paint/present */
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
maybe_reschedule_update (frame_clock);
|
|
break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
+ maybe_reschedule_update (frame_clock);
|
|
+ break;
|
|
}
|
|
break;
|
|
}
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 171608c43d38761abc8933331a3750b72f7bf1f9 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 10 Dec 2021 16:28:04 +0800
|
|
Subject: [PATCH 31/44] clutter/frame-clock: Log N-buffers in
|
|
CLUTTTER_DEBUG=frame-timings
|
|
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 11 ++++++++++-
|
|
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index cacd4f6362..e97c6f2ad4 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -229,6 +229,10 @@ void
|
|
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
ClutterFrameInfo *frame_info)
|
|
{
|
|
+ const char *debug_state =
|
|
+ frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO ?
|
|
+ "Triple buffering" : "Double buffering";
|
|
+
|
|
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented,
|
|
"Frame Clock (presented)");
|
|
|
|
@@ -290,7 +294,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
frame_info->cpu_time_before_buffer_swap_us;
|
|
|
|
CLUTTER_NOTE (FRAME_TIMINGS,
|
|
- "dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
|
+ "%s: dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
|
+ debug_state,
|
|
dispatch_to_swap_us,
|
|
swap_to_rendering_done_us,
|
|
swap_to_flip_us);
|
|
@@ -304,6 +309,10 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
|
|
frame_clock->got_measurements_last_frame = TRUE;
|
|
}
|
|
+ else
|
|
+ {
|
|
+ CLUTTER_NOTE (FRAME_TIMINGS, "%s", debug_state);
|
|
+ }
|
|
|
|
if (frame_info->refresh_rate > 1)
|
|
{
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 8dd2b170d40cf556ee4d7cdc5ff05b0ab653b85c Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Mon, 13 Dec 2021 17:03:44 +0800
|
|
Subject: [PATCH 32/44] clutter/frame-clock: Don't clamp
|
|
compute_max_render_time_us
|
|
|
|
Because values over refresh_interval_us are real and valid. They
|
|
tell us when we're not keeping up.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 2 --
|
|
1 file changed, 2 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index e97c6f2ad4..ade6f2e4a5 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -415,8 +415,6 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
|
frame_clock->vblank_duration_us +
|
|
clutter_max_render_time_constant_us;
|
|
|
|
- max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us);
|
|
-
|
|
return max_render_time_us;
|
|
}
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From b9c6aaa146770ed47454db487dcac2e41323e17b Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 17 Feb 2022 15:54:57 +0800
|
|
Subject: [PATCH 33/44] clutter/frame-clock: Subtract buffer queue latency from
|
|
max_swap_to_flip_us
|
|
|
|
swap_to_flip times were getting stuck at over one frame interval
|
|
because of a positive feedback loop with triple buffering.
|
|
|
|
The moment triple buffering started it would cause swap_to_flip times
|
|
to exceed one frame interval. Then that high value would feed back
|
|
through max_render_time which in turn ensured triple buffering
|
|
continued which ensured swap_to_flip stayed over one frame interval.
|
|
So even when actual GPU render times became low we were stuck with
|
|
a high value of max_render_time and stuck in triple buffering when we
|
|
should have switched to double buffering.
|
|
|
|
By subtracting the constant buffer queue latency from max_swap_to_flip_us
|
|
we break this positive feedback loop and only include real performance
|
|
measurements. So now the frame clock is able to drop back to double
|
|
buffering when appropriate.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 22 ++++++++++++++++++++++
|
|
1 file changed, 22 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index ade6f2e4a5..cc4ac21c24 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -377,6 +377,7 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
|
int64_t max_swap_to_rendering_done_us = 0;
|
|
int64_t max_swap_to_flip_us = 0;
|
|
int64_t max_render_time_us;
|
|
+ int buffer_queue_latency_frames = 0;
|
|
int i;
|
|
|
|
refresh_interval_us = frame_clock->refresh_interval_us;
|
|
@@ -399,6 +400,27 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
|
frame_clock->swap_to_flip_us.values[i]);
|
|
}
|
|
|
|
+ switch (frame_clock->state)
|
|
+ {
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
+ buffer_queue_latency_frames = 0;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
+ buffer_queue_latency_frames = 1;
|
|
+ break;
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
+ g_warn_if_reached ();
|
|
+ buffer_queue_latency_frames = 2;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ max_swap_to_flip_us -= refresh_interval_us * buffer_queue_latency_frames;
|
|
+ if (max_swap_to_flip_us < 0)
|
|
+ max_swap_to_flip_us = 0;
|
|
+
|
|
/* Max render time shows how early the frame clock needs to be dispatched
|
|
* to make it to the predicted next presentation time. It is composed of:
|
|
* - An estimate of duration from dispatch start to buffer swap.
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 4855f39c21b7e98c42df4c8e2573019c2573dc5a Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Sep 2021 19:08:15 +0800
|
|
Subject: [PATCH 34/44] clutter/frame: Add ClutterFrameHint to ClutterFrame
|
|
|
|
This will allow the backend to provide performance hints to the frame
|
|
clock in future.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.h | 6 ++++++
|
|
clutter/clutter/clutter-frame-private.h | 1 +
|
|
clutter/clutter/clutter-frame.c | 13 +++++++++++++
|
|
clutter/clutter/clutter-frame.h | 7 +++++++
|
|
4 files changed, 27 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
|
|
index 91e6b3a130..18c7676f4e 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.h
|
|
+++ b/clutter/clutter/clutter-frame-clock.h
|
|
@@ -34,6 +34,12 @@ typedef enum _ClutterFrameResult
|
|
CLUTTER_FRAME_RESULT_IDLE,
|
|
} ClutterFrameResult;
|
|
|
|
+typedef enum _ClutterFrameHint
|
|
+{
|
|
+ CLUTTER_FRAME_HINT_NONE = 0,
|
|
+ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED = 1 << 0,
|
|
+} ClutterFrameHint;
|
|
+
|
|
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
|
|
CLUTTER_EXPORT
|
|
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
|
diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h
|
|
index e0088564fc..06581492f5 100644
|
|
--- a/clutter/clutter/clutter-frame-private.h
|
|
+++ b/clutter/clutter/clutter-frame-private.h
|
|
@@ -24,6 +24,7 @@ struct _ClutterFrame
|
|
{
|
|
gboolean has_result;
|
|
ClutterFrameResult result;
|
|
+ ClutterFrameHint hints;
|
|
};
|
|
|
|
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
|
|
diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c
|
|
index 3c708da9dc..63ae302af7 100644
|
|
--- a/clutter/clutter/clutter-frame.c
|
|
+++ b/clutter/clutter/clutter-frame.c
|
|
@@ -40,3 +40,16 @@ clutter_frame_set_result (ClutterFrame *frame,
|
|
frame->result = result;
|
|
frame->has_result = TRUE;
|
|
}
|
|
+
|
|
+void
|
|
+clutter_frame_set_hint (ClutterFrame *frame,
|
|
+ ClutterFrameHint hint)
|
|
+{
|
|
+ frame->hints |= hint;
|
|
+}
|
|
+
|
|
+ClutterFrameHint
|
|
+clutter_frame_get_hints (ClutterFrame *frame)
|
|
+{
|
|
+ return frame->hints;
|
|
+}
|
|
diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h
|
|
index d3608e81ca..06c5f7f28a 100644
|
|
--- a/clutter/clutter/clutter-frame.h
|
|
+++ b/clutter/clutter/clutter-frame.h
|
|
@@ -33,4 +33,11 @@ void clutter_frame_set_result (ClutterFrame *frame,
|
|
CLUTTER_EXPORT
|
|
gboolean clutter_frame_has_result (ClutterFrame *frame);
|
|
|
|
+CLUTTER_EXPORT
|
|
+void clutter_frame_set_hint (ClutterFrame *frame,
|
|
+ ClutterFrameHint hint);
|
|
+
|
|
+CLUTTER_EXPORT
|
|
+ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame);
|
|
+
|
|
#endif /* CLUTTER_FRAME_H */
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 3bdb988fd0940922e53519f13486ae784f5131db Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Sep 2021 19:10:26 +0800
|
|
Subject: [PATCH 35/44] backends: Flag that the frame attempted direct scanout
|
|
|
|
We need this hint whether direct scanout succeeds or fails because it's
|
|
the mechanism by which we will tell the clock to enforce double buffering,
|
|
thus making direct scanout possible on future frames. Triple buffering
|
|
will be disabled until such time that direct scanout is not being attempted.
|
|
---
|
|
src/backends/meta-stage-impl.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c
|
|
index c45aaf852e..683f4ff6c5 100644
|
|
--- a/src/backends/meta-stage-impl.c
|
|
+++ b/src/backends/meta-stage-impl.c
|
|
@@ -720,6 +720,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window,
|
|
{
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
+ clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED);
|
|
+
|
|
if (meta_stage_impl_scanout_view (stage_impl,
|
|
stage_view,
|
|
scanout,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 97e6394f725c432ade1e824746a84f690227dbff Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Sep 2021 19:15:18 +0800
|
|
Subject: [PATCH 36/44] clutter: Pass ClutterFrameHint(s) to the frame clock
|
|
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 8 ++++++--
|
|
clutter/clutter/clutter-frame-clock.h | 5 +++--
|
|
clutter/clutter/clutter-stage-view.c | 5 +++--
|
|
3 files changed, 12 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index cc4ac21c24..577f10ee71 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -97,6 +97,8 @@ struct _ClutterFrameClock
|
|
/* Last KMS buffer submission time. */
|
|
int64_t last_flip_time_us;
|
|
|
|
+ ClutterFrameHint last_flip_hints;
|
|
+
|
|
/* Last few durations between dispatch start and buffer swap. */
|
|
EstimateQueue dispatch_to_swap_us;
|
|
/* Last few durations between buffer swap and GPU rendering finish. */
|
|
@@ -836,10 +838,12 @@ frame_clock_source_dispatch (GSource *source,
|
|
}
|
|
|
|
void
|
|
-clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
|
- int64_t flip_time_us)
|
|
+clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock,
|
|
+ int64_t flip_time_us,
|
|
+ ClutterFrameHint hints)
|
|
{
|
|
frame_clock->last_flip_time_us = flip_time_us;
|
|
+ frame_clock->last_flip_hints = hints;
|
|
}
|
|
|
|
GString *
|
|
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
|
|
index 18c7676f4e..d750404d53 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.h
|
|
+++ b/clutter/clutter/clutter-frame-clock.h
|
|
@@ -96,8 +96,9 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
|
CLUTTER_EXPORT
|
|
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
|
|
|
-void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
|
- int64_t flip_time_us);
|
|
+void clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock,
|
|
+ int64_t flip_time_us,
|
|
+ ClutterFrameHint hints);
|
|
|
|
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
|
index 8a82de71ed..45d0093521 100644
|
|
--- a/clutter/clutter/clutter-stage-view.c
|
|
+++ b/clutter/clutter/clutter-stage-view.c
|
|
@@ -1190,8 +1190,9 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|
|
|
_clutter_stage_window_redraw_view (stage_window, view, &frame);
|
|
|
|
- clutter_frame_clock_record_flip_time (frame_clock,
|
|
- g_get_monotonic_time ());
|
|
+ clutter_frame_clock_record_flip (frame_clock,
|
|
+ g_get_monotonic_time (),
|
|
+ clutter_frame_get_hints (&frame));
|
|
|
|
clutter_stage_emit_after_paint (stage, view);
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 9649fbb9cf95d8e0d044b48811ed753ccc25ae32 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Tue, 7 Sep 2021 19:15:55 +0800
|
|
Subject: [PATCH 37/44] clutter/frame-clock: Throttle back to double buffering
|
|
for direct scanout
|
|
|
|
There's no compositing during direct scanout so the "render" time is zero.
|
|
Thus there is no need to implement triple buffering for direct scanouts.
|
|
Stick to double buffering and enjoy the lower latency.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 7 +++++++
|
|
1 file changed, 7 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index 577f10ee71..57176b3763 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -696,6 +696,13 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
return;
|
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
+ if (frame_clock->last_flip_hints & CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)
|
|
+ {
|
|
+ /* Force double buffering, disable triple buffering */
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
+ return;
|
|
+ }
|
|
+
|
|
calculate_next_update_time_us (frame_clock,
|
|
&next_update_time_us,
|
|
&frame_clock->next_presentation_time_us);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From e1d01f6cb3963a39e8c07e10f4e12e77b9762d18 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Thu, 10 Mar 2022 16:44:14 +0800
|
|
Subject: [PATCH 38/44] clutter/frame-clock: Add env var
|
|
MUTTER_DEBUG_DISABLE_TRIPLE_BUFFERING
|
|
|
|
You can set environment variable MUTTER_DEBUG_DISABLE_TRIPLE_BUFFERING=1
|
|
to disable triple buffering. This shouldn't ever be needed except when
|
|
debugging.
|
|
---
|
|
clutter/clutter/clutter-frame-clock.c | 8 +++++++-
|
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
index 57176b3763..7a6444ec44 100644
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
@@ -45,6 +45,8 @@ typedef struct _EstimateQueue
|
|
int next_index;
|
|
} EstimateQueue;
|
|
|
|
+static gboolean triple_buffering_disabled = FALSE;
|
|
+
|
|
#define SYNC_DELAY_FALLBACK_FRACTION 0.875
|
|
|
|
typedef struct _ClutterFrameListener
|
|
@@ -696,7 +698,8 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
return;
|
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
- if (frame_clock->last_flip_hints & CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)
|
|
+ if (frame_clock->last_flip_hints & CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED ||
|
|
+ triple_buffering_disabled)
|
|
{
|
|
/* Force double buffering, disable triple buffering */
|
|
frame_clock->pending_reschedule = TRUE;
|
|
@@ -981,6 +984,9 @@ clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
+ if (!g_strcmp0 (g_getenv ("MUTTER_DEBUG_DISABLE_TRIPLE_BUFFERING"), "1"))
|
|
+ triple_buffering_disabled = TRUE;
|
|
+
|
|
object_class->dispose = clutter_frame_clock_dispose;
|
|
|
|
signals[DESTROY] =
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 1fe109cf7a96f8521bcef30910ac41007cd5d467 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 22 Sep 2021 17:01:42 +0800
|
|
Subject: [PATCH 39/44] kms: Keep a hash table of CRTCs relating to the
|
|
KmsUpdate
|
|
|
|
This will allow more efficient lookup than linear searching each of
|
|
the GLists.
|
|
---
|
|
src/backends/native/meta-kms-update.c | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
|
|
index 2889338ec5..5896d66dfe 100644
|
|
--- a/src/backends/native/meta-kms-update.c
|
|
+++ b/src/backends/native/meta-kms-update.c
|
|
@@ -31,6 +31,7 @@
|
|
struct _MetaKmsUpdate
|
|
{
|
|
MetaKmsDevice *device;
|
|
+ GHashTable *crtcs;
|
|
|
|
gboolean is_locked;
|
|
uint64_t sequence_number;
|
|
@@ -238,6 +239,8 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
|
|
update->plane_assignments = g_list_prepend (update->plane_assignments,
|
|
plane_assignment);
|
|
|
|
+ g_hash_table_insert (update->crtcs, crtc, NULL);
|
|
+
|
|
return plane_assignment;
|
|
}
|
|
|
|
@@ -263,6 +266,8 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update,
|
|
update->plane_assignments = g_list_prepend (update->plane_assignments,
|
|
plane_assignment);
|
|
|
|
+ g_hash_table_insert (update->crtcs, crtc, NULL);
|
|
+
|
|
return plane_assignment;
|
|
}
|
|
|
|
@@ -285,6 +290,8 @@ meta_kms_update_mode_set (MetaKmsUpdate *update,
|
|
};
|
|
|
|
update->mode_sets = g_list_prepend (update->mode_sets, mode_set);
|
|
+
|
|
+ g_hash_table_insert (update->crtcs, crtc, NULL);
|
|
}
|
|
|
|
static MetaKmsConnectorUpdate *
|
|
@@ -403,6 +410,8 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
|
|
gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue);
|
|
|
|
update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma);
|
|
+
|
|
+ g_hash_table_insert (update->crtcs, crtc, NULL);
|
|
}
|
|
|
|
void
|
|
@@ -694,12 +703,15 @@ meta_kms_update_new (MetaKmsDevice *device)
|
|
update->device = device;
|
|
update->sequence_number = sequence_number++;
|
|
|
|
+ update->crtcs = g_hash_table_new (NULL, NULL);
|
|
+
|
|
return update;
|
|
}
|
|
|
|
void
|
|
meta_kms_update_free (MetaKmsUpdate *update)
|
|
{
|
|
+ g_hash_table_destroy (update->crtcs);
|
|
g_list_free_full (update->result_listeners,
|
|
(GDestroyNotify) meta_kms_result_listener_free);
|
|
g_list_free_full (update->plane_assignments,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 043be2e16d4c8afebb749181962d884d97451292 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 22 Sep 2021 17:19:45 +0800
|
|
Subject: [PATCH 40/44] kms: Add functions meta_kms_update_include[s]_crtc()
|
|
|
|
---
|
|
src/backends/native/meta-kms-update-private.h | 6 ++++++
|
|
src/backends/native/meta-kms-update.c | 14 ++++++++++++++
|
|
2 files changed, 20 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
|
|
index a613cbc5d6..1d964ff21f 100644
|
|
--- a/src/backends/native/meta-kms-update-private.h
|
|
+++ b/src/backends/native/meta-kms-update-private.h
|
|
@@ -132,6 +132,12 @@ uint64_t meta_kms_update_get_sequence_number (MetaKmsUpdate *update);
|
|
META_EXPORT_TEST
|
|
MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update);
|
|
|
|
+gboolean meta_kms_update_includes_crtc (MetaKmsUpdate *update,
|
|
+ MetaKmsCrtc *crtc);
|
|
+
|
|
+void meta_kms_update_include_crtc (MetaKmsUpdate *update,
|
|
+ MetaKmsCrtc *crtc);
|
|
+
|
|
void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment,
|
|
uint64_t rotation);
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
|
|
index 5896d66dfe..1e43f3f0f5 100644
|
|
--- a/src/backends/native/meta-kms-update.c
|
|
+++ b/src/backends/native/meta-kms-update.c
|
|
@@ -675,6 +675,20 @@ meta_kms_update_get_device (MetaKmsUpdate *update)
|
|
return update->device;
|
|
}
|
|
|
|
+gboolean
|
|
+meta_kms_update_includes_crtc (MetaKmsUpdate *update,
|
|
+ MetaKmsCrtc *crtc)
|
|
+{
|
|
+ return g_hash_table_lookup_extended (update->crtcs, crtc, NULL, NULL);
|
|
+}
|
|
+
|
|
+void
|
|
+meta_kms_update_include_crtc (MetaKmsUpdate *update,
|
|
+ MetaKmsCrtc *crtc)
|
|
+{
|
|
+ g_hash_table_insert (update->crtcs, crtc, NULL);
|
|
+}
|
|
+
|
|
MetaKmsCustomPageFlip *
|
|
meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update)
|
|
{
|
|
--
|
|
GitLab
|
|
|
|
|
|
From db5653698234487b006321b4198f4c225394ede0 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Wed, 22 Sep 2021 18:13:54 +0800
|
|
Subject: [PATCH 41/44] kms: Add per-CRTC update functions
|
|
|
|
---
|
|
src/backends/native/meta-kms.c | 103 +++++++++++++++++++++++++++++++--
|
|
src/backends/native/meta-kms.h | 10 ++++
|
|
2 files changed, 109 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
|
|
index 052ec8a65c..9acc17b0d0 100644
|
|
--- a/src/backends/native/meta-kms.c
|
|
+++ b/src/backends/native/meta-kms.c
|
|
@@ -23,6 +23,7 @@
|
|
#include "backends/native/meta-kms-private.h"
|
|
|
|
#include "backends/native/meta-backend-native.h"
|
|
+#include "backends/native/meta-kms-crtc.h"
|
|
#include "backends/native/meta-kms-device-private.h"
|
|
#include "backends/native/meta-kms-impl.h"
|
|
#include "backends/native/meta-kms-update-private.h"
|
|
@@ -181,6 +182,11 @@ struct _MetaKms
|
|
|
|
G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
|
|
|
|
+static MetaKmsFeedback *
|
|
+meta_kms_post_update_sync (MetaKms *kms,
|
|
+ MetaKmsUpdate *update,
|
|
+ MetaKmsUpdateFlag flags);
|
|
+
|
|
void
|
|
meta_kms_discard_pending_updates (MetaKms *kms)
|
|
{
|
|
@@ -247,12 +253,105 @@ meta_kms_take_pending_update (MetaKms *kms,
|
|
return NULL;
|
|
}
|
|
|
|
+MetaKmsUpdate *
|
|
+meta_kms_ensure_pending_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc)
|
|
+{
|
|
+ MetaKmsUpdate *update;
|
|
+
|
|
+ update = meta_kms_get_pending_update_for_crtc (kms, crtc);
|
|
+ if (update == NULL)
|
|
+ {
|
|
+ update = meta_kms_update_new (meta_kms_crtc_get_device (crtc));
|
|
+ meta_kms_update_include_crtc (update, crtc);
|
|
+ meta_kms_add_pending_update (kms, update);
|
|
+ }
|
|
+
|
|
+ return update;
|
|
+}
|
|
+
|
|
+static MetaKmsUpdate *
|
|
+meta_kms_find_compatible_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc,
|
|
+ gboolean take)
|
|
+{
|
|
+ MetaKmsDevice *device;
|
|
+ MetaKmsUpdate *update;
|
|
+ GList *l;
|
|
+
|
|
+ for (l = kms->pending_updates; l; l = l->next)
|
|
+ {
|
|
+ update = l->data;
|
|
+ if (meta_kms_update_includes_crtc (update, crtc))
|
|
+ goto found;
|
|
+ }
|
|
+
|
|
+ device = meta_kms_crtc_get_device (crtc);
|
|
+
|
|
+ for (l = kms->pending_updates; l; l = l->next)
|
|
+ {
|
|
+ update = l->data;
|
|
+ if (meta_kms_update_get_device (update) == device &&
|
|
+ meta_kms_update_get_mode_sets (update))
|
|
+ goto found;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+
|
|
+found:
|
|
+ if (take)
|
|
+ kms->pending_updates = g_list_delete_link (kms->pending_updates, l);
|
|
+ return update;
|
|
+}
|
|
+
|
|
+MetaKmsUpdate *
|
|
+meta_kms_get_pending_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc)
|
|
+{
|
|
+ return meta_kms_find_compatible_update_for_crtc (kms, crtc, FALSE);
|
|
+}
|
|
+
|
|
+static MetaKmsUpdate *
|
|
+meta_kms_take_pending_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc)
|
|
+{
|
|
+ return meta_kms_find_compatible_update_for_crtc (kms, crtc, TRUE);
|
|
+}
|
|
+
|
|
MetaKmsFeedback *
|
|
meta_kms_post_pending_update_sync (MetaKms *kms,
|
|
MetaKmsDevice *device,
|
|
MetaKmsUpdateFlag flags)
|
|
{
|
|
MetaKmsUpdate *update;
|
|
+
|
|
+ update = meta_kms_take_pending_update (kms, device);
|
|
+ if (!update)
|
|
+ return NULL;
|
|
+
|
|
+ return meta_kms_post_update_sync (kms, update, flags);
|
|
+}
|
|
+
|
|
+MetaKmsFeedback *
|
|
+meta_kms_post_pending_update_for_crtc_sync (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc,
|
|
+ MetaKmsUpdateFlag flags)
|
|
+{
|
|
+ MetaKmsUpdate *update;
|
|
+
|
|
+ update = meta_kms_take_pending_update_for_crtc (kms, crtc);
|
|
+ if (!update)
|
|
+ return NULL;
|
|
+
|
|
+ return meta_kms_post_update_sync (kms, update, flags);
|
|
+}
|
|
+
|
|
+static MetaKmsFeedback *
|
|
+meta_kms_post_update_sync (MetaKms *kms,
|
|
+ MetaKmsUpdate *update,
|
|
+ MetaKmsUpdateFlag flags)
|
|
+{
|
|
+ MetaKmsDevice *device = meta_kms_update_get_device (update);
|
|
MetaKmsFeedback *feedback;
|
|
GList *result_listeners;
|
|
GList *l;
|
|
@@ -260,10 +359,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
|
|
COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync,
|
|
"KMS (post update)");
|
|
|
|
- update = meta_kms_take_pending_update (kms, device);
|
|
- if (!update)
|
|
- return NULL;
|
|
-
|
|
meta_kms_update_lock (update);
|
|
|
|
feedback = meta_kms_device_process_update_sync (device, update, flags);
|
|
diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h
|
|
index bd9fe5cead..84f1bed498 100644
|
|
--- a/src/backends/native/meta-kms.h
|
|
+++ b/src/backends/native/meta-kms.h
|
|
@@ -39,9 +39,15 @@ void meta_kms_discard_pending_updates (MetaKms *kms);
|
|
MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms,
|
|
MetaKmsDevice *device);
|
|
|
|
+MetaKmsUpdate * meta_kms_ensure_pending_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc);
|
|
+
|
|
MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms,
|
|
MetaKmsDevice *device);
|
|
|
|
+MetaKmsUpdate * meta_kms_get_pending_update_for_crtc (MetaKms *kms,
|
|
+ MetaKmsCrtc *crtc);
|
|
+
|
|
MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
|
|
MetaKmsDevice *device,
|
|
MetaKmsUpdateFlag flags);
|
|
@@ -49,6 +55,10 @@ MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
|
|
MetaKmsFeedback * meta_kms_post_test_update_sync (MetaKms *kms,
|
|
MetaKmsUpdate *update);
|
|
|
|
+MetaKmsFeedback * meta_kms_post_pending_update_for_crtc_sync (MetaKms *kms,
|
|
+ MetaKmsCrtc *device,
|
|
+ MetaKmsUpdateFlag flags);
|
|
+
|
|
void meta_kms_discard_pending_page_flips (MetaKms *kms);
|
|
|
|
void meta_kms_notify_modes_set (MetaKms *kms);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From c48a8338a6a6ec7f20d9b072faf8f6d84509ea48 Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 28 Jan 2022 15:46:09 +0800
|
|
Subject: [PATCH 42/44] cursor-renderer/native: Use CRTC-specific update
|
|
retrieval
|
|
|
|
---
|
|
src/backends/native/meta-cursor-renderer-native.c | 6 +++---
|
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
|
|
index 998af173d3..606fcad97f 100644
|
|
--- a/src/backends/native/meta-cursor-renderer-native.c
|
|
+++ b/src/backends/native/meta-cursor-renderer-native.c
|
|
@@ -291,8 +291,8 @@ assign_cursor_plane (MetaCursorRendererNative *native,
|
|
flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED;
|
|
|
|
kms_update =
|
|
- meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device),
|
|
- meta_kms_crtc_get_device (kms_crtc));
|
|
+ meta_kms_ensure_pending_update_for_crtc (meta_kms_device_get_kms (kms_device),
|
|
+ kms_crtc);
|
|
plane_assignment = meta_kms_update_assign_plane (kms_update,
|
|
kms_crtc,
|
|
cursor_plane,
|
|
@@ -440,7 +440,7 @@ unset_crtc_cursor (MetaCursorRendererNative *native,
|
|
MetaKms *kms = meta_kms_device_get_kms (kms_device);
|
|
MetaKmsUpdate *kms_update;
|
|
|
|
- kms_update = meta_kms_ensure_pending_update (kms, kms_device);
|
|
+ kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc);
|
|
meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane);
|
|
}
|
|
|
|
--
|
|
GitLab
|
|
|
|
|
|
From fe9b03f65bc168fd10aecdeae865405aa9e93aef Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 28 Jan 2022 15:50:24 +0800
|
|
Subject: [PATCH 43/44] crtc/native: Use CRTC-specific update retrieval
|
|
|
|
---
|
|
src/backends/native/meta-crtc-kms.c | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
|
|
index 584a780ba8..773b540b47 100644
|
|
--- a/src/backends/native/meta-crtc-kms.c
|
|
+++ b/src/backends/native/meta-crtc-kms.c
|
|
@@ -211,6 +211,7 @@ meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms,
|
|
MetaMonitorManagerNative *monitor_manager_native =
|
|
META_MONITOR_MANAGER_NATIVE (monitor_manager);
|
|
MetaKms *kms = meta_kms_device_get_kms (kms_device);
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
MetaKmsUpdate *kms_update;
|
|
MetaKmsCrtcGamma *gamma;
|
|
|
|
@@ -222,9 +223,9 @@ meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms,
|
|
if (!gamma)
|
|
return;
|
|
|
|
- kms_update = meta_kms_ensure_pending_update (kms, kms_device);
|
|
+ kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc);
|
|
meta_kms_update_set_crtc_gamma (kms_update,
|
|
- meta_crtc_kms_get_kms_crtc (crtc_kms),
|
|
+ kms_crtc,
|
|
gamma->size,
|
|
gamma->red,
|
|
gamma->green,
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 163776ae49fa9af98405d8225be6e23473d550dc Mon Sep 17 00:00:00 2001
|
|
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
Date: Fri, 28 Jan 2022 16:35:42 +0800
|
|
Subject: [PATCH 44/44] onscreen/native: Use CRTC-specific update retrieval
|
|
|
|
For mode setting we want all CRTCs to share the same MetaKmsUpdate, but
|
|
after that we don't want them to share the same update for regular flips
|
|
and cursor movement. The reason being that different CRTCs are attached to
|
|
different displays with different clocks. So each CRTC would finish the
|
|
same update at slightly different times.
|
|
|
|
If you wait for all CRTCs to complete a shared update then you have waited
|
|
half a frame on average, possibly more. This waiting would consume most of
|
|
the render time for the next frame and risk stuttering.
|
|
|
|
If you only wait for one CRTC to complete a shared update then the next
|
|
shared update may be posted before other CRTCs have finished the last, so
|
|
the next update would fail due to those other CRTCs still being busy.
|
|
|
|
So the only safe answer for maintaining full framerate of multiple outputs
|
|
is to ensure unsynchronized CRTCs don't share the same update. At least
|
|
not after mode setting.
|
|
|
|
This fixes a multi-monitor bug for atomic KMS whereby
|
|
`meta_onscreen_native_finish_frame` would fail its post because it was
|
|
trying to commit a cursor update on the wrong (busy) CRTC.
|
|
---
|
|
src/backends/native/meta-onscreen-native.c | 20 ++++++++++++--------
|
|
1 file changed, 12 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
|
index fb42ba7f4b..24d7f73852 100644
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
@@ -423,7 +423,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
|
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
|
|
kms = meta_kms_device_get_kms (kms_device);
|
|
- kms_update = meta_kms_ensure_pending_update (kms, kms_device);
|
|
+ kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc);
|
|
|
|
g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
|
|
|
|
@@ -478,7 +478,7 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen,
|
|
COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes,
|
|
"Onscreen (set CRTC modes)");
|
|
|
|
- kms_update = meta_kms_ensure_pending_update (kms, kms_device);
|
|
+ kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc);
|
|
|
|
switch (renderer_gpu_data->mode)
|
|
{
|
|
@@ -1280,7 +1280,9 @@ try_post_latest_swap (CoglOnscreen *onscreen)
|
|
meta_kms_device_get_path (kms_device));
|
|
|
|
flags = META_KMS_UPDATE_FLAG_NONE;
|
|
- kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
|
|
+ kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms,
|
|
+ kms_crtc,
|
|
+ flags);
|
|
g_return_if_fail (kms_feedback != NULL);
|
|
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
@@ -1438,7 +1440,9 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
|
meta_kms_device_get_path (kms_device));
|
|
|
|
flags = META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR;
|
|
- kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
|
|
+ kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms,
|
|
+ kms_crtc,
|
|
+ flags);
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
{
|
|
case META_KMS_FEEDBACK_PASSED:
|
|
@@ -1490,7 +1494,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
|
if (cogl_onscreen_count_pending_frames (onscreen) > 0)
|
|
return;
|
|
|
|
- kms_update = meta_kms_get_pending_update (kms, kms_device);
|
|
+ kms_update = meta_kms_get_pending_update_for_crtc (kms, kms_crtc);
|
|
if (!kms_update)
|
|
{
|
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
|
@@ -1505,9 +1509,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
|
g_object_unref);
|
|
|
|
flags = META_KMS_UPDATE_FLAG_NONE;
|
|
- kms_feedback = meta_kms_post_pending_update_sync (kms,
|
|
- kms_device,
|
|
- flags);
|
|
+ kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms,
|
|
+ kms_crtc,
|
|
+ flags);
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
{
|
|
case META_KMS_FEEDBACK_PASSED:
|
|
--
|
|
GitLab
|
|
|