Skip to content

Instantly share code, notes, and snippets.

@tonylambiris
Last active December 15, 2018 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonylambiris/eea7f90398e1a0a201a452e36b180277 to your computer and use it in GitHub Desktop.
Save tonylambiris/eea7f90398e1a0a201a452e36b180277 to your computer and use it in GitHub Desktop.
Backported mutter patch for 3.30.2 (https://gitlab.gnome.org/GNOME/mutter/merge_requests/171)
diff --git a/src/Makefile.am b/src/Makefile.am
index 811e2b86b..3826f896c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,8 @@ mutter_built_sources = \
$(dbus_login1_built_sources) \
meta/meta-enum-types.h \
meta-enum-types.c \
+ meta-marshal.c \
+ meta-marshal.h \
$(NULL)
if HAVE_REMOTE_DESKTOP
@@ -695,7 +698,10 @@ BUILT_SOURCES = \
$(libmutterinclude_built_headers)
MUTTER_STAMP_FILES = stamp-meta-enum-types.h
-CLEANFILES += $(MUTTER_STAMP_FILES)
+CLEANFILES += \
+ $(MUTTER_STAMP_FILES) \
+ meta-marshal.c \
+ meta-marshal.h
meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
@true
@@ -791,3 +797,20 @@ endef
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
%-server-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
+
+meta_marshal_opts = --prefix=meta_marshal --internal
+
+meta-marshal.h: meta-marshal.list
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
+ --header \
+ $(meta_marshal_opts) \
+ --output=$@ \
+ $<
+
+meta-marshal.c: meta-marshal.list meta-marshal.h
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
+ --include-header=meta-marshal.h \
+ $(meta_marshal_opts) \
+ --body \
+ --output=$@ \
+ $<
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 0f6ae87d353a6b5576f93a08e7f08c33b61dac56..974f8f4256693054cd80177e9cf7287b2a8816fc 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <poll.h>
#include <string.h>
+#include <time.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -53,6 +54,7 @@ typedef struct _MetaGpuKmsFlipClosureContainer
{
GClosure *flip_closure;
MetaGpuKms *gpu_kms;
+ MetaCrtc *crtc;
} MetaGpuKmsFlipClosureContainer;
struct _MetaGpuKms
@@ -64,6 +66,8 @@ struct _MetaGpuKms
char *file_path;
GSource *source;
+ clockid_t clock_id;
+
drmModeConnector **connectors;
unsigned int n_connectors;
@@ -173,18 +177,26 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
static void
invoke_flip_closure (GClosure *flip_closure,
- MetaGpuKms *gpu_kms)
+ MetaGpuKms *gpu_kms,
+ MetaCrtc *crtc,
+ int64_t page_flip_time_ns)
{
GValue params[] = {
G_VALUE_INIT,
- G_VALUE_INIT
+ G_VALUE_INIT,
+ G_VALUE_INIT,
+ G_VALUE_INIT,
};
g_value_init (&params[0], G_TYPE_POINTER);
g_value_set_pointer (&params[0], flip_closure);
g_value_init (&params[1], G_TYPE_OBJECT);
g_value_set_object (&params[1], gpu_kms);
- g_closure_invoke (flip_closure, NULL, 2, params, NULL);
+ g_value_init (&params[2], G_TYPE_OBJECT);
+ g_value_set_object (&params[2], crtc);
+ g_value_init (&params[3], G_TYPE_INT64);
+ g_value_set_int64 (&params[3], page_flip_time_ns);
+ g_closure_invoke (flip_closure, NULL, 4, params, NULL);
g_closure_unref (flip_closure);
}
@@ -224,6 +236,7 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
MetaGpuKmsFlipClosureContainer *
meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
+ MetaCrtc *crtc,
GClosure *flip_closure)
{
MetaGpuKmsFlipClosureContainer *closure_container;
@@ -231,7 +244,8 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
*closure_container = (MetaGpuKmsFlipClosureContainer) {
.flip_closure = flip_closure,
- .gpu_kms = gpu_kms
+ .gpu_kms = gpu_kms,
+ .crtc = crtc
};
return closure_container;
@@ -273,6 +287,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
+ crtc,
flip_closure);
ret = drmModePageFlip (kms_fd,
@@ -306,6 +321,23 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
return TRUE;
}
+static int64_t
+timespec_to_nanoseconds (const struct timespec *ts)
+{
+ const int64_t one_billion = 1000000000;
+
+ return ((int64_t) ts->tv_sec) * one_billion + ts->tv_nsec;
+}
+
+static int64_t
+timeval_to_nanoseconds (const struct timeval *tv)
+{
+ int64_t usec = ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec;
+ int64_t nsec = usec * 1000;
+
+ return nsec;
+}
+
static void
page_flip_handler (int fd,
unsigned int frame,
@@ -316,8 +348,12 @@ page_flip_handler (int fd,
MetaGpuKmsFlipClosureContainer *closure_container = user_data;
GClosure *flip_closure = closure_container->flip_closure;
MetaGpuKms *gpu_kms = closure_container->gpu_kms;
+ struct timeval page_flip_time = {sec, usec};
- invoke_flip_closure (flip_closure, gpu_kms);
+ invoke_flip_closure (flip_closure,
+ gpu_kms,
+ closure_container->crtc,
+ timeval_to_nanoseconds (&page_flip_time));
meta_gpu_kms_flip_closure_container_free (closure_container);
}
@@ -396,6 +432,17 @@ meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
return gpu_kms->file_path;
}
+int64_t
+meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
+{
+ struct timespec ts;
+
+ if (clock_gettime (gpu_kms->clock_id, &ts))
+ return 0;
+
+ return timespec_to_nanoseconds (&ts);
+}
+
void
meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
uint64_t state)
@@ -695,6 +742,17 @@ init_crtcs (MetaGpuKms *gpu_kms,
meta_gpu_take_crtcs (gpu, crtcs);
}
+static void
+init_frame_clock (MetaGpuKms *gpu_kms)
+{
+ uint64_t uses_monotonic;
+
+ if (drmGetCap (gpu_kms->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic) != 0)
+ uses_monotonic = 0;
+
+ gpu_kms->clock_id = uses_monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+}
+
static void
init_outputs (MetaGpuKms *gpu_kms,
MetaKmsResources *resources)
@@ -823,6 +881,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
init_modes (gpu_kms, resources.resources);
init_crtcs (gpu_kms, &resources);
init_outputs (gpu_kms, &resources);
+ init_frame_clock (gpu_kms);
meta_kms_resources_release (&resources);
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index 349db29906d9dafceb248d643a6eca3d8ae053ef..21fb04605e0da98f28dc904c52fa0371f11bf192 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -76,6 +76,8 @@ uint32_t meta_gpu_kms_get_id (MetaGpuKms *gpu_kms);
const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms);
+int64_t meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms);
+
void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms,
int *max_width,
int *max_height);
@@ -92,6 +94,7 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
+ MetaCrtc *crtc,
GClosure *flip_closure);
void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 6277dda204a9169df9345f663b15c8a23bfa5827..96afdc4d1d6eb220133c5d9f7eb52bb185a1020c 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -62,6 +62,7 @@
#include "backends/native/meta-monitor-manager-kms.h"
#include "backends/native/meta-renderer-native-gles3.h"
#include "backends/native/meta-renderer-native.h"
+#include "meta-marshal.h"
#include "cogl/cogl.h"
#include "core/boxes-private.h"
@@ -1160,6 +1161,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
static void
on_crtc_flipped (GClosure *closure,
MetaGpuKms *gpu_kms,
+ MetaCrtc *crtc,
+ int64_t page_flip_time_ns,
MetaRendererView *view)
{
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
@@ -1170,6 +1173,24 @@ on_crtc_flipped (GClosure *closure,
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
+ CoglFrameInfo *frame_info;
+ float refresh_rate;
+
+ frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
+ refresh_rate = crtc && crtc->current_mode ?
+ crtc->current_mode->refresh_rate :
+ 0.0f;
+
+ /* Only keep the frame info for the fastest CRTC in use, which may not be
+ * the first one to complete a flip. By only telling the compositor about the
+ * fastest monitor(s) we direct it to produce new frames fast enough to
+ * satisfy all monitors.
+ */
+ if (refresh_rate >= frame_info->refresh_rate)
+ {
+ frame_info->presentation_time = page_flip_time_ns;
+ frame_info->refresh_rate = refresh_rate;
+ }
if (gpu_kms != render_gpu)
{
@@ -1300,7 +1321,9 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
return FALSE;
closure_container =
- meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
+ meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu,
+ NULL,
+ flip_closure);
acquire_attribs = (EGLAttrib[]) {
EGL_DRM_FLIP_EVENT_DATA_NV,
@@ -1543,7 +1566,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
g_object_ref (view),
(GClosureNotify) flip_closure_destroyed);
- g_closure_set_marshal (flip_closure, g_cclosure_marshal_VOID__OBJECT);
+ g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
/* Either flip the CRTC's of the monitor info, if we are drawing just part
* of the stage, or all of the CRTC's if we are drawing the whole stage.
@@ -2059,6 +2082,13 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
TRUE);
+ /* COGL_WINSYS_FEATURE_SWAP_THROTTLE is always true for this renderer
+ * because we have the call to wait_for_pending_flips on every frame.
+ */
+ COGL_FLAGS_SET (cogl_context->winsys_features,
+ COGL_WINSYS_FEATURE_SWAP_THROTTLE,
+ TRUE);
+
#ifdef HAVE_EGL_DEVICE
if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE)
COGL_FLAGS_SET (cogl_context->features,
@@ -2694,8 +2724,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
}
onscreen = cogl_onscreen_new (context, width, height);
- cogl_onscreen_set_swap_throttled (onscreen,
- _clutter_get_sync_to_vblank ());
+
+ /* We have wait_for_pending_flips hardcoded, so throttling always. */
+ cogl_onscreen_set_swap_throttled (onscreen, TRUE);
+ if (!_clutter_get_sync_to_vblank ())
+ g_warning ("Request to disable sync-to-vblank is being ignored. "
+ "MetaRendererNative does not support disabling it.");
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
{
@@ -2765,6 +2799,15 @@ meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
return fb;
}
+static int64_t
+meta_renderer_native_get_clock_time (CoglContext *context)
+{
+ CoglRenderer *cogl_renderer = cogl_context_get_renderer (context);
+ MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data;
+
+ return meta_gpu_kms_get_current_time_ns (gpu_kms);
+}
+
static const CoglWinsysVtable *
get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
{
@@ -2793,6 +2836,8 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
vtable.onscreen_swap_buffers_with_damage =
meta_onscreen_native_swap_buffers_with_damage;
+ vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
+
vtable_inited = TRUE;
}
diff --git a/src/meta-marshal.list b/src/meta-marshal.list
new file mode 100644
index 0000000000000000000000000000000000000000..c1f4781d2d83cf5fe3a96b9e5ceb43c5900ce484
--- /dev/null
+++ b/src/meta-marshal.list
@@ -0,0 +1 @@
+VOID:OBJECT,OBJECT,INT64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment