From 224f31c0b5ad86b5ea56025ff08faf7e25e1a82d Mon Sep 17 00:00:00 2001 From: Dominik Holland Date: Thu, 24 Mar 2016 15:38:05 +0100 Subject: Multi-screen handling for the eglfs_kms_egldevice backend Separates the generic kms classes into a own kms static lib called QtEglFsKmsSupport. The eglfs_kms plugin was changed to use these base classes and got renamed accordingly to QEglFSKmsGbm*. The eglfs_kms_egldevice plugin got extended to also derive from the kms base classed and by this provides multi-screen support Change-Id: I6de6a754e94cb8d52cf8e658b03c6bd6637674a1 Reviewed-by: Laszlo Agocs --- .../eglfs_kms/qeglfskmsgbmscreen.cpp | 223 +++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp (limited to 'src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp new file mode 100644 index 0000000000..7a17b60a5e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfskmsgbmscreen.h" +#include "qeglfskmsgbmdevice.h" +#include "qeglfskmsgbmcursor.h" +#include "qeglfsintegration.h" + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) +{ + FrameBuffer *fb = static_cast(data); + + if (fb->fb) { + gbm_device *device = gbm_bo_get_device(bo); + drmModeRmFB(gbm_device_get_fd(device), fb->fb); + } + + delete fb; +} + +QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(gbm_bo *bo) +{ + { + FrameBuffer *fb = static_cast(gbm_bo_get_user_data(bo)); + if (fb) + return fb; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t stride = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + + QScopedPointer fb(new FrameBuffer); + + int ret = drmModeAddFB(device()->fd(), width, height, 24, 32, + stride, handle, &fb->fb); + + if (ret) { + qWarning("Failed to create KMS FB!"); + return Q_NULLPTR; + } + + gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); + return fb.take(); +} + +QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) + : QEglFSKmsScreen(integration, device, output, position) + , m_gbm_surface(Q_NULLPTR) + , m_gbm_bo_current(Q_NULLPTR) + , m_gbm_bo_next(Q_NULLPTR) + , m_cursor(Q_NULLPTR) +{ +} + +QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen() +{ +} + +QPlatformCursor *QEglFSKmsGbmScreen::cursor() const +{ + if (integration()->hwCursor()) { + if (!integration()->separateScreens()) + return static_cast(device())->globalCursor(); + + if (m_cursor.isNull()) { + QEglFSKmsGbmScreen *that = const_cast(this); + that->m_cursor.reset(new QEglFSKmsGbmCursor(that)); + } + + return m_cursor.data(); + } else { + return QEglFSScreen::cursor(); + } +} + +gbm_surface *QEglFSKmsGbmScreen::createSurface() +{ + if (!m_gbm_surface) { + qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name(); + m_gbm_surface = gbm_surface_create(static_cast(device())->gbmDevice(), + geometry().width(), + geometry().height(), + GBM_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + } + return m_gbm_surface; +} + +void QEglFSKmsGbmScreen::destroySurface() +{ + if (m_gbm_bo_current) { + gbm_bo_destroy(m_gbm_bo_current); + m_gbm_bo_current = Q_NULLPTR; + } + + if (m_gbm_bo_next) { + gbm_bo_destroy(m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } + + if (m_gbm_surface) { + gbm_surface_destroy(m_gbm_surface); + m_gbm_surface = Q_NULLPTR; + } +} + +void QEglFSKmsGbmScreen::waitForFlip() +{ + // Don't lock the mutex unless we actually need to + if (!m_gbm_bo_next) + return; + + QMutexLocker lock(&m_waitForFlipMutex); + while (m_gbm_bo_next) + static_cast(device())->handleDrmEvent(); +} + +void QEglFSKmsGbmScreen::flip() +{ + if (!m_gbm_surface) { + qWarning("Cannot sync before platform init!"); + return; + } + + m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface); + if (!m_gbm_bo_next) { + qWarning("Could not lock GBM surface front buffer!"); + return; + } + + FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); + + if (!output().mode_set) { + int ret = drmModeSetCrtc(device()->fd(), + output().crtc_id, + fb->fb, + 0, 0, + &output().connector_id, 1, + &output().modes[output().mode]); + + if (ret) { + qErrnoWarning("Could not set DRM mode!"); + } else { + output().mode_set = true; + setPowerState(PowerStateOn); + } + } + + int ret = drmModePageFlip(device()->fd(), + output().crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + this); + if (ret) { + qErrnoWarning("Could not queue DRM page flip!"); + gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } +} + +void QEglFSKmsGbmScreen::flipFinished() +{ + if (m_gbm_bo_current) + gbm_surface_release_buffer(m_gbm_surface, + m_gbm_bo_current); + + m_gbm_bo_current = m_gbm_bo_next; + m_gbm_bo_next = Q_NULLPTR; +} + +QT_END_NAMESPACE -- cgit v1.2.3