Compare commits
22 commits
2cdcc4b9cc
...
8cba382d49
Author | SHA1 | Date | |
---|---|---|---|
|
8cba382d49 | ||
|
fd3373f9cf | ||
|
279baeaea4 | ||
|
f5b3b673ed | ||
|
302f71df9d | ||
|
71c1bf4cd4 | ||
|
0129d10266 | ||
|
64df19d2ba | ||
|
60a340218c | ||
|
3fe6990db9 | ||
|
2d9bffe681 | ||
|
b85dce10b1 | ||
|
1b407cb533 | ||
|
157ddfed97 | ||
|
d18752b3b2 | ||
|
25416e3f5b | ||
|
c1dc75704c | ||
|
40203436a6 | ||
|
1c938c80c4 | ||
|
7c22a88c97 | ||
|
247e70d9e2 | ||
|
ea64b55916 |
24 changed files with 755 additions and 190 deletions
|
@ -137,6 +137,8 @@ struct _ClutterFrameClock
|
|||
|
||||
int64_t last_dispatch_interval_us;
|
||||
|
||||
int64_t deadline_evasion_us;
|
||||
|
||||
char *output_name;
|
||||
};
|
||||
|
||||
|
@ -389,7 +391,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|||
|
||||
frame_clock->shortterm_max_update_duration_us =
|
||||
CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us +
|
||||
MAX (swap_to_rendering_done_us, swap_to_flip_us),
|
||||
MAX (swap_to_rendering_done_us, swap_to_flip_us) +
|
||||
frame_clock->deadline_evasion_us,
|
||||
frame_clock->shortterm_max_update_duration_us,
|
||||
frame_clock->refresh_interval_us);
|
||||
|
||||
|
@ -1253,3 +1256,10 @@ clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
|
|||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock,
|
||||
int64_t deadline_evasion_us)
|
||||
{
|
||||
frame_clock->deadline_evasion_us = deadline_evasion_us;
|
||||
}
|
||||
|
|
|
@ -106,3 +106,7 @@ void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
|||
int64_t flip_time_us);
|
||||
|
||||
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock,
|
||||
int64_t deadline_evasion_us);
|
||||
|
|
|
@ -740,6 +740,10 @@ clutter_stage_view_schedule_update (ClutterStageView *view)
|
|||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
|
||||
|
||||
if (view_class->schedule_update)
|
||||
view_class->schedule_update (view);
|
||||
|
||||
clutter_frame_clock_schedule_update (priv->frame_clock);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ struct _ClutterStageViewClass
|
|||
ClutterFrame * (* new_frame) (ClutterStageView *view);
|
||||
|
||||
ClutterPaintFlag (* get_default_paint_flags) (ClutterStageView *view);
|
||||
|
||||
void (* schedule_update) (ClutterStageView *view);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
|
|
|
@ -44,6 +44,11 @@ struct _MetaEgl
|
|||
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
|
||||
|
||||
PFNEGLCREATESYNCPROC eglCreateSync;
|
||||
PFNEGLDESTROYSYNCPROC eglDestroySync;
|
||||
PFNEGLWAITSYNCPROC eglWaitSync;
|
||||
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
|
||||
|
||||
PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL;
|
||||
PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL;
|
||||
|
||||
|
@ -1162,6 +1167,90 @@ meta_egl_query_display_attrib (MetaEgl *egl,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_create_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLenum type,
|
||||
const EGLAttrib *attrib_list,
|
||||
EGLSync *egl_sync,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglCreateSync, error))
|
||||
return FALSE;
|
||||
|
||||
EGLSync sync;
|
||||
|
||||
sync = egl->eglCreateSync (display, type, attrib_list);
|
||||
|
||||
if (sync == EGL_NO_SYNC)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*egl_sync = sync;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_destroy_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglDestroySync, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglDestroySync (display, sync))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_wait_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
EGLint flags,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglWaitSync, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglWaitSync (display, sync, flags))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EGLint
|
||||
meta_egl_duplicate_native_fence_fd (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglDupNativeFenceFDANDROID, error))
|
||||
return EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
||||
|
||||
EGLint fd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
||||
|
||||
fd = egl->eglDupNativeFenceFDANDROID (display, sync);
|
||||
|
||||
if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
||||
{
|
||||
set_egl_error (error);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#define GET_EGL_PROC_ADDR(proc) \
|
||||
egl->proc = (void *) eglGetProcAddress (#proc);
|
||||
|
||||
|
@ -1175,6 +1264,11 @@ meta_egl_constructed (GObject *object)
|
|||
GET_EGL_PROC_ADDR (eglCreateImageKHR);
|
||||
GET_EGL_PROC_ADDR (eglDestroyImageKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglCreateSync);
|
||||
GET_EGL_PROC_ADDR (eglDestroySync);
|
||||
GET_EGL_PROC_ADDR (eglWaitSync);
|
||||
GET_EGL_PROC_ADDR (eglDupNativeFenceFDANDROID);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL);
|
||||
GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL);
|
||||
|
||||
|
|
|
@ -276,3 +276,26 @@ gboolean meta_egl_query_display_attrib (MetaEgl *egl,
|
|||
EGLint attribute,
|
||||
EGLAttrib *value,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_create_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLenum type,
|
||||
const EGLAttrib *attrib_list,
|
||||
EGLSync *egl_sync,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_destroy_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_wait_sync (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
EGLint flags,
|
||||
GError **error);
|
||||
|
||||
EGLint meta_egl_duplicate_native_fence_fd (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLSync sync,
|
||||
GError **error);
|
||||
|
|
|
@ -348,6 +348,15 @@ meta_crtc_kms_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|||
return meta_kms_device_has_cursor_plane_for (kms_device, kms_crtc);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
meta_crtc_kms_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native);
|
||||
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
||||
|
||||
return meta_kms_crtc_get_deadline_evasion (kms_crtc);
|
||||
}
|
||||
|
||||
MetaKmsPlane *
|
||||
meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms)
|
||||
{
|
||||
|
@ -479,6 +488,7 @@ meta_crtc_kms_class_init (MetaCrtcKmsClass *klass)
|
|||
|
||||
crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled;
|
||||
crtc_native_class->is_hw_cursor_supported = meta_crtc_kms_is_hw_cursor_supported;
|
||||
crtc_native_class->get_deadline_evasion = meta_crtc_kms_get_deadline_evasion;
|
||||
|
||||
signals[GAMMA_LUT_CHANGED] =
|
||||
g_signal_new ("gamma-lut-changed",
|
||||
|
|
|
@ -39,6 +39,14 @@ meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|||
return klass->is_hw_cursor_supported (crtc_native);
|
||||
}
|
||||
|
||||
int64_t
|
||||
meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
||||
{
|
||||
MetaCrtcNativeClass *klass = META_CRTC_NATIVE_GET_CLASS (crtc_native);
|
||||
|
||||
return klass->get_deadline_evasion (crtc_native);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_crtc_native_init (MetaCrtcNative *crtc_native)
|
||||
{
|
||||
|
|
|
@ -31,9 +31,12 @@ struct _MetaCrtcNativeClass
|
|||
gboolean (* is_transform_handled) (MetaCrtcNative *crtc_native,
|
||||
MetaMonitorTransform monitor_transform);
|
||||
gboolean (* is_hw_cursor_supported) (MetaCrtcNative *crtc_native);
|
||||
int64_t (* get_deadline_evasion) (MetaCrtcNative *crtc_native);
|
||||
};
|
||||
|
||||
gboolean meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native,
|
||||
MetaMonitorTransform transform);
|
||||
|
||||
gboolean meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native);
|
||||
|
||||
int64_t meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native);
|
||||
|
|
|
@ -70,6 +70,12 @@ meta_crtc_virtual_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
meta_crtc_virtual_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_crtc_virtual_init (MetaCrtcVirtual *crtc_virtual)
|
||||
{
|
||||
|
@ -89,4 +95,6 @@ meta_crtc_virtual_class_init (MetaCrtcVirtualClass *klass)
|
|||
meta_crtc_virtual_is_transform_handled;
|
||||
crtc_native_class->is_hw_cursor_supported =
|
||||
meta_crtc_virtual_is_hw_cursor_supported;
|
||||
crtc_native_class->get_deadline_evasion =
|
||||
meta_crtc_virtual_get_deadline_evasion;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ struct _MetaFrameNative
|
|||
{
|
||||
ClutterFrame base;
|
||||
|
||||
MetaDrmBuffer *buffer;
|
||||
CoglScanout *scanout;
|
||||
|
||||
MetaKmsUpdate *kms_update;
|
||||
};
|
||||
|
||||
|
@ -35,6 +38,9 @@ meta_frame_native_release (ClutterFrame *frame)
|
|||
{
|
||||
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
||||
|
||||
g_clear_object (&frame_native->buffer);
|
||||
g_clear_object (&frame_native->scanout);
|
||||
|
||||
g_return_if_fail (!frame_native->kms_update);
|
||||
}
|
||||
|
||||
|
@ -76,3 +82,29 @@ meta_frame_native_has_kms_update (MetaFrameNative *frame_native)
|
|||
{
|
||||
return !!frame_native->kms_update;
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_native_set_buffer (MetaFrameNative *frame_native,
|
||||
MetaDrmBuffer *buffer)
|
||||
{
|
||||
g_set_object (&frame_native->buffer, buffer);
|
||||
}
|
||||
|
||||
MetaDrmBuffer *
|
||||
meta_frame_native_get_buffer (MetaFrameNative *frame_native)
|
||||
{
|
||||
return frame_native->buffer;
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_native_set_scanout (MetaFrameNative *frame_native,
|
||||
CoglScanout *scanout)
|
||||
{
|
||||
g_set_object (&frame_native->scanout, scanout);
|
||||
}
|
||||
|
||||
CoglScanout *
|
||||
meta_frame_native_get_scanout (MetaFrameNative *frame_native)
|
||||
{
|
||||
return frame_native->scanout;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "backends/native/meta-backend-native-types.h"
|
||||
#include "backends/native/meta-kms-types.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "core/util-private.h"
|
||||
|
@ -36,3 +37,13 @@ MetaKmsUpdate * meta_frame_native_steal_kms_update (MetaFrameNative *frame_nativ
|
|||
|
||||
META_EXPORT_TEST
|
||||
gboolean meta_frame_native_has_kms_update (MetaFrameNative *frame_native);
|
||||
|
||||
void meta_frame_native_set_buffer (MetaFrameNative *frame_native,
|
||||
MetaDrmBuffer *buffer);
|
||||
|
||||
MetaDrmBuffer * meta_frame_native_get_buffer (MetaFrameNative *frame_native);
|
||||
|
||||
void meta_frame_native_set_scanout (MetaFrameNative *frame_native,
|
||||
CoglScanout *scanout);
|
||||
|
||||
CoglScanout * meta_frame_native_get_scanout (MetaFrameNative *frame_native);
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
#include "backends/native/meta-kms-update-private.h"
|
||||
#include "backends/native/meta-kms-utils.h"
|
||||
|
||||
#define DEADLINE_EVASION_US 800
|
||||
#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000
|
||||
#define DEADLINE_EVASION_CONSTANT_US 200
|
||||
|
||||
#define MINIMUM_REFRESH_RATE 30.f
|
||||
|
||||
|
@ -50,6 +49,10 @@ struct _MetaKmsCrtc
|
|||
MetaKmsCrtcState current_state;
|
||||
|
||||
MetaKmsCrtcPropTable prop_table;
|
||||
|
||||
int64_t shortterm_max_dispatch_duration_us;
|
||||
int64_t deadline_evasion_us;
|
||||
int64_t deadline_evasion_update_time_us;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
|
||||
|
@ -543,6 +546,33 @@ get_crtc_type_bitmask (MetaKmsCrtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_update_deadline_evasion (MetaKmsCrtc *crtc,
|
||||
int64_t next_presentation_time_us)
|
||||
{
|
||||
/* Do not update long-term max if there has been no measurement */
|
||||
if (!crtc->shortterm_max_dispatch_duration_us)
|
||||
return;
|
||||
|
||||
if (next_presentation_time_us - crtc->deadline_evasion_update_time_us <
|
||||
G_USEC_PER_SEC)
|
||||
return;
|
||||
|
||||
if (crtc->deadline_evasion_us > crtc->shortterm_max_dispatch_duration_us)
|
||||
{
|
||||
/* Exponential drop-off toward the clamped short-term max */
|
||||
crtc->deadline_evasion_us -=
|
||||
(crtc->deadline_evasion_us - crtc->shortterm_max_dispatch_duration_us) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
crtc->deadline_evasion_us = crtc->shortterm_max_dispatch_duration_us;
|
||||
}
|
||||
|
||||
crtc->shortterm_max_dispatch_duration_us = 0;
|
||||
crtc->deadline_evasion_update_time_us = next_presentation_time_us;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
||||
int64_t *out_next_deadline_us,
|
||||
|
@ -610,10 +640,8 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
|||
*
|
||||
*/
|
||||
|
||||
if (meta_is_topic_enabled (META_DEBUG_KMS))
|
||||
deadline_evasion_us = DEADLINE_EVASION_WITH_KMS_TOPIC_US;
|
||||
else
|
||||
deadline_evasion_us = DEADLINE_EVASION_US;
|
||||
deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
|
||||
maybe_update_deadline_evasion (crtc, next_presentation_us);
|
||||
|
||||
vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode);
|
||||
next_deadline_us = next_presentation_us - (vblank_duration_us +
|
||||
|
@ -625,3 +653,33 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
|
||||
int64_t duration_us)
|
||||
{
|
||||
int64_t refresh_interval_us;
|
||||
|
||||
if (duration_us <= crtc->shortterm_max_dispatch_duration_us)
|
||||
return;
|
||||
|
||||
refresh_interval_us =
|
||||
(int64_t) (0.5 + G_USEC_PER_SEC /
|
||||
meta_calculate_drm_mode_refresh_rate (&crtc->current_state.drm_mode));
|
||||
|
||||
crtc->shortterm_max_dispatch_duration_us = MIN (duration_us, refresh_interval_us);
|
||||
}
|
||||
|
||||
int64_t
|
||||
meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc)
|
||||
{
|
||||
int64_t deadline_evasion_us;
|
||||
|
||||
deadline_evasion_us =
|
||||
MAX (crtc->shortterm_max_dispatch_duration_us, crtc->deadline_evasion_us);
|
||||
|
||||
if (!deadline_evasion_us)
|
||||
return 0;
|
||||
|
||||
return deadline_evasion_us + DEADLINE_EVASION_CONSTANT_US;
|
||||
}
|
||||
|
|
|
@ -65,3 +65,8 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc);
|
|||
|
||||
META_EXPORT_TEST
|
||||
gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc);
|
||||
|
||||
void meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
|
||||
int64_t duration_us);
|
||||
|
||||
int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc);
|
||||
|
|
|
@ -643,7 +643,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT)
|
||||
if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC)
|
||||
{
|
||||
int signaled_sync_file;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "backends/native/meta-kms-plane-private.h"
|
||||
#include "backends/native/meta-kms-plane.h"
|
||||
#include "backends/native/meta-kms-private.h"
|
||||
#include "backends/native/meta-kms-utils.h"
|
||||
#include "backends/native/meta-thread-private.h"
|
||||
|
||||
#include "meta-default-modes.h"
|
||||
|
@ -71,9 +72,17 @@ typedef struct _CrtcDeadline
|
|||
GSource *source;
|
||||
gboolean armed;
|
||||
gboolean is_deadline_page_flip;
|
||||
int64_t expected_deadline_time_us;
|
||||
int64_t expected_presentation_time_us;
|
||||
gboolean has_expected_presentation_time;
|
||||
} deadline;
|
||||
|
||||
struct {
|
||||
MetaKmsUpdate *kms_update;
|
||||
MetaKmsUpdateFlag flags;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
GSource *source;
|
||||
} submitted_update;
|
||||
} CrtcFrame;
|
||||
|
||||
typedef enum _MetaDeadlineTimerState
|
||||
|
@ -1165,6 +1174,7 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame,
|
|||
timerfd_settime (crtc_frame->deadline.timer_fd,
|
||||
TFD_TIMER_ABSTIME, &its, NULL);
|
||||
|
||||
crtc_frame->deadline.expected_deadline_time_us = next_deadline_us;
|
||||
crtc_frame->deadline.expected_presentation_time_us = next_presentation_us;
|
||||
crtc_frame->deadline.has_expected_presentation_time = next_presentation_us != 0;
|
||||
crtc_frame->deadline.armed = TRUE;
|
||||
|
@ -1197,7 +1207,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
|||
CrtcFrame *crtc_frame = user_data;
|
||||
|
||||
if (crtc_frame->deadline.is_deadline_page_flip &&
|
||||
meta_is_topic_enabled (META_DEBUG_KMS))
|
||||
meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
||||
{
|
||||
struct timeval page_flip_timeval;
|
||||
int64_t presentation_time_us;
|
||||
|
@ -1210,7 +1220,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
|||
|
||||
if (crtc_frame->deadline.has_expected_presentation_time)
|
||||
{
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
meta_topic (META_DEBUG_KMS_DEADLINE,
|
||||
"Deadline page flip presentation time: %" G_GINT64_FORMAT " us, "
|
||||
"expected %" G_GINT64_FORMAT " us "
|
||||
"(diff: %" G_GINT64_FORMAT ")",
|
||||
|
@ -1221,7 +1231,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
|||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
meta_topic (META_DEBUG_KMS_DEADLINE,
|
||||
"Deadline page flip presentation time: %" G_GINT64_FORMAT " us",
|
||||
presentation_time_us);
|
||||
}
|
||||
|
@ -1390,11 +1400,16 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
|
|||
GError **error)
|
||||
{
|
||||
CrtcFrame *crtc_frame = user_data;
|
||||
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
|
||||
MetaKmsCrtc *crtc = crtc_frame->crtc;
|
||||
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
g_autoptr (MetaKmsFeedback) feedback = NULL;
|
||||
uint64_t timer_value;
|
||||
ssize_t ret;
|
||||
int64_t dispatch_time_us = 0, update_done_time_us, interval_us;
|
||||
|
||||
if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
||||
dispatch_time_us = g_get_monotonic_time ();
|
||||
|
||||
ret = read (crtc_frame->deadline.timer_fd,
|
||||
&timer_value,
|
||||
|
@ -1416,6 +1431,36 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
|
|||
crtc_frame->crtc,
|
||||
g_steal_pointer (&crtc_frame->pending_update),
|
||||
META_KMS_UPDATE_FLAG_NONE);
|
||||
|
||||
update_done_time_us = g_get_monotonic_time ();
|
||||
/* Calculate how long after the planned start of deadline dispatch it finished */
|
||||
interval_us = update_done_time_us - crtc_frame->deadline.expected_deadline_time_us;
|
||||
|
||||
if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
||||
{
|
||||
int64_t deadline_evasion_us, lateness_us, duration_us, vblank_delta_us;
|
||||
|
||||
deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
|
||||
lateness_us = dispatch_time_us -
|
||||
crtc_frame->deadline.expected_deadline_time_us;
|
||||
duration_us = update_done_time_us - dispatch_time_us;
|
||||
vblank_delta_us = deadline_evasion_us - lateness_us - duration_us;
|
||||
|
||||
meta_topic (META_DEBUG_KMS_DEADLINE,
|
||||
"Deadline evasion %3"G_GINT64_FORMAT "µs, "
|
||||
"dispatch started %3"G_GINT64_FORMAT "µs %s and "
|
||||
"completed %3"G_GINT64_FORMAT "µs after that, "
|
||||
"%3"G_GINT64_FORMAT "µs %s start of vblank.",
|
||||
deadline_evasion_us,
|
||||
ABS (lateness_us),
|
||||
lateness_us >= 0 ? "late" : "early",
|
||||
duration_us,
|
||||
ABS (vblank_delta_us),
|
||||
vblank_delta_us >= 0 ? "before" : "after");
|
||||
}
|
||||
|
||||
meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us);
|
||||
|
||||
if (meta_kms_feedback_did_pass (feedback))
|
||||
crtc_frame->deadline.is_deadline_page_flip = TRUE;
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
|
@ -1429,6 +1474,8 @@ crtc_frame_free (CrtcFrame *crtc_frame)
|
|||
g_clear_fd (&crtc_frame->deadline.timer_fd, NULL);
|
||||
g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy);
|
||||
g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free);
|
||||
g_clear_pointer (&crtc_frame->submitted_update.kms_update, meta_kms_update_free);
|
||||
g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
||||
g_free (crtc_frame);
|
||||
}
|
||||
|
||||
|
@ -1530,6 +1577,79 @@ queue_update (MetaKmsImplDevice *impl_device,
|
|||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
meta_kms_impl_device_update_ready (MetaThreadImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
CrtcFrame *crtc_frame = user_data;
|
||||
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsUpdate *update;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
MetaKmsFeedback *feedback;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
||||
|
||||
update = g_steal_pointer (&crtc_frame->submitted_update.kms_update);
|
||||
meta_kms_update_realize (update, impl_device);
|
||||
|
||||
latch_crtc = g_steal_pointer (&crtc_frame->submitted_update.latch_crtc);
|
||||
|
||||
if (crtc_frame->pending_page_flip &&
|
||||
!meta_kms_update_get_mode_sets (update))
|
||||
{
|
||||
g_assert (latch_crtc);
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"Queuing update on CRTC %u (%s): pending page flip",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
|
||||
queue_update (impl_device, crtc_frame, update);
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
if (crtc_frame->pending_update)
|
||||
{
|
||||
meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
||||
meta_kms_update_free (update);
|
||||
update = g_steal_pointer (&crtc_frame->pending_update);
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
}
|
||||
|
||||
meta_kms_device_handle_flush (priv->device, latch_crtc);
|
||||
|
||||
feedback = do_process (impl_device, latch_crtc, update, crtc_frame->submitted_update.flags);
|
||||
|
||||
if (meta_kms_feedback_did_pass (feedback) &&
|
||||
crtc_frame->deadline.armed)
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
|
||||
meta_kms_feedback_unref (feedback);
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_fd_readable (int fd)
|
||||
{
|
||||
GPollFD poll_fd;
|
||||
|
||||
poll_fd.fd = fd;
|
||||
poll_fd.events = G_IO_IN;
|
||||
poll_fd.revents = 0;
|
||||
|
||||
if (!g_poll (&poll_fd, 1, 0))
|
||||
return FALSE;
|
||||
|
||||
return (poll_fd.revents & (G_IO_IN | G_IO_NVAL)) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdate *update,
|
||||
|
@ -1537,10 +1657,15 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
|||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl);
|
||||
g_autoptr (GError) error = NULL;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
CrtcFrame *crtc_frame;
|
||||
MetaKmsFeedback *feedback;
|
||||
g_autoptr (GSource) source = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
int sync_fd = -1;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
|
@ -1561,38 +1686,58 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
|||
if (!ensure_device_file (impl_device, &error))
|
||||
goto err;
|
||||
|
||||
meta_kms_update_realize (update, impl_device);
|
||||
|
||||
crtc_frame = ensure_crtc_frame (impl_device, latch_crtc);
|
||||
|
||||
crtc_frame->await_flush = FALSE;
|
||||
|
||||
if (crtc_frame->pending_page_flip &&
|
||||
!meta_kms_update_get_mode_sets (update))
|
||||
if (crtc_frame->submitted_update.kms_update)
|
||||
{
|
||||
g_assert (latch_crtc);
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_PENDING,
|
||||
"Previously-submitted update wasn't ready yet");
|
||||
goto err;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"Queuing update on CRTC %u (%s): pending page flip",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
crtc_frame->await_flush = FALSE;
|
||||
crtc_frame->submitted_update.kms_update = update;
|
||||
crtc_frame->submitted_update.flags = flags;
|
||||
crtc_frame->submitted_update.latch_crtc = latch_crtc;
|
||||
|
||||
queue_update (impl_device, crtc_frame, update);
|
||||
if (is_using_deadline_timer (impl_device))
|
||||
sync_fd = meta_kms_update_get_sync_fd (update);
|
||||
|
||||
if (sync_fd >= 0)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
||||
{
|
||||
MetaKmsPlaneAssignment *assignment = l->data;
|
||||
|
||||
assignment->flags |= META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
if (sync_fd < 0 ||
|
||||
is_fd_readable (sync_fd))
|
||||
{
|
||||
meta_kms_impl_device_update_ready (thread_impl,
|
||||
crtc_frame,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (crtc_frame->pending_update)
|
||||
{
|
||||
meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
||||
meta_kms_update_free (update);
|
||||
update = g_steal_pointer (&crtc_frame->pending_update);
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
}
|
||||
source = meta_thread_impl_register_fd (thread_impl,
|
||||
sync_fd,
|
||||
meta_kms_impl_device_update_ready,
|
||||
crtc_frame);
|
||||
|
||||
meta_kms_device_handle_flush (priv->device, latch_crtc);
|
||||
name = g_strdup_printf ("[mutter] KMS update sync_fd (crtc: %u, %s)",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
g_source_set_name (source, name);
|
||||
g_source_set_priority (source, G_PRIORITY_HIGH + 1);
|
||||
g_source_set_can_recurse (source, FALSE);
|
||||
g_source_set_ready_time (source, -1);
|
||||
|
||||
feedback = do_process (impl_device, latch_crtc, update, flags);
|
||||
meta_kms_feedback_unref (feedback);
|
||||
crtc_frame->submitted_update.source = source;
|
||||
return;
|
||||
|
||||
err:
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "backends/native/meta-kms-update.h"
|
||||
#include "backends/native/meta-kms-update-private.h"
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "backends/meta-display-config-shared.h"
|
||||
#include "backends/native/meta-kms-connector.h"
|
||||
#include "backends/native/meta-kms-crtc.h"
|
||||
|
@ -51,6 +53,8 @@ struct _MetaKmsUpdate
|
|||
gboolean needs_modeset;
|
||||
|
||||
MetaKmsImplDevice *impl_device;
|
||||
|
||||
int sync_fd;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -1136,6 +1140,8 @@ meta_kms_update_merge_from (MetaKmsUpdate *update,
|
|||
merge_custom_page_flip_from (update, other_update);
|
||||
merge_page_flip_listeners_from (update, other_update);
|
||||
merge_result_listeners_from (update, other_update);
|
||||
|
||||
meta_kms_update_set_sync_fd (update, g_steal_fd (&other_update->sync_fd));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1152,6 +1158,7 @@ meta_kms_update_new (MetaKmsDevice *device)
|
|||
update = g_new0 (MetaKmsUpdate, 1);
|
||||
update->device = device;
|
||||
update->is_latchable = TRUE;
|
||||
update->sync_fd = -1;
|
||||
|
||||
return update;
|
||||
}
|
||||
|
@ -1175,6 +1182,7 @@ meta_kms_update_free (MetaKmsUpdate *update)
|
|||
g_list_free_full (update->crtc_color_updates,
|
||||
(GDestroyNotify) meta_kms_crtc_color_updates_free);
|
||||
g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free);
|
||||
g_clear_fd (&update->sync_fd, NULL);
|
||||
|
||||
g_free (update);
|
||||
}
|
||||
|
@ -1200,6 +1208,23 @@ meta_kms_update_get_latch_crtc (MetaKmsUpdate *update)
|
|||
return update->latch_crtc;
|
||||
}
|
||||
|
||||
int
|
||||
meta_kms_update_get_sync_fd (MetaKmsUpdate *update)
|
||||
{
|
||||
return update->sync_fd;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_update_set_sync_fd (MetaKmsUpdate *update,
|
||||
int sync_fd)
|
||||
{
|
||||
if (update->sync_fd == sync_fd)
|
||||
return;
|
||||
|
||||
g_clear_fd (&update->sync_fd, NULL);
|
||||
update->sync_fd = sync_fd;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_update_is_empty (MetaKmsUpdate *update)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef enum _MetaKmsAssignPlaneFlag
|
|||
META_KMS_ASSIGN_PLANE_FLAG_NONE = 0,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL = 1 << 1,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT = 1 << 2,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC = 1 << 2,
|
||||
} MetaKmsAssignPlaneFlag;
|
||||
|
||||
struct _MetaKmsPageFlipListenerVtable
|
||||
|
@ -157,6 +157,13 @@ void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
|
|||
MetaKmsCrtc *crtc,
|
||||
const MetaGammaLut *gamma);
|
||||
|
||||
int
|
||||
meta_kms_update_get_sync_fd (MetaKmsUpdate *update);
|
||||
|
||||
void
|
||||
meta_kms_update_set_sync_fd (MetaKmsUpdate *update,
|
||||
int sync_fd);
|
||||
|
||||
void meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "backends/native/meta-onscreen-native.h"
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include "backends/meta-egl-ext.h"
|
||||
|
@ -102,12 +103,11 @@ struct _MetaOnscreenNative
|
|||
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||
|
||||
ClutterFrame *presented_frame;
|
||||
ClutterFrame *next_frame;
|
||||
|
||||
struct {
|
||||
struct gbm_surface *surface;
|
||||
MetaDrmBuffer *current_fb;
|
||||
MetaDrmBuffer *next_fb;
|
||||
CoglScanout *current_scanout;
|
||||
CoglScanout *next_scanout;
|
||||
} gbm;
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
|
@ -144,30 +144,17 @@ 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);
|
||||
g_clear_object (&onscreen_native->gbm.current_scanout);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
||||
{
|
||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||
|
||||
if (!onscreen_native->gbm.next_fb)
|
||||
if (!onscreen_native->next_frame)
|
||||
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);
|
||||
g_set_object (&onscreen_native->gbm.current_scanout,
|
||||
onscreen_native->gbm.next_scanout);
|
||||
g_clear_object (&onscreen_native->gbm.next_scanout);
|
||||
g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref);
|
||||
onscreen_native->presented_frame =
|
||||
g_steal_pointer (&onscreen_native->next_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -175,8 +162,7 @@ meta_onscreen_native_clear_next_fb (CoglOnscreen *onscreen)
|
|||
{
|
||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||
|
||||
g_clear_object (&onscreen_native->gbm.next_fb);
|
||||
g_clear_object (&onscreen_native->gbm.next_scanout);
|
||||
g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -311,7 +297,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc,
|
|||
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
||||
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
||||
|
||||
g_warn_if_fail (!onscreen_native->gbm.next_fb);
|
||||
g_warn_if_fail (!onscreen_native->next_frame);
|
||||
|
||||
meta_onscreen_native_notify_frame_complete (onscreen);
|
||||
}
|
||||
|
@ -528,12 +514,15 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||
{
|
||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
||||
ClutterFrame *frame = onscreen_native->next_frame;
|
||||
MetaFrameNative *frame_native;
|
||||
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
||||
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
|
||||
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
MetaGpuKms *gpu_kms;
|
||||
MetaDrmBuffer *buffer;
|
||||
CoglScanout *scanout;
|
||||
MetaKmsPlaneAssignment *plane_assignment;
|
||||
graphene_rect_t src_rect;
|
||||
MtkRectangle dst_rect;
|
||||
|
@ -541,6 +530,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||
COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
|
||||
"Meta::OnscreenNative::flip_crtc()");
|
||||
|
||||
g_return_if_fail (frame);
|
||||
|
||||
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||
|
||||
g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
|
||||
|
@ -550,14 +541,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
buffer = onscreen_native->gbm.next_fb;
|
||||
frame_native = meta_frame_native_from_frame (frame);
|
||||
buffer = meta_frame_native_get_buffer (frame_native);
|
||||
scanout = meta_frame_native_get_scanout (frame_native);
|
||||
|
||||
if (onscreen_native->gbm.next_scanout)
|
||||
if (scanout)
|
||||
{
|
||||
cogl_scanout_get_src_rect (onscreen_native->gbm.next_scanout,
|
||||
&src_rect);
|
||||
cogl_scanout_get_dst_rect (onscreen_native->gbm.next_scanout,
|
||||
&dst_rect);
|
||||
cogl_scanout_get_src_rect (scanout, &src_rect);
|
||||
cogl_scanout_get_dst_rect (scanout, &dst_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -848,29 +839,63 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
|
|||
}
|
||||
|
||||
static MetaDrmBuffer *
|
||||
copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
gboolean *egl_context_changed,
|
||||
MetaDrmBuffer *primary_gpu_fb)
|
||||
copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
MetaDrmBuffer *primary_gpu_fb,
|
||||
GError **error)
|
||||
{
|
||||
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);
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys;
|
||||
MetaRenderDevice *render_device;
|
||||
EGLDisplay egl_display;
|
||||
GError *error = NULL;
|
||||
EGLDisplay egl_display = NULL;
|
||||
gboolean use_modifiers;
|
||||
MetaDeviceFile *device_file;
|
||||
MetaDrmBufferFlags flags;
|
||||
MetaDrmBufferGbm *buffer_gbm;
|
||||
MetaDrmBufferGbm *buffer_gbm = NULL;
|
||||
struct gbm_bo *bo;
|
||||
EGLSync primary_gpu_egl_sync = EGL_NO_SYNC;
|
||||
EGLSync secondary_gpu_egl_sync = EGL_NO_SYNC;
|
||||
g_autofd int primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu,
|
||||
"copy_shared_framebuffer_gpu()");
|
||||
|
||||
if (renderer_gpu_data->secondary.needs_explicit_sync)
|
||||
cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen));
|
||||
{
|
||||
if (!meta_egl_create_sync (egl,
|
||||
cogl_renderer_egl->edpy,
|
||||
EGL_SYNC_NATIVE_FENCE_ANDROID,
|
||||
NULL,
|
||||
&primary_gpu_egl_sync,
|
||||
error))
|
||||
{
|
||||
g_prefix_error (error, "Failed to create EGLSync on primary GPU: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// According to the EGL_KHR_fence_sync specification we must ensure
|
||||
// the fence command is flushed in this context to be able to await it
|
||||
// in another (secondary GPU context) or we risk waiting indefinitely.
|
||||
cogl_framebuffer_flush (COGL_FRAMEBUFFER (onscreen));
|
||||
|
||||
primary_gpu_sync_fence =
|
||||
meta_egl_duplicate_native_fence_fd (egl,
|
||||
cogl_renderer_egl->edpy,
|
||||
primary_gpu_egl_sync,
|
||||
error);
|
||||
|
||||
if (primary_gpu_sync_fence == EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
||||
{
|
||||
g_prefix_error (error, "Failed to duplicate EGLSync FD on primary GPU: ");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
render_device = renderer_gpu_data->render_device;
|
||||
egl_display = meta_render_device_get_egl_display (render_device);
|
||||
|
@ -880,15 +905,45 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|||
secondary_gpu_state->egl_surface,
|
||||
secondary_gpu_state->egl_surface,
|
||||
renderer_gpu_data->secondary.egl_context,
|
||||
&error))
|
||||
error))
|
||||
{
|
||||
g_warning ("Failed to make current: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
g_prefix_error (error, "Failed to make current: ");
|
||||
goto done;
|
||||
}
|
||||
|
||||
*egl_context_changed = TRUE;
|
||||
if (primary_gpu_sync_fence != EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
||||
{
|
||||
EGLAttrib attribs[3];
|
||||
|
||||
attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
|
||||
attribs[1] = primary_gpu_sync_fence;
|
||||
attribs[2] = EGL_NONE;
|
||||
|
||||
if (!meta_egl_create_sync (egl,
|
||||
egl_display,
|
||||
EGL_SYNC_NATIVE_FENCE_ANDROID,
|
||||
attribs,
|
||||
&secondary_gpu_egl_sync,
|
||||
error))
|
||||
{
|
||||
g_prefix_error (error, "Failed to create EGLSync on secondary GPU: ");
|
||||
goto done;
|
||||
}
|
||||
|
||||
// eglCreateSync takes ownership of an existing fd that is passed, so
|
||||
// don't try to clean it up twice.
|
||||
primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
||||
|
||||
if (!meta_egl_wait_sync (egl,
|
||||
egl_display,
|
||||
secondary_gpu_egl_sync,
|
||||
0,
|
||||
error))
|
||||
{
|
||||
g_prefix_error (error, "Failed to wait for EGLSync on secondary GPU: ");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb);
|
||||
bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
|
||||
|
@ -898,21 +953,19 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|||
renderer_gpu_data->secondary.egl_context,
|
||||
secondary_gpu_state->egl_surface,
|
||||
bo,
|
||||
&error))
|
||||
error))
|
||||
{
|
||||
g_warning ("Failed to blit shared framebuffer: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
g_prefix_error (error, "Failed to blit shared framebuffer: ");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!meta_egl_swap_buffers (egl,
|
||||
egl_display,
|
||||
secondary_gpu_state->egl_surface,
|
||||
&error))
|
||||
error))
|
||||
{
|
||||
g_warning ("Failed to swap buffers: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
g_prefix_error (error, "Failed to swap buffers: ");
|
||||
goto done;
|
||||
}
|
||||
|
||||
use_modifiers = meta_renderer_native_use_modifiers (renderer_native);
|
||||
|
@ -926,13 +979,11 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|||
meta_drm_buffer_gbm_new_lock_front (device_file,
|
||||
secondary_gpu_state->gbm.surface,
|
||||
flags,
|
||||
&error);
|
||||
error);
|
||||
if (!buffer_gbm)
|
||||
{
|
||||
g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
g_prefix_error (error, "meta_drm_buffer_gbm_new_lock_front failed: ");
|
||||
goto done;
|
||||
}
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (buffer_gbm),
|
||||
|
@ -940,7 +991,24 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|||
g_object_ref (primary_gpu_fb),
|
||||
g_object_unref);
|
||||
|
||||
return META_DRM_BUFFER (buffer_gbm);
|
||||
done:
|
||||
_cogl_winsys_egl_ensure_current (cogl_display);
|
||||
|
||||
if (primary_gpu_egl_sync != EGL_NO_SYNC &&
|
||||
!meta_egl_destroy_sync (egl,
|
||||
cogl_renderer_egl->edpy,
|
||||
primary_gpu_egl_sync,
|
||||
error))
|
||||
g_prefix_error (error, "Failed to destroy primary GPU EGLSync: ");
|
||||
|
||||
if (secondary_gpu_egl_sync != EGL_NO_SYNC &&
|
||||
!meta_egl_destroy_sync (egl,
|
||||
egl_display,
|
||||
secondary_gpu_egl_sync,
|
||||
error))
|
||||
g_prefix_error (error, "Failed to destroy secondary GPU EGLSync: ");
|
||||
|
||||
return buffer_gbm ? META_DRM_BUFFER (buffer_gbm) : NULL;
|
||||
}
|
||||
|
||||
static MetaDrmBufferDumb *
|
||||
|
@ -1192,56 +1260,54 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
|||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
||||
gboolean *egl_context_changed,
|
||||
MetaDrmBuffer *primary_gpu_fb,
|
||||
MetaDrmBuffer **secondary_gpu_fb)
|
||||
static MetaDrmBuffer *
|
||||
acquire_front_buffer (CoglOnscreen *onscreen,
|
||||
MetaDrmBuffer *primary_gpu_fb,
|
||||
MetaDrmBuffer *secondary_gpu_fb,
|
||||
GError **error)
|
||||
{
|
||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
MetaDrmBuffer *imported_fb;
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePostSwapBuffers,
|
||||
"update_secondary_gpu_state_post_swap_buffers()");
|
||||
"acquire_front_buffer()");
|
||||
|
||||
secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
||||
if (secondary_gpu_state)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
g_autoptr (MetaDrmBuffer) next_fb = NULL;
|
||||
if (!secondary_gpu_state)
|
||||
return g_object_ref (primary_gpu_fb);
|
||||
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (renderer_native,
|
||||
secondary_gpu_state->gpu_kms);
|
||||
switch (renderer_gpu_data->secondary.copy_mode)
|
||||
{
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO:
|
||||
next_fb = import_shared_framebuffer (onscreen,
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (renderer_native,
|
||||
secondary_gpu_state->gpu_kms);
|
||||
switch (renderer_gpu_data->secondary.copy_mode)
|
||||
{
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO:
|
||||
imported_fb = import_shared_framebuffer (onscreen,
|
||||
secondary_gpu_state,
|
||||
primary_gpu_fb);
|
||||
if (next_fb)
|
||||
break;
|
||||
/* 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:
|
||||
next_fb = g_object_ref (*secondary_gpu_fb);
|
||||
break;
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU:
|
||||
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);
|
||||
if (imported_fb)
|
||||
return imported_fb;
|
||||
/* 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:
|
||||
return g_object_ref (secondary_gpu_fb);
|
||||
case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU:
|
||||
return copy_shared_framebuffer_gpu (onscreen,
|
||||
secondary_gpu_state,
|
||||
renderer_gpu_data,
|
||||
primary_gpu_fb,
|
||||
error);
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1303,7 +1369,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
||||
|
@ -1321,15 +1386,18 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
MetaKmsUpdate *kms_update;
|
||||
CoglOnscreenClass *parent_class;
|
||||
gboolean create_timestamp_query = TRUE;
|
||||
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;
|
||||
g_autoptr (MetaDrmBuffer) buffer = NULL;
|
||||
MetaKmsCrtc *kms_crtc;
|
||||
MetaKmsDevice *kms_device;
|
||||
int sync_fd;
|
||||
|
||||
COGL_TRACE_SCOPED_ANCHOR (MetaRendererNativePostKmsUpdate);
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
||||
"Meta::OnscreenNative::swap_buffers_with_damage()");
|
||||
|
@ -1383,46 +1451,28 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
g_warning ("Failed to lock front buffer on %s: %s",
|
||||
meta_device_file_get_path (render_device_file),
|
||||
error->message);
|
||||
|
||||
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
||||
meta_onscreen_native_notify_frame_complete (onscreen);
|
||||
return;
|
||||
goto swap_failed;
|
||||
}
|
||||
|
||||
primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm));
|
||||
break;
|
||||
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
buffer = acquire_front_buffer (onscreen,
|
||||
primary_gpu_fb,
|
||||
secondary_gpu_fb,
|
||||
&error);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
g_warning ("Failed to acquire front buffer: %s", error->message);
|
||||
goto swap_failed;
|
||||
}
|
||||
|
||||
update_secondary_gpu_state_post_swap_buffers (onscreen,
|
||||
&egl_context_changed,
|
||||
primary_gpu_fb,
|
||||
&secondary_gpu_fb);
|
||||
meta_frame_native_set_buffer (frame_native, buffer);
|
||||
|
||||
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);
|
||||
|
||||
if (!meta_drm_buffer_ensure_fb_id (onscreen_native->gbm.next_fb, &error))
|
||||
if (!meta_drm_buffer_ensure_fb_id (buffer, &error))
|
||||
{
|
||||
g_warning ("Failed to ensure KMS FB ID on %s: %s",
|
||||
meta_device_file_get_path (render_device_file),
|
||||
error->message);
|
||||
|
||||
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
||||
meta_onscreen_native_notify_frame_complete (onscreen);
|
||||
return;
|
||||
goto swap_failed;
|
||||
}
|
||||
break;
|
||||
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
||||
|
@ -1433,14 +1483,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* EGL_NO_CONTEXT current now, making cogl eventually set the correct
|
||||
* context.
|
||||
*/
|
||||
if (egl_context_changed)
|
||||
_cogl_winsys_egl_ensure_current (cogl_display);
|
||||
g_warn_if_fail (!onscreen_native->next_frame);
|
||||
onscreen_native->next_frame = clutter_frame_ref (frame);
|
||||
|
||||
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
|
||||
kms_device = meta_kms_crtc_get_device (kms_crtc);
|
||||
|
@ -1474,8 +1518,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
return;
|
||||
}
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate,
|
||||
"Meta::OnscreenNative::swap_buffers_with_damage#post_pending_update()");
|
||||
COGL_TRACE_BEGIN_ANCHORED (MetaRendererNativePostKmsUpdate,
|
||||
"Meta::OnscreenNative::swap_buffers_with_damage#post_pending_update()");
|
||||
|
||||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
|
@ -1536,9 +1580,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||
meta_kms_device_get_path (kms_device));
|
||||
|
||||
kms_update = meta_frame_native_steal_kms_update (frame_native);
|
||||
sync_fd = cogl_context_get_latest_sync_fd (cogl_context);
|
||||
meta_kms_update_set_sync_fd (kms_update, sync_fd);
|
||||
meta_kms_device_post_update (kms_device, kms_update,
|
||||
META_KMS_UPDATE_FLAG_NONE);
|
||||
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
||||
return;
|
||||
|
||||
swap_failed:
|
||||
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
||||
meta_onscreen_native_notify_frame_complete (onscreen);
|
||||
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1571,7 +1623,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
|||
assign_primary_plane (crtc_kms,
|
||||
buffer,
|
||||
test_update,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC,
|
||||
&src_rect,
|
||||
&dst_rect);
|
||||
|
||||
|
@ -1606,11 +1658,15 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback,
|
|||
G_IO_ERROR_PERMISSION_DENIED))
|
||||
{
|
||||
ClutterStageView *view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
||||
ClutterFrame *next_frame = onscreen_native->next_frame;
|
||||
MetaFrameNative *next_frame_native =
|
||||
meta_frame_native_from_frame (next_frame);
|
||||
CoglScanout *scanout =
|
||||
meta_frame_native_get_scanout (next_frame_native);
|
||||
|
||||
g_warning ("Direct scanout page flip failed: %s", error->message);
|
||||
|
||||
cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout,
|
||||
onscreen);
|
||||
cogl_scanout_notify_failed (scanout, onscreen);
|
||||
clutter_stage_view_add_redraw_clip (view, NULL);
|
||||
clutter_stage_view_schedule_update_now (view);
|
||||
}
|
||||
|
@ -1675,12 +1731,13 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
|||
render_gpu);
|
||||
|
||||
g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM);
|
||||
g_warn_if_fail (!onscreen_native->gbm.next_fb);
|
||||
g_warn_if_fail (!onscreen_native->gbm.next_scanout);
|
||||
|
||||
g_set_object (&onscreen_native->gbm.next_scanout, scanout);
|
||||
g_set_object (&onscreen_native->gbm.next_fb,
|
||||
META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)));
|
||||
g_warn_if_fail (!onscreen_native->next_frame);
|
||||
onscreen_native->next_frame = clutter_frame_ref (frame);
|
||||
|
||||
meta_frame_native_set_scanout (frame_native, scanout);
|
||||
meta_frame_native_set_buffer (frame_native,
|
||||
META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)));
|
||||
|
||||
frame_info->cpu_time_before_buffer_swap_us = g_get_monotonic_time ();
|
||||
|
||||
|
@ -1701,7 +1758,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
|||
onscreen_native->view,
|
||||
onscreen_native->crtc,
|
||||
kms_update,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
|
@ -1786,11 +1843,15 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen,
|
|||
ClutterFrame *frame)
|
||||
{
|
||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||
MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
||||
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
||||
|
||||
meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc),
|
||||
kms_crtc);
|
||||
if (meta_get_debug_paint_flags () & META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
||||
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
||||
|
||||
meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), kms_crtc);
|
||||
}
|
||||
|
||||
maybe_update_frame_sync (onscreen_native, frame);
|
||||
}
|
||||
|
||||
|
@ -2865,15 +2926,15 @@ meta_onscreen_native_dispose (GObject *object)
|
|||
|
||||
meta_onscreen_native_detach (onscreen_native);
|
||||
|
||||
g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref);
|
||||
g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref);
|
||||
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (renderer_native,
|
||||
onscreen_native->render_gpu);
|
||||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
g_clear_object (&onscreen_native->gbm.next_fb);
|
||||
g_clear_object (&onscreen_native->gbm.next_scanout);
|
||||
free_current_bo (onscreen);
|
||||
break;
|
||||
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
||||
g_assert_not_reached ();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "backends/native/meta-renderer-view-native.h"
|
||||
|
||||
#include "backends/native/meta-crtc-native.h"
|
||||
#include "backends/native/meta-frame-native.h"
|
||||
|
||||
struct _MetaRendererViewNative
|
||||
|
@ -34,18 +35,58 @@ struct _MetaRendererViewNative
|
|||
G_DEFINE_TYPE (MetaRendererViewNative, meta_renderer_view_native,
|
||||
META_TYPE_RENDERER_VIEW)
|
||||
|
||||
static void
|
||||
update_frame_clock_deadline_evasion (MetaRendererView *renderer_view)
|
||||
{
|
||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view);
|
||||
ClutterFrameClock *frame_clock;
|
||||
MetaCrtc *crtc;
|
||||
MetaCrtcNative *crtc_native;
|
||||
int64_t deadline_evasion_us;
|
||||
|
||||
frame_clock = clutter_stage_view_get_frame_clock (stage_view);
|
||||
crtc = meta_renderer_view_get_crtc (renderer_view);
|
||||
crtc_native = META_CRTC_NATIVE (crtc);
|
||||
|
||||
deadline_evasion_us = meta_crtc_native_get_deadline_evasion (crtc_native);
|
||||
clutter_frame_clock_set_deadline_evasion (frame_clock,
|
||||
deadline_evasion_us);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_native_constructed (GObject *object)
|
||||
{
|
||||
MetaRendererView *renderer_view = META_RENDERER_VIEW (object);
|
||||
|
||||
G_OBJECT_CLASS (meta_renderer_view_native_parent_class)->constructed (object);
|
||||
|
||||
update_frame_clock_deadline_evasion (renderer_view);
|
||||
}
|
||||
|
||||
static ClutterFrame *
|
||||
meta_renderer_view_native_new_frame (ClutterStageView *stage_view)
|
||||
{
|
||||
return (ClutterFrame *) meta_frame_native_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_native_schedule_update (ClutterStageView *stage_view)
|
||||
{
|
||||
MetaRendererView *renderer_view = META_RENDERER_VIEW (stage_view);
|
||||
|
||||
update_frame_clock_deadline_evasion (renderer_view);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_native_class_init (MetaRendererViewNativeClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterStageViewClass *stage_view_class = CLUTTER_STAGE_VIEW_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_renderer_view_native_constructed;
|
||||
|
||||
stage_view_class->new_frame = meta_renderer_view_native_new_frame;
|
||||
stage_view_class->schedule_update = meta_renderer_view_native_schedule_update;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -69,6 +69,7 @@ static const GDebugKey meta_debug_keys[] = {
|
|||
{ "color", META_DEBUG_COLOR },
|
||||
{ "input-events", META_DEBUG_INPUT_EVENTS },
|
||||
{ "eis", META_DEBUG_EIS },
|
||||
{ "kms-deadline", META_DEBUG_KMS_DEADLINE },
|
||||
};
|
||||
|
||||
static gint verbose_topics = 0;
|
||||
|
@ -326,6 +327,8 @@ meta_topic_to_string (MetaDebugTopic topic)
|
|||
return "INPUT_EVENTS";
|
||||
case META_DEBUG_EIS:
|
||||
return "EIS";
|
||||
case META_DEBUG_KMS_DEADLINE:
|
||||
return "KMS_DEADLINE";
|
||||
}
|
||||
|
||||
return "WM";
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
* @META_DEBUG_COLOR: color management
|
||||
* @META_DEBUG_INPUT_EVENTS: input events
|
||||
* @META_DEBUG_EIS: eis state
|
||||
* @META_DEBUG_KMS_DEADLINE: KMS deadline timers
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
|
@ -83,6 +84,7 @@ typedef enum
|
|||
META_DEBUG_COLOR = 1 << 26,
|
||||
META_DEBUG_INPUT_EVENTS = 1 << 27,
|
||||
META_DEBUG_EIS = 1 << 28,
|
||||
META_DEBUG_KMS_DEADLINE = 1 << 29,
|
||||
} MetaDebugTopic;
|
||||
|
||||
META_EXPORT
|
||||
|
|
|
@ -51,11 +51,14 @@ void meta_fatal (const char *format,
|
|||
* MetaDebugPaintFlag:
|
||||
* @META_DEBUG_PAINT_NONE: default
|
||||
* @META_DEBUG_PAINT_OPAQUE_REGION: paint opaque regions
|
||||
* @META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY: make cursor updates await compositing
|
||||
* frames
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_DEBUG_PAINT_NONE = 0,
|
||||
META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0,
|
||||
META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY = 1 << 1,
|
||||
} MetaDebugPaintFlag;
|
||||
|
||||
META_EXPORT
|
||||
|
|
|
@ -517,6 +517,12 @@ meta_crtc_test_set_gamma_lut (MetaCrtc *crtc,
|
|||
sizeof (uint16_t) * lut->size);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
meta_crtc_test_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_crtc_test_finalize (GObject *object)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue