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.
This commit is contained in:
Po Lu 2022-08-01 05:51:59 +00:00
parent bc03a5b2c4
commit 99754dad3c
4 changed files with 48 additions and 9 deletions

View file

@ -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

View file

@ -1512,6 +1512,8 @@ class EmacsView : public BView
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 @@ class EmacsView : public BView
cr_context (NULL),
#endif
wait_for_release_message (NULL),
grabbed_buttons (0)
grabbed_buttons (0),
use_frame_synchronization (false)
{
}
@ -1546,6 +1549,16 @@ class EmacsView : public BView
grab_view_locker.Unlock ();
}
void
SetFrameSynchronization (bool sync)
{
if (LockLooper ())
{
use_frame_synchronization = sync;
UnlockLooper ();
}
}
void
MessageReceived (BMessage *msg)
{
@ -1722,14 +1735,14 @@ class EmacsView : public BView
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 @@ class EmacsView : public BView
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);
}

View file

@ -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
}

View file

@ -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