1/****************************************************************************
2**
3** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
4** Copyright (C) 2016 The Qt Company Ltd.
5** Copyright (C) 2016 Pelagicore AG
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the plugins of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qeglfskmsgbmintegration.h"
43#include "qeglfskmsgbmdevice.h"
44#include "qeglfskmsgbmscreen.h"
45#include "qeglfskmsgbmcursor.h"
46#include "qeglfskmsgbmwindow.h"
47#include "private/qeglfscursor_p.h"
48
49#include <QtCore/QLoggingCategory>
50#include <QtGui/QScreen>
51#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
52
53#include <gbm.h>
54
55QT_BEGIN_NAMESPACE
56
57QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration()
58{
59 qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created");
60}
61
62#ifndef EGL_EXT_platform_base
63typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
64#endif
65
66#ifndef EGL_PLATFORM_GBM_KHR
67#define EGL_PLATFORM_GBM_KHR 0x31D7
68#endif
69
70EGLDisplay QEglFSKmsGbmIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
71{
72 qCDebug(qLcEglfsKmsDebug, "Querying EGLDisplay");
73 EGLDisplay display;
74
75 PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = nullptr;
76 const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
77 if (extensions && (strstr(haystack: extensions, needle: "EGL_KHR_platform_gbm") || strstr(haystack: extensions, needle: "EGL_MESA_platform_gbm"))) {
78 getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
79 eglGetProcAddress(procname: "eglGetPlatformDisplayEXT"));
80 }
81
82 if (getPlatformDisplay) {
83 display = getPlatformDisplay(EGL_PLATFORM_GBM_KHR, nativeDisplay, nullptr);
84 } else {
85 qCDebug(qLcEglfsKmsDebug, "No eglGetPlatformDisplay for GBM, falling back to eglGetDisplay");
86 display = eglGetDisplay(display_id: nativeDisplay);
87 }
88
89 return display;
90}
91
92EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
93{
94 Q_UNUSED(format);
95 Q_ASSERT(device());
96
97 gbm_surface *surface = gbm_surface_create(gbm: static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
98 width: 1, height: 1,
99 GBM_FORMAT_XRGB8888,
100 flags: GBM_BO_USE_RENDERING);
101
102 return reinterpret_cast<EGLNativeWindowType>(surface);
103}
104
105void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window)
106{
107 gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
108 gbm_surface_destroy(surface);
109}
110
111QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) const
112{
113#if QT_CONFIG(opengl)
114 if (!screenConfig()->hwCursor()) {
115 qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor");
116 return new QEglFSCursor(screen);
117 }
118#else
119 Q_UNUSED(screen);
120#endif
121 return nullptr;
122}
123
124void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
125{
126 QWindow *window = static_cast<QWindow *>(surface->surface());
127 QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(window->screen()->handle());
128 screen->flip();
129}
130
131QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
132{
133 QString path = screenConfig()->devicePath();
134 if (!path.isEmpty()) {
135 qCDebug(qLcEglfsKmsDebug) << "GBM: Using DRM device" << path << "specified in config file";
136 } else {
137 QDeviceDiscovery *d = QDeviceDiscovery::create(type: QDeviceDiscovery::Device_VideoMask);
138 const QStringList devices = d->scanConnectedDevices();
139 qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
140 d->deleteLater();
141
142 if (Q_UNLIKELY(devices.isEmpty()))
143 qFatal(msg: "Could not find DRM device!");
144
145 path = devices.first();
146 qCDebug(qLcEglfsKmsDebug) << "Using" << path;
147 }
148
149 return new QEglFSKmsGbmDevice(screenConfig(), path);
150}
151
152QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const
153{
154 return new QEglFSKmsGbmWindow(window, this);
155}
156
157QT_END_NAMESPACE
158

source code of qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp