File indexing completed on 2024-11-10 04:56:32
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "virtual_backend.h" 0010 0011 #include "virtual_egl_backend.h" 0012 #include "virtual_output.h" 0013 #include "virtual_qpainter_backend.h" 0014 0015 #include <fcntl.h> 0016 #include <gbm.h> 0017 #include <xf86drm.h> 0018 0019 namespace KWin 0020 { 0021 0022 static FileDescriptor findRenderDevice() 0023 { 0024 const int deviceCount = drmGetDevices2(0, nullptr, 0); 0025 if (deviceCount <= 0) { 0026 return FileDescriptor{}; 0027 } 0028 0029 QList<drmDevice *> devices(deviceCount); 0030 if (drmGetDevices2(0, devices.data(), devices.size()) < 0) { 0031 return FileDescriptor{}; 0032 } 0033 auto deviceCleanup = qScopeGuard([&devices]() { 0034 drmFreeDevices(devices.data(), devices.size()); 0035 }); 0036 0037 for (drmDevice *device : std::as_const(devices)) { 0038 // If it's a vgem device, prefer the primary node because gbm will attempt to allocate 0039 // dumb buffers and they can be allocated only on the primary node. 0040 int nodeType = DRM_NODE_RENDER; 0041 if (device->bustype == DRM_BUS_PLATFORM) { 0042 if (strcmp(device->businfo.platform->fullname, "vgem") == 0) { 0043 nodeType = DRM_NODE_PRIMARY; 0044 } 0045 } 0046 0047 if (device->available_nodes & (1 << nodeType)) { 0048 FileDescriptor fd{open(device->nodes[nodeType], O_RDWR | O_CLOEXEC)}; 0049 if (fd.isValid()) { 0050 return fd; 0051 } 0052 } 0053 } 0054 0055 return FileDescriptor{}; 0056 } 0057 0058 VirtualBackend::VirtualBackend(QObject *parent) 0059 : OutputBackend(parent) 0060 { 0061 m_drmFileDescriptor = findRenderDevice(); 0062 if (m_drmFileDescriptor.isValid()) { 0063 m_gbmDevice = gbm_create_device(m_drmFileDescriptor.get()); 0064 } 0065 } 0066 0067 VirtualBackend::~VirtualBackend() 0068 { 0069 if (m_gbmDevice) { 0070 gbm_device_destroy(m_gbmDevice); 0071 } 0072 } 0073 0074 bool VirtualBackend::initialize() 0075 { 0076 return true; 0077 } 0078 0079 QList<CompositingType> VirtualBackend::supportedCompositors() const 0080 { 0081 QList<CompositingType> compositingTypes; 0082 if (m_gbmDevice) { 0083 compositingTypes.append(OpenGLCompositing); 0084 } 0085 compositingTypes.append(QPainterCompositing); 0086 return compositingTypes; 0087 } 0088 0089 gbm_device *VirtualBackend::gbmDevice() const 0090 { 0091 return m_gbmDevice; 0092 } 0093 0094 std::unique_ptr<QPainterBackend> VirtualBackend::createQPainterBackend() 0095 { 0096 return std::make_unique<VirtualQPainterBackend>(this); 0097 } 0098 0099 std::unique_ptr<OpenGLBackend> VirtualBackend::createOpenGLBackend() 0100 { 0101 return std::make_unique<VirtualEglBackend>(this); 0102 } 0103 0104 Outputs VirtualBackend::outputs() const 0105 { 0106 return m_outputs; 0107 } 0108 0109 VirtualOutput *VirtualBackend::createOutput(const OutputInfo &info) 0110 { 0111 VirtualOutput *output = new VirtualOutput(this, info.internal); 0112 output->init(info.geometry.topLeft(), info.geometry.size() * info.scale, info.scale); 0113 m_outputs.append(output); 0114 Q_EMIT outputAdded(output); 0115 output->updateEnabled(true); 0116 return output; 0117 } 0118 0119 Output *VirtualBackend::addOutput(const OutputInfo &info) 0120 { 0121 VirtualOutput *output = createOutput(info); 0122 Q_EMIT outputsQueried(); 0123 return output; 0124 } 0125 0126 void VirtualBackend::setVirtualOutputs(const QList<OutputInfo> &infos) 0127 { 0128 const QList<VirtualOutput *> removed = m_outputs; 0129 0130 for (const auto &info : infos) { 0131 createOutput(info); 0132 } 0133 0134 for (VirtualOutput *output : removed) { 0135 output->updateEnabled(false); 0136 m_outputs.removeOne(output); 0137 Q_EMIT outputRemoved(output); 0138 output->unref(); 0139 } 0140 0141 Q_EMIT outputsQueried(); 0142 } 0143 0144 void VirtualBackend::setEglDisplay(std::unique_ptr<EglDisplay> &&display) 0145 { 0146 m_display = std::move(display); 0147 } 0148 0149 EglDisplay *VirtualBackend::sceneEglDisplayObject() const 0150 { 0151 return m_display.get(); 0152 } 0153 0154 } // namespace KWin 0155 0156 #include "moc_virtual_backend.cpp"