From 99754dad3c612703e06439cdb324033a25e24464 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 1 Aug 2022 05:51:59 +0000 Subject: [PATCH] Implement primitive frame synchronization on Haiku Instead of relying on a compositor to do the work, we simply wait for VBLANK and hope that the update finishes soon enough. * doc/lispref/frames.texi (Management Parameters): Document that frame synchronization is now supported on Haiku. * src/haiku_support.cc (class EmacsView): New field `use_frame_synchronization'. (FlipBuffers): Wait for vertical blanking period. (be_set_use_frame_synchronization): New function. * src/haiku_support.h: Update prototypes. * src/haikufns.c (haiku_create_frame): Set `use-frame-synchronization'. (haiku_set_use_frame_synchronization) (haiku_frame_parm_handlers): New param handler. --- doc/lispref/frames.texi | 10 +++++----- src/haiku_support.cc | 33 ++++++++++++++++++++++++++++++--- src/haiku_support.h | 1 + src/haikufns.c | 13 ++++++++++++- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index e5dec4f8072..262b86672da 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -2188,11 +2188,11 @@ way that its contents are hidden, leaving only the title bar. @item use-frame-synchronization If non-@code{nil}, synchronize the frame redisplay with the refresh rate of the monitor to avoid graphics tearing. At present, this is -only implemented on the X window system inside no-toolkit and X -toolkit builds, does not work correctly with toolkit scroll bars, and -requires a compositing manager supporting the relevant display -synchronization protocols. The @code{synchronizeResize} X resource -must also be set to the string @code{"extended"}. +only implemented on Haiku and the X window system inside no-toolkit +and X toolkit builds, does not work correctly with toolkit scroll +bars, and requires a compositing manager supporting the relevant +display synchronization protocols. The @code{synchronizeResize} X +resource must also be set to the string @code{"extended"}. @vindex inhibit-double-buffering@r{, a frame parameter} @item inhibit-double-buffering diff --git a/src/haiku_support.cc b/src/haiku_support.cc index b7590f68a48..983928442a1 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1512,6 +1512,8 @@ public: BMessage *wait_for_release_message; int64 grabbed_buttons; + BScreen screen; + bool use_frame_synchronization; EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", B_FOLLOW_NONE, B_WILL_DRAW), @@ -1524,7 +1526,8 @@ public: cr_context (NULL), #endif wait_for_release_message (NULL), - grabbed_buttons (0) + grabbed_buttons (0), + use_frame_synchronization (false) { } @@ -1546,6 +1549,16 @@ public: grab_view_locker.Unlock (); } + void + SetFrameSynchronization (bool sync) + { + if (LockLooper ()) + { + use_frame_synchronization = sync; + UnlockLooper (); + } + } + void MessageReceived (BMessage *msg) { @@ -1722,14 +1735,14 @@ public: void FlipBuffers (void) { + EmacsWindow *w; if (!LockLooper ()) gui_abort ("Failed to lock looper during buffer flip"); if (!offscreen_draw_view) gui_abort ("Failed to lock offscreen view during buffer flip"); offscreen_draw_view->Sync (); - - EmacsWindow *w = (EmacsWindow *) Window (); + w = (EmacsWindow *) Window (); w->shown_flag = 0; if (copy_bitmap && @@ -1750,6 +1763,11 @@ public: if (copy_bitmap->InitCheck () != B_OK) gui_abort ("Failed to init copy bitmap during buffer flip"); + /* Wait for VBLANK. If responding to the invalidation or buffer + flipping takes longer than the blanking period, we lose. */ + if (use_frame_synchronization) + screen.WaitForRetrace (); + Invalidate (&invalid_region); invalid_region.MakeEmpty (); UnlockLooper (); @@ -5474,3 +5492,12 @@ be_clear_grab_view (void) grab_view_locker.Unlock (); } } + +void +be_set_use_frame_synchronization (void *view, bool sync) +{ + EmacsView *vw; + + vw = (EmacsView *) view; + vw->SetFrameSynchronization (sync); +} diff --git a/src/haiku_support.h b/src/haiku_support.h index 76fe071f2c9..ca1808556a4 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -728,6 +728,7 @@ extern void be_lock_window (void *); extern void be_unlock_window (void *); extern bool be_get_explicit_workarea (int *, int *, int *, int *); extern void be_clear_grab_view (void); +extern void be_set_use_frame_synchronization (void *, bool); #ifdef __cplusplus } diff --git a/src/haikufns.c b/src/haikufns.c index 055a33e2c1e..64aa2fde4a1 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -949,6 +949,10 @@ haiku_create_frame (Lisp_Object parms) || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) kset_default_minibuffer_frame (kb, frame); + /* Set whether or not frame synchronization is enabled. */ + gui_default_parameter (f, parms, Quse_frame_synchronization, Qt, + NULL, NULL, RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); @@ -2115,6 +2119,13 @@ haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) update_face_from_frame_parameter (f, Qmouse_color, arg); } +static void +haiku_set_use_frame_synchronization (struct frame *f, Lisp_Object arg, + Lisp_Object oldval) +{ + be_set_use_frame_synchronization (FRAME_HAIKU_VIEW (f), !NILP (arg)); +} + DEFUN ("haiku-set-mouse-absolute-pixel-position", @@ -3128,7 +3139,7 @@ frame_parm_handler haiku_frame_parm_handlers[] = haiku_set_override_redirect, gui_set_no_special_glyphs, gui_set_alpha_background, - NULL, + haiku_set_use_frame_synchronization, }; void -- 2.39.2