diff --git a/backends/hwcomposer/egl_hwcomposer_backend.cpp b/backends/hwcomposer/egl_hwcomposer_backend.cpp index 14b66b2bbd..8ea4314df1 100644 --- a/backends/hwcomposer/egl_hwcomposer_backend.cpp +++ b/backends/hwcomposer/egl_hwcomposer_backend.cpp @@ -35,6 +35,7 @@ EglHwcomposerBackend::EglHwcomposerBackend(HwcomposerBackend *backend) init(); // EGL is always direct rendering setIsDirectRendering(true); + setSyncsToVBlank(true); } EglHwcomposerBackend::~EglHwcomposerBackend() diff --git a/backends/hwcomposer/hwcomposer_backend.cpp b/backends/hwcomposer/hwcomposer_backend.cpp index 40a8f02671..87f6a2f5e0 100644 --- a/backends/hwcomposer/hwcomposer_backend.cpp +++ b/backends/hwcomposer/hwcomposer_backend.cpp @@ -110,6 +110,28 @@ void HwcomposerBackend::init() // unblank, setPowerMode? m_device = hwcDevice; + + // register callbacks + hwc_procs_t *procs = new hwc_procs_t; + procs->invalidate = [] (const struct hwc_procs* procs) { + Q_UNUSED(procs) + }; + procs->vsync = [] (const struct hwc_procs* procs, int disp, int64_t timestamp) { + Q_UNUSED(procs) + if (disp != 0) { + return; + } + QMetaObject::invokeMethod(dynamic_cast(waylandServer()->backend()), + "vsync", + Qt::QueuedConnection); + }; + procs->hotplug = [] (const struct hwc_procs* procs, int disp, int connected) { + Q_UNUSED(procs) + Q_UNUSED(disp) + Q_UNUSED(connected) + }; + m_device->registerProcs(m_device, procs); + toggleBlankOutput(); // get display configuration @@ -136,6 +158,7 @@ void HwcomposerBackend::toggleBlankOutput() } m_outputBlank = !m_outputBlank; m_device->blank(m_device, 0, m_outputBlank ? 1 : 0); + m_device->eventControl(m_device, 0, HWC_EVENT_VSYNC, m_outputBlank ? 0 : 1); // enable/disable compositor repainting when blanked if (Compositor *compositor = Compositor::self()) { if (m_outputBlank) { @@ -162,6 +185,27 @@ OpenGLBackend *HwcomposerBackend::createOpenGLBackend() return new EglHwcomposerBackend(this); } +void HwcomposerBackend::present() +{ + if (m_pageFlipPending) { + return; + } + m_pageFlipPending = true; + if (Compositor::self()) { + Compositor::self()->aboutToSwapBuffers(); + } +} + +void HwcomposerBackend::vsync() +{ + if (m_pageFlipPending) { + m_pageFlipPending = false; + if (Compositor::self()) { + Compositor::self()->bufferSwapComplete(); + } + } +} + static void initLayer(hwc_layer_1_t *layer, const hwc_rect_t &rect) { memset(layer, 0, sizeof(hwc_layer_1_t)); @@ -217,6 +261,7 @@ HwcomposerWindow::~HwcomposerWindow() void HwcomposerWindow::present(HWComposerNativeWindowBuffer *buffer) { + m_backend->present(); hwc_composer_device_1_t *device = m_backend->device(); auto fblayer = &m_list[0]->hwLayers[1]; @@ -235,6 +280,7 @@ void HwcomposerWindow::present(HWComposerNativeWindowBuffer *buffer) close(m_list[0]->retireFenceFd); m_list[0]->retireFenceFd = -1; } + m_list[0]->flags = 0; } } diff --git a/backends/hwcomposer/hwcomposer_backend.h b/backends/hwcomposer/hwcomposer_backend.h index 70f7ebb584..2e1633aef4 100644 --- a/backends/hwcomposer/hwcomposer_backend.h +++ b/backends/hwcomposer/hwcomposer_backend.h @@ -59,10 +59,14 @@ public: hwc_composer_device_1_t *device() const { return m_device; } + void present(); int refreshRate() const { return m_refreshRate; } +public Q_SLOTS: + void vsync(); + private Q_SLOTS: void toggleBlankOutput(); @@ -70,6 +74,7 @@ private: QSize m_displaySize; hwc_composer_device_1_t *m_device = nullptr; bool m_outputBlank = true; + bool m_pageFlipPending = false; int m_refreshRate = 60000; };