|
|
|
|
@ -74,8 +74,9 @@ typedef struct xcb_glx_buffer_swap_complete_event_t |
|
|
|
|
namespace KWin |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
SwapEventFilter::SwapEventFilter(xcb_drawable_t drawable, xcb_glx_drawable_t glxDrawable) |
|
|
|
|
SwapEventFilter::SwapEventFilter(GlxBackend *backend, xcb_drawable_t drawable, xcb_glx_drawable_t glxDrawable) |
|
|
|
|
: X11EventFilter(Xcb::Extensions::self()->glxEventBase() + XCB_GLX_BUFFER_SWAP_COMPLETE) |
|
|
|
|
, m_backend(backend) |
|
|
|
|
, m_drawable(drawable) |
|
|
|
|
, m_glxDrawable(glxDrawable) |
|
|
|
|
{ |
|
|
|
|
@ -92,9 +93,7 @@ bool SwapEventFilter::event(xcb_generic_event_t *event) |
|
|
|
|
// The clock for the UST timestamp is left unspecified in the spec, however, usually,
|
|
|
|
|
// it's CLOCK_MONOTONIC, so no special conversions are needed.
|
|
|
|
|
const std::chrono::microseconds timestamp((uint64_t(swapEvent->ust_hi) << 32) | swapEvent->ust_lo); |
|
|
|
|
|
|
|
|
|
const auto platform = static_cast<X11StandaloneBackend *>(kwinApp()->outputBackend()); |
|
|
|
|
RenderLoopPrivate::get(platform->renderLoop())->notifyFrameCompleted(timestamp, Compositor::self()->backend()->primaryLayer(nullptr)->queryRenderTime()); |
|
|
|
|
m_backend->vblank(timestamp); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
@ -303,7 +302,7 @@ void GlxBackend::init() |
|
|
|
|
if (supportsSwapEvent && !forceSoftwareVsync) { |
|
|
|
|
// Nice, the GLX_INTEL_swap_event extension is available. We are going to receive
|
|
|
|
|
// the presentation timestamp (UST) after glXSwapBuffers() via the X command stream.
|
|
|
|
|
m_swapEventFilter = std::make_unique<SwapEventFilter>(window, glxWindow); |
|
|
|
|
m_swapEventFilter = std::make_unique<SwapEventFilter>(this, window, glxWindow); |
|
|
|
|
glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); |
|
|
|
|
} else { |
|
|
|
|
// If the GLX_INTEL_swap_event extension is unavailble, we are going to wait for
|
|
|
|
|
|