diff --git a/backends/hwcomposer/egl_hwcomposer_backend.cpp b/backends/hwcomposer/egl_hwcomposer_backend.cpp index f16ad42f52..14b66b2bbd 100644 --- a/backends/hwcomposer/egl_hwcomposer_backend.cpp +++ b/backends/hwcomposer/egl_hwcomposer_backend.cpp @@ -144,7 +144,6 @@ bool EglHwcomposerBackend::makeContextCurrent() void EglHwcomposerBackend::present() { eglSwapBuffers(eglDisplay(), surface()); - m_nativeSurface->present(); } void EglHwcomposerBackend::screenGeometryChanged(const QSize &size) diff --git a/backends/hwcomposer/hwcomposer_backend.cpp b/backends/hwcomposer/hwcomposer_backend.cpp index 3fa21fe67e..40a8f02671 100644 --- a/backends/hwcomposer/hwcomposer_backend.cpp +++ b/backends/hwcomposer/hwcomposer_backend.cpp @@ -177,18 +177,25 @@ static void initLayer(hwc_layer_1_t *layer, const hwc_rect_t &rect) layer->visibleRegionScreen.rects = &layer->displayFrame; layer->acquireFenceFd = -1; layer->releaseFenceFd = -1; + layer->planeAlpha = 0xFF; } HwcomposerWindow::HwcomposerWindow(HwcomposerBackend *backend) : HWComposerNativeWindow(backend->size().width(), backend->size().height(), HAL_PIXEL_FORMAT_RGB_888) , m_backend(backend) { + setBufferCount(2); + size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t); hwc_display_contents_1_t *list = (hwc_display_contents_1_t*)malloc(size); m_list = (hwc_display_contents_1_t**)malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *)); for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i) { - m_list[i] = list; + m_list[i] = nullptr; } + // Assign buffer only to the first item, otherwise you get tearing + // if passed the same to multiple places + // see https://github.com/mer-hybris/qt5-qpa-hwcomposer-plugin/commit/f1d802151e8a4f5d10d60eb8de8e07552b93a34a + m_list[0] = list; const hwc_rect_t rect = { 0, 0, @@ -208,41 +215,26 @@ HwcomposerWindow::~HwcomposerWindow() // TODO: cleanup } -static void syncWait(int fd) +void HwcomposerWindow::present(HWComposerNativeWindowBuffer *buffer) { - if (fd == -1) { - return; - } - sync_wait(fd, -1); - close(fd); -} - -void HwcomposerWindow::present() -{ - HWComposerNativeWindowBuffer *front; - lockFrontBuffer(&front); - - m_list[0]->hwLayers[1].handle = front->handle; - m_list[0]->hwLayers[0].handle = NULL; - m_list[0]->hwLayers[0].flags = HWC_SKIP_LAYER; - - int oldretire = m_list[0]->retireFenceFd; - int oldrelease = m_list[0]->hwLayers[1].releaseFenceFd; - int oldrelease2 = m_list[0]->hwLayers[0].releaseFenceFd; - hwc_composer_device_1_t *device = m_backend->device(); - if (device->prepare(device, 1, m_list) != 0) { - qCWarning(KWIN_HWCOMPOSER) << "Error preparing hwcomposer for frame"; - } - if (device->set(device, 1, m_list) != 0) { - qCWarning(KWIN_HWCOMPOSER) << "Error setting device for frame"; - } - unlockFrontBuffer(front); + auto fblayer = &m_list[0]->hwLayers[1]; + fblayer->handle = buffer->handle; + fblayer->acquireFenceFd = getFenceBufferFd(buffer); + fblayer->releaseFenceFd = -1; - syncWait(oldrelease); - syncWait(oldrelease2); - syncWait(oldretire); + int err = device->prepare(device, 1, m_list); + assert(err == 0); + + err = device->set(device, 1, m_list); + assert(err == 0); + setFenceBufferFd(buffer, fblayer->releaseFenceFd); + + if (m_list[0]->retireFenceFd != -1) { + close(m_list[0]->retireFenceFd); + m_list[0]->retireFenceFd = -1; + } } } diff --git a/backends/hwcomposer/hwcomposer_backend.h b/backends/hwcomposer/hwcomposer_backend.h index a3eae2de1f..70f7ebb584 100644 --- a/backends/hwcomposer/hwcomposer_backend.h +++ b/backends/hwcomposer/hwcomposer_backend.h @@ -30,6 +30,8 @@ typedef struct hwc_display_contents_1 hwc_display_contents_1_t; typedef struct hwc_layer_1 hwc_layer_1_t; typedef struct hwc_composer_device_1 hwc_composer_device_1_t; +class HWComposerNativeWindowBuffer; + namespace KWin { @@ -76,7 +78,7 @@ class HwcomposerWindow : public HWComposerNativeWindow public: virtual ~HwcomposerWindow(); - void present(); + void present(HWComposerNativeWindowBuffer *buffer); private: friend HwcomposerBackend;