diff options
Diffstat (limited to 'src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice')
8 files changed, 418 insertions, 303 deletions
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro index 1932f861b9..e2263f6cbf 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro @@ -1,23 +1,33 @@ TARGET = qeglfs-kms-egldevice-integration -QT += core-private gui-private platformsupport-private eglfs_device_lib-private +QT += core-private gui-private platformsupport-private eglfs_device_lib-private eglfs_kms_support-private -INCLUDEPATH += $$PWD/../.. +INCLUDEPATH += $$PWD/../.. $$PWD/../eglfs_kms_support -DEFINES += MESA_EGL_NO_X11_HEADERS +# Avoid X11 header collision, use generic EGL native types +DEFINES += QT_EGL_NO_X11 + +CONFIG += link_pkgconfig +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += libdrm +} else { + LIBS += -ldrm +} CONFIG += egl QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \ - $$PWD/qeglfskmsegldeviceintegration.cpp + $$PWD/qeglfskmsegldeviceintegration.cpp \ + qeglfskmsegldevice.cpp \ + qeglfskmsegldevicescreen.cpp -HEADERS += $$PWD/qeglfskmsegldeviceintegration.h +HEADERS += $$PWD/qeglfskmsegldeviceintegration.h \ + qeglfskmsegldevice.h \ + qeglfskmsegldevicescreen.h OTHER_FILES += $$PWD/eglfs_kms_egldevice.json -LIBS += -ldrm - PLUGIN_TYPE = egldeviceintegrations PLUGIN_CLASS_NAME = QEglFSKmsEglDeviceIntegrationPlugin load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp new file mode 100644 index 0000000000..743f714cf0 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 "qeglfskmsegldevice.h" +#include "qeglfskmsegldevicescreen.h" +#include "qeglfskmsegldeviceintegration.h" + +#include <QtCore/private/qcore_unix_p.h> + +QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path) + : QEglFSKmsDevice(integration, path) +{ +} + +bool QEglFSKmsEglDevice::open() +{ + Q_ASSERT(fd() == -1); + + int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR); + if (Q_UNLIKELY(fd < 0)) + qFatal("Could not open DRM device"); + + setFd(fd); + + return true; +} + +void QEglFSKmsEglDevice::close() +{ + if (qt_safe_close(fd()) == -1) + qErrnoWarning("Could not close DRM device"); + + setFd(-1); +} + +EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const +{ + return static_cast<QEglFSKmsEglDeviceIntegration *>(m_integration)->eglDevice(); +} + +QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +{ + return new QEglFSKmsEglDeviceScreen(integration, device, output, position); +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h new file mode 100644 index 0000000000..b1c98f3fe6 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QEGLFSKMSEGLDEVICE_H +#define QEGLFSKMSEGLDEVICE_H + +#include <qeglfskmsdevice.h> + +class QEglFSKmsEglDevice: public QEglFSKmsDevice +{ +public: + QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path); + + virtual bool open() Q_DECL_OVERRIDE; + virtual void close() Q_DECL_OVERRIDE; + + virtual EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE; + + virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) Q_DECL_OVERRIDE; +}; + +#endif // QEGLFSKMSEGLDEVICE_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index f67362ea61..838569d5c6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -1,99 +1,69 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** 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:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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 "qeglfskmsegldeviceintegration.h" +#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include "qeglfswindow.h" +#include "qeglfskmsegldevice.h" +#include "qeglfskmsscreen.h" #include <QLoggingCategory> #include <private/qmath_p.h> QT_BEGIN_NAMESPACE -// Use a name different from qLcEglfsEglKmsDebug to avoid duplicate symbols in -// static builds. Starting from Qt 5.7 this will be solved by the common kms -// support library, but in the meantime just work it around. -Q_LOGGING_CATEGORY(qLcEglfsEglDevDebug, "qt.qpa.eglfs.kms") - QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration() - : m_dri_fd(-1) + : QEglFSKmsIntegration() , m_egl_device(EGL_NO_DEVICE_EXT) - , m_egl_display(EGL_NO_DISPLAY) - , m_drm_connector(Q_NULLPTR) - , m_drm_encoder(Q_NULLPTR) - , m_drm_crtc(0) , m_funcs(Q_NULLPTR) { - qCDebug(qLcEglfsEglDevDebug, "New DRM/KMS on EGLDevice integration created"); + qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created"); } -void QEglFSKmsEglDeviceIntegration::platformInit() -{ - if (!query_egl_device()) - qFatal("Could not set up EGL device!"); - - const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT); - if (!deviceName) - qFatal("Failed to query device name from EGLDevice"); - - qCDebug(qLcEglfsEglDevDebug, "Opening %s", deviceName); - - m_dri_fd = drmOpen(deviceName, Q_NULLPTR); - if (m_dri_fd < 0) - qFatal("Could not open DRM device"); - - if (!setup_kms()) - qFatal("Could not set up KMS on device %s!", m_device.constData()); - - qCDebug(qLcEglfsEglDevDebug, "DRM/KMS initialized"); -} - -void QEglFSKmsEglDeviceIntegration::platformDestroy() -{ - if (qt_safe_close(m_dri_fd) == -1) - qErrnoWarning("Could not close DRM device"); - - m_dri_fd = -1; - - delete m_funcs; - m_funcs = Q_NULLPTR; -} - -EGLNativeDisplayType QEglFSKmsEglDeviceIntegration::platformDisplay() const +EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const { - return static_cast<EGLNativeDisplayType>(m_egl_device); + return EGL_STREAM_BIT_KHR; } EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) { - qCDebug(qLcEglfsEglDevDebug, "Creating display"); + qCDebug(qLcEglfsKmsDebug, "Creating display"); EGLDisplay display; @@ -104,59 +74,30 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat display = eglGetDisplay(nativeDisplay); } - if (display == EGL_NO_DISPLAY) + if (Q_UNLIKELY(display == EGL_NO_DISPLAY)) qFatal("Could not get EGL display"); EGLint major, minor; - if (!eglInitialize(display, &major, &minor)) + if (Q_UNLIKELY(!eglInitialize(display, &major, &minor))) qFatal("Could not initialize egl display"); - if (!eglBindAPI(EGL_OPENGL_ES_API)) + if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API))) qFatal("Failed to bind EGL_OPENGL_ES_API\n"); return display; } -QSizeF QEglFSKmsEglDeviceIntegration::physicalScreenSize() const -{ - const int defaultPhysicalDpi = 100; - static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH"); - static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT"); - QSizeF size(width, height); - if (size.isEmpty()) { - size = QSizeF(m_drm_connector->mmWidth, m_drm_connector->mmHeight); - if (size.isEmpty()) { - const float pixelsPerMm = Q_MM_PER_INCH / defaultPhysicalDpi; - size = QSizeF(screenSize().width() * pixelsPerMm, screenSize().height() * pixelsPerMm); - } - } - return size; -} - -QSize QEglFSKmsEglDeviceIntegration::screenSize() const -{ - return QSize(m_drm_mode.hdisplay, m_drm_mode.vdisplay); -} - -int QEglFSKmsEglDeviceIntegration::screenDepth() const -{ - return 32; -} - -QSurfaceFormat QEglFSKmsEglDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const { - QSurfaceFormat format(inputFormat); - format.setRenderableType(QSurfaceFormat::OpenGLES); - format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - return format; + // Returning false disables the usage of EGL_KHR_surfaceless_context even when the + // extension is available. This is just what we need since, at least with NVIDIA + // 352.00 making a null surface current with a context breaks. + return false; } -EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const +bool QEglFSKmsEglDeviceIntegration::supportsPBuffers() const { - return EGL_STREAM_BIT_KHR; + return true; } class QEglJetsonTK1Window : public QEglFSWindow @@ -184,7 +125,7 @@ void QEglJetsonTK1Window::invalidateSurface() void QEglJetsonTK1Window::resetSurface() { - qCDebug(qLcEglfsEglDevDebug, "Creating stream"); + qCDebug(qLcEglfsKmsDebug, "Creating stream"); EGLDisplay display = screen()->display(); EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT; @@ -196,14 +137,14 @@ void QEglJetsonTK1Window::resetSurface() return; } - qCDebug(qLcEglfsEglDevDebug, "Created stream %p on display %p", m_egl_stream, display); + qCDebug(qLcEglfsKmsDebug, "Created stream %p on display %p", m_egl_stream, display); if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) { qWarning("No output layers found"); return; } - qCDebug(qLcEglfsEglDevDebug, "Output has %d layers", count); + qCDebug(qLcEglfsKmsDebug, "Output has %d layers", count); QVector<EGLOutputLayerEXT> layers; layers.resize(count); @@ -213,17 +154,21 @@ void QEglJetsonTK1Window::resetSurface() return; } + QEglFSKmsScreen *cur_screen = static_cast<QEglFSKmsScreen*>(screen()); + Q_ASSERT(cur_screen); + qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", cur_screen->output().crtc_id); + for (int i = 0; i < actualCount; ++i) { EGLAttrib id; if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) { - qCDebug(qLcEglfsEglDevDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id); - if (id == EGLAttrib(m_integration->m_drm_crtc)) + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id); + if (id == EGLAttrib(cur_screen->output().crtc_id)) layer = layers[i]; } else if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) { // Not used yet, just for debugging. - qCDebug(qLcEglfsEglDevDebug, " [%d] layer %p - plane %d", i, layers[i], (int) id); + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - plane %d", i, layers[i], (int) id); } else { - qCDebug(qLcEglfsEglDevDebug, " [%d] layer %p - unknown", i, layers[i]); + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - unknown", i, layers[i]); } } @@ -239,18 +184,18 @@ void QEglJetsonTK1Window::resetSurface() return; } - qCDebug(qLcEglfsEglDevDebug, "Using layer %p", layer); + qCDebug(qLcEglfsKmsDebug, "Using layer %p", layer); if (!m_integration->m_funcs->stream_consumer_output(display, m_egl_stream, layer)) qWarning("resetSurface: Unable to connect stream"); m_config = QEglFSIntegration::chooseConfig(display, m_integration->surfaceFormatFor(window()->requestedFormat())); m_format = q_glFormatFromConfig(display, m_config); - qCDebug(qLcEglfsEglDevDebug) << "Stream producer format is" << m_format; + qCDebug(qLcEglfsKmsDebug) << "Stream producer format is" << m_format; - const int w = m_integration->screenSize().width(); - const int h = m_integration->screenSize().height(); - qCDebug(qLcEglfsEglDevDebug, "Creating stream producer surface of size %dx%d", w, h); + const int w = cur_screen->geometry().width(); + const int h = cur_screen->geometry().height(); + qCDebug(qLcEglfsKmsDebug, "Creating stream producer surface of size %dx%d", w, h); const EGLint stream_producer_attribs[] = { EGL_WIDTH, w, @@ -262,7 +207,7 @@ void QEglJetsonTK1Window::resetSurface() if (m_surface == EGL_NO_SURFACE) return; - qCDebug(qLcEglfsEglDevDebug, "Created stream producer surface %p", m_surface); + qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface); } QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const @@ -270,144 +215,36 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const QEglJetsonTK1Window *eglWindow = new QEglJetsonTK1Window(window, this); m_funcs->initialize(eglWindow->screen()->display()); - if (!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream - && m_funcs->has_egl_stream_producer_eglsurface && m_funcs->has_egl_stream_consumer_egloutput)) + if (Q_UNLIKELY(!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream && + m_funcs->has_egl_stream_producer_eglsurface && m_funcs->has_egl_stream_consumer_egloutput))) qFatal("Required extensions missing!"); return eglWindow; } -bool QEglFSKmsEglDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case QPlatformIntegration::ThreadedPixmaps: - case QPlatformIntegration::OpenGL: - case QPlatformIntegration::ThreadedOpenGL: - case QPlatformIntegration::BufferQueueingOpenGL: - return true; - default: - return false; - } -} - -void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const +bool QEglFSKmsEglDeviceIntegration::separateScreens() const { - static bool mode_set = false; - - if (!mode_set) { - mode_set = true; - - drmModeCrtcPtr currentMode = drmModeGetCrtc(m_dri_fd, m_drm_crtc); - const bool alreadySet = currentMode - && currentMode->width == m_drm_mode.hdisplay - && currentMode->height == m_drm_mode.vdisplay; - if (currentMode) - drmModeFreeCrtc(currentMode); - if (alreadySet) { - // Maybe detecting the DPMS mode could help here, but there are no properties - // exposed on the connector apparently. So rely on an env var for now. - static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); - if (!alwaysDoSet) { - qCDebug(qLcEglfsEglDevDebug, "Mode already set"); - return; - } - } - - qCDebug(qLcEglfsEglDevDebug, "Setting mode"); - int ret = drmModeSetCrtc(m_dri_fd, m_drm_crtc, - -1, 0, 0, - &m_drm_connector->connector_id, 1, - const_cast<const drmModeModeInfoPtr>(&m_drm_mode)); - if (ret) - qFatal("drmModeSetCrtc failed"); - } -} - -qreal QEglFSKmsEglDeviceIntegration::refreshRate() const -{ - quint32 refresh = m_drm_mode.vrefresh; - return refresh > 0 ? refresh : 60; -} - -bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const -{ - // Returning false disables the usage of EGL_KHR_surfaceless_context even when the - // extension is available. This is just what we need since, at least with NVIDIA - // 352.00 making a null surface current with a context breaks. - return false; + return true; } -bool QEglFSKmsEglDeviceIntegration::setup_kms() +QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devicePath) { - drmModeRes *resources; - drmModeConnector *connector = Q_NULLPTR; - drmModeEncoder *encoder = Q_NULLPTR; - quint32 crtc = 0; - int i; - - resources = drmModeGetResources(m_dri_fd); - if (!resources) { - qWarning("drmModeGetResources failed"); - return false; - } - - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); - if (!connector) - continue; + Q_UNUSED(devicePath) - if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) - break; - - drmModeFreeConnector(connector); - } - - if (i == resources->count_connectors) { - qWarning("No currently active connector found."); - return false; - } - - qCDebug(qLcEglfsEglDevDebug, "Using connector with type %d", connector->connector_type); - - for (i = 0; i < resources->count_encoders; i++) { - encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]); - if (!encoder) - continue; - - if (encoder->encoder_id == connector->encoder_id) - break; - - drmModeFreeEncoder(encoder); - } - - for (int j = 0; j < resources->count_crtcs; j++) { - if ((encoder->possible_crtcs & (1 << j))) { - crtc = resources->crtcs[j]; - break; - } - } - - if (crtc == 0) - qFatal("No suitable CRTC available"); - - m_drm_connector = connector; - m_drm_encoder = encoder; - m_drm_mode = connector->modes[0]; - m_drm_crtc = crtc; - - qCDebug(qLcEglfsEglDevDebug).noquote() << "Using crtc" << m_drm_crtc - << "with mode" << m_drm_mode.hdisplay << "x" << m_drm_mode.vdisplay - << "@" << m_drm_mode.vrefresh; + if (Q_UNLIKELY(!query_egl_device())) + qFatal("Could not set up EGL device!"); - drmModeFreeResources(resources); + const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT); + if (Q_UNLIKELY(!deviceName)) + qFatal("Failed to query device name from EGLDevice"); - return true; + return new QEglFSKmsEglDevice(this, deviceName); } bool QEglFSKmsEglDeviceIntegration::query_egl_device() { m_funcs = new QEGLStreamConvenience; - if (!m_funcs->has_egl_device_base) + if (Q_UNLIKELY(!m_funcs->has_egl_device_base)) qFatal("EGL_EXT_device_base missing"); EGLint num_devices = 0; @@ -416,7 +253,7 @@ bool QEglFSKmsEglDeviceIntegration::query_egl_device() return false; } - qCDebug(qLcEglfsEglDevDebug, "Found %d EGL devices", num_devices); + qCDebug(qLcEglfsKmsDebug, "Found %d EGL devices", num_devices); if (num_devices < 1 || m_egl_device == EGL_NO_DEVICE_EXT) { qWarning("eglQueryDevicesEXT could not find any EGL devices"); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h index a89a65ca55..f04c42267a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -1,31 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** 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:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -34,17 +41,7 @@ #ifndef QEGLFSKMSEGLDEVICEINTEGRATION_H #define QEGLFSKMSEGLDEVICEINTEGRATION_H -#include "qeglfsdeviceintegration.h" -#include "qeglfswindow.h" -#include "qeglfsintegration.h" - -#include <QtPlatformSupport/private/qdevicediscovery_p.h> -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtCore/private/qcore_unix_p.h> -#include <QtCore/QScopedPointer> -#include <QtGui/qpa/qplatformwindow.h> -#include <QtGui/qguiapplication.h> -#include <QDebug> +#include <qeglfskmsintegration.h> #include <xf86drm.h> #include <xf86drmMode.h> @@ -53,41 +50,31 @@ QT_BEGIN_NAMESPACE -class QEglFSKmsEglDeviceIntegration : public QEGLDeviceIntegration +class QEglFSKmsEglDeviceIntegration : public QEglFSKmsIntegration { public: QEglFSKmsEglDeviceIntegration(); - void platformInit() Q_DECL_OVERRIDE; - void platformDestroy() Q_DECL_OVERRIDE; - EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; - EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE; - QSizeF physicalScreenSize() const Q_DECL_OVERRIDE; - QSize screenSize() const Q_DECL_OVERRIDE; - int screenDepth() const Q_DECL_OVERRIDE; - qreal refreshRate() const Q_DECL_OVERRIDE; - QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; EGLint surfaceType() const Q_DECL_OVERRIDE; - QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; + EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE; bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE; + bool supportsPBuffers() const Q_DECL_OVERRIDE; + QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + virtual bool separateScreens() const Q_DECL_OVERRIDE; + + EGLDeviceEXT eglDevice() const { return m_egl_device; } + +protected: + QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE; + +private: bool setup_kms(); bool query_egl_device(); - // device bits - QByteArray m_device; - int m_dri_fd; EGLDeviceEXT m_egl_device; - EGLDisplay m_egl_display; - - // KMS bits - drmModeConnector *m_drm_connector; - drmModeEncoder *m_drm_encoder; - drmModeModeInfo m_drm_mode; - quint32 m_drm_crtc; + friend class QEglJetsonTK1Window; // EGLStream infrastructure QEGLStreamConvenience *m_funcs; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp index f987ae38a6..63571f796f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the qmake spec of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp new file mode 100644 index 0000000000..da1b577801 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 "qeglfskmsegldevicescreen.h" +#include "qeglfskmsegldevice.h" + +QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) + : QEglFSKmsScreen(integration, device, output, position) +{ +} + +void QEglFSKmsEglDeviceScreen::waitForFlip() +{ + if (!output().mode_set) { + output().mode_set = true; + + drmModeCrtcPtr currentMode = drmModeGetCrtc(device()->fd(), output().crtc_id); + const bool alreadySet = currentMode + && currentMode->width == output().modes[output().mode].hdisplay + && currentMode->height == output().modes[output().mode].vdisplay; + if (currentMode) + drmModeFreeCrtc(currentMode); + if (alreadySet) { + // Maybe detecting the DPMS mode could help here, but there are no properties + // exposed on the connector apparently. So rely on an env var for now. + static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); + if (!alwaysDoSet) { + qCDebug(qLcEglfsKmsDebug, "Mode already set"); + return; + } + } + + qCDebug(qLcEglfsKmsDebug, "Setting mode"); + int ret = drmModeSetCrtc(device()->fd(), output().crtc_id, + -1, 0, 0, + &output().connector_id, 1, + &output().modes[output().mode]); + if (ret) + qFatal("drmModeSetCrtc failed"); + } + +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h new file mode 100644 index 0000000000..0cd46e9f9d --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QEGLFSKMSEGLDEVICESCREEN_H +#define QEGLFSKMSEGLDEVICESCREEN_H + +#include <qeglfskmsscreen.h> + +class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen +{ +public: + QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + + void waitForFlip() Q_DECL_OVERRIDE; +}; + +#endif // QEGLFSKMSEGLDEVICESCREEN_H |