| 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 | |
| 55 | QT_BEGIN_NAMESPACE |
| 56 | |
| 57 | QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration() |
| 58 | { |
| 59 | qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created" ); |
| 60 | } |
| 61 | |
| 62 | #ifndef EGL_EXT_platform_base |
| 63 | typedef 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 | |
| 70 | EGLDisplay 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 | |
| 92 | EGLNativeWindowType 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 | |
| 105 | void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window) |
| 106 | { |
| 107 | gbm_surface *surface = reinterpret_cast<gbm_surface *>(window); |
| 108 | gbm_surface_destroy(surface); |
| 109 | } |
| 110 | |
| 111 | QPlatformCursor *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 | |
| 124 | void 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 | |
| 131 | QKmsDevice *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 | |
| 152 | QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const |
| 153 | { |
| 154 | return new QEglFSKmsGbmWindow(window, this); |
| 155 | } |
| 156 | |
| 157 | QT_END_NAMESPACE |
| 158 | |