Last active
December 15, 2018 21:08
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 (¶ms[0], G_TYPE_POINTER); | |
g_value_set_pointer (¶ms[0], flip_closure); | |
g_value_init (¶ms[1], G_TYPE_OBJECT); | |
g_value_set_object (¶ms[1], gpu_kms); | |
- g_closure_invoke (flip_closure, NULL, 2, params, NULL); | |
+ g_value_init (¶ms[2], G_TYPE_OBJECT); | |
+ g_value_set_object (¶ms[2], crtc); | |
+ g_value_init (¶ms[3], G_TYPE_INT64); | |
+ g_value_set_int64 (¶ms[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