From d9239872c71d117f78ce6c109cd9ab42e2d80c6b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 3 Nov 2019 19:02:38 +0100 Subject: X11: Only merge expose events if they intersect Towards actual fine-grained exposure. This uses the previous behaviour if expose events intersect to reduce redundant drawing, but dispatches expose events immediately (after flushing and pending configure events) if they don't to support partial redraws. --- pugl/detail/x11.c | 58 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 13 deletions(-) (limited to 'pugl') diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index e576b49..871c16b 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -586,8 +586,17 @@ puglWaitForEvent(PuglView* view) return PUGL_SUCCESS; } +static bool +exposeEventsIntersect(const PuglEvent* a, const PuglEvent* b) +{ + return !(a->expose.x + a->expose.width < b->expose.x || + b->expose.x + b->expose.width < a->expose.x || + a->expose.y + a->expose.height < b->expose.y || + b->expose.y + b->expose.height < a->expose.y); +} + static void -merge_expose_events(PuglEvent* dst, const PuglEvent* src) +mergeExposeEvents(PuglEvent* dst, const PuglEvent* src) { if (!dst->type) { *dst = *src; @@ -615,6 +624,26 @@ sendRedisplayEvent(PuglView* view) XSendEvent(view->impl->display, view->impl->win, False, 0, (XEvent*)&ev); } +static void +flushPendingConfigure(PuglView* view) +{ + PuglEvent* const configure = &view->impl->pendingConfigure; + + if (configure->type) { + view->frame.x = configure->configure.x; + view->frame.y = configure->configure.y; + view->frame.width = configure->configure.width; + view->frame.height = configure->configure.height; + + view->backend->resize(view, + (int)view->frame.width, + (int)view->frame.height); + + view->eventFunc(view, configure); + configure->type = 0; + } +} + PUGL_API PuglStatus puglDispatchEvents(PuglWorld* world) { @@ -712,7 +741,20 @@ puglDispatchEvents(PuglWorld* world) if (event.type == PUGL_EXPOSE) { // Expand expose event to be dispatched after loop - merge_expose_events(&view->impl->pendingExpose, &event); + if (view->impl->pendingConfigure.type || + (view->impl->pendingExpose.type && + exposeEventsIntersect(&view->impl->pendingExpose, &event))) { + mergeExposeEvents(&view->impl->pendingExpose, &event); + } else { + if (view->impl->pendingExpose.type) { + puglEnterContext(view, true); + flushPendingConfigure(view); + puglDispatchEvent(view, &view->impl->pendingExpose); + puglLeaveContext(view, true); + } + + view->impl->pendingExpose = event; + } } else if (event.type == PUGL_CONFIGURE) { // Expand configure event to be dispatched after loop view->impl->pendingConfigure = event; @@ -732,17 +774,7 @@ puglDispatchEvents(PuglWorld* world) const bool mustExpose = expose->type && expose->expose.count == 0; puglEnterContext(view, mustExpose); - if (configure->type) { - view->frame.x = configure->configure.x; - view->frame.y = configure->configure.y; - view->frame.width = configure->configure.width; - view->frame.height = configure->configure.height; - - view->backend->resize(view, - (int)view->frame.width, - (int)view->frame.height); - view->eventFunc(view, &view->impl->pendingConfigure); - } + flushPendingConfigure(view); if (mustExpose) { view->eventFunc(view, &view->impl->pendingExpose); -- cgit v1.2.1