Skip to content

Commit

Permalink
Say hello to AuroraPlatform
Browse files Browse the repository at this point in the history
AuroraPlatform is a platform abstraction library that glues together
compositors with EGL device integration and input device managers.

Compositors will use the platform abstraction layer to access input
and output devices directly.

Closes: #41
  • Loading branch information
plfiorini committed Sep 2, 2023
1 parent 4edaf1b commit 92779ed
Show file tree
Hide file tree
Showing 29 changed files with 1,955 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ endif()
if(FEATURE_aurora_xkbcommon)
add_subdirectory(src/platformsupport/xkbcommon)
endif()
add_subdirectory(src/platform)
add_subdirectory(src/compositor)
if(FEATURE_aurora_brcm)
add_subdirectory(src/plugins/hardwareintegration/compositor/brcm-egl)
Expand Down
38 changes: 38 additions & 0 deletions src/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
# SPDX-License-Identifier: BSD-3-Clause

include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(
AuroraPlatform_SOURCES
HEADER "auroracoreloggingcategories.h"
IDENTIFIER "Aurora::Platform::gLcAuroraPlatform"
CATEGORY_NAME "aurora.platform"
DEFAULT_SEVERITY "Info"
DESCRIPTION "Aurora platform abstraction"
)

liri_add_module(AuroraPlatform
DESCRIPTION
"Platform abstraction library for Wayland compositors using Aurora"
SOURCES
deviceintegration.cpp deviceintegration.h
deviceintegrationplugin.cpp deviceintegrationplugin.h
eglconfigchooser.cpp eglconfigchooser_p.h
inputdevice.cpp inputdevice.h
inputmanager.cpp inputmanager.h
keyboarddevice.cpp keyboarddevice.h
output.cpp output.h output_p.h
pointerdevice.cpp pointerdevice.h
session.cpp session.h
session_noop.cpp session_noop_p.h
touchdevice.cpp touchdevice.h
window.cpp window.h window_p.h
${AuroraPlatform_SOURCES}
DEFINES
QT_NO_CAST_FROM_ASCII
PUBLIC_LIBRARIES
Qt::Core
Qt::Gui
)

liri_finalize_module(AuroraPlatform)
129 changes: 129 additions & 0 deletions src/platform/deviceintegration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "deviceintegration.h"
#include "deviceintegration_p.h"
#include "eglconfigchooser_p.h"
#include "inputmanager.h"

namespace Aurora {

namespace Platform {

/*
* DeviceIntegration
*/

DeviceIntegration::DeviceIntegration(QObject *parent)
: QObject(parent)
, d_ptr(new DeviceIntegrationPrivate(this))
{
}

DeviceIntegration::~DeviceIntegration()
{
}

bool DeviceIntegration::isReady() const
{
Q_D(const DeviceIntegration);
return d->ready;
}

bool DeviceIntegration::supportsPBuffers()
{
return true;
}

bool DeviceIntegration::supportsSurfacelessContexts()
{
return true;
}

EGLNativeDisplayType DeviceIntegration::platformDisplay() const
{
return EGL_DEFAULT_DISPLAY;
}

EGLDisplay DeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
{
return eglGetDisplay(nativeDisplay);
}

void DeviceIntegration::destroyDisplay(EGLDisplay eglDisplay)
{
if (eglDisplay != EGL_NO_DISPLAY)
eglTerminate(eglDisplay);
}

EGLNativeWindowType DeviceIntegration::createNativeWindow(Window *window, const QSize &size,
const QSurfaceFormat &format)
{
Q_UNUSED(window)
Q_UNUSED(size)
Q_UNUSED(format)
return 0;
}

void DeviceIntegration::destroyNativeWindow(EGLNativeWindowType nativeWindow)
{
Q_UNUSED(nativeWindow)
}

QSurfaceFormat DeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
{
return inputFormat;
}

EGLint DeviceIntegration::surfaceType() const
{
return EGL_WINDOW_BIT;
}

EGLConfig DeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
{
Q_D(DeviceIntegration);

QVector<EGLint> configAttribs = eglConfigAttributesFromSurfaceFormat(display, format);

configAttribs.append(EGL_SURFACE_TYPE);
configAttribs.append(surfaceType());

configAttribs.append(EGL_NONE);

// Get the number of matching configurations for the attributes
EGLConfig config = nullptr;
EGLint numConfigs = 0;
if (!eglChooseConfig(display, configAttribs.constData(), &config, 1, &numConfigs))
return nullptr;
return config;
}

InputManager *Aurora::Platform::DeviceIntegration::createInputManager()
{
return nullptr;
}

void DeviceIntegration::setReady(bool ready)
{
Q_D(DeviceIntegration);

if (d->ready == ready)
return;

d->ready = ready;
emit readyChanged(ready);
}

/*
* DeviceIntegrationPrivate
*/

DeviceIntegrationPrivate::DeviceIntegrationPrivate(DeviceIntegration *self)
: q_ptr(self)
{
}

} // namespace Platform

} // namespace Aurora
78 changes: 78 additions & 0 deletions src/platform/deviceintegration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <QSurfaceFormat>

#include <LiriAuroraPlatform/Output>

#include <EGL/egl.h>

#include <memory>

class QPlatformSurface;

namespace Aurora {

namespace Platform {

class DeviceIntegrationPrivate;
class InputManager;
class Window;

class LIRIAURORAPLATFORM_EXPORT DeviceIntegration : public QObject
{
Q_OBJECT
Q_PROPERTY(bool ready READ isReady NOTIFY readyChanged)
Q_DECLARE_PRIVATE(DeviceIntegration)
public:
~DeviceIntegration();

bool isReady() const;

virtual void initialize() = 0;
virtual void destroy() = 0;

virtual bool supportsPBuffers();
virtual bool supportsSurfacelessContexts();

virtual EGLNativeDisplayType platformDisplay() const;

virtual EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay);
virtual void destroyDisplay(EGLDisplay eglDisplay);

virtual EGLNativeWindowType createNativeWindow(Window *window, const QSize &size,
const QSurfaceFormat &format);
virtual void destroyNativeWindow(EGLNativeWindowType nativeWindow);

virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const;
virtual EGLint surfaceType() const;

virtual EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);

virtual Window *createWindow(Output *output, QWindow *window) = 0;

virtual void waitForVSync(Window *window) const = 0;
virtual void presentBuffer(Window *window) = 0;

virtual InputManager *createInputManager();

virtual Outputs outputs() const = 0;

signals:
void readyChanged(bool ready);
void outputAdded(Output *output);
void outputRemoved(Output *output);

protected:
QScopedPointer<DeviceIntegrationPrivate> const d_ptr;

explicit DeviceIntegration(QObject *parent = nullptr);

void setReady(bool ready);
};

} // namespace Platform

} // namespace Aurora
37 changes: 37 additions & 0 deletions src/platform/deviceintegration_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <LiriAuroraPlatform/DeviceIntegration>

//
// W A R N I N G
// -------------
//
// This file is not part of the Aurora API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

namespace Aurora {

namespace Platform {

class LIRIAURORAPLATFORM_EXPORT DeviceIntegrationPrivate
{
Q_DECLARE_PUBLIC(DeviceIntegration)
public:
DeviceIntegrationPrivate(DeviceIntegration *self);

bool ready = false;

protected:
DeviceIntegration *q_ptr = nullptr;
};

} // namespace Platform

} // namespace Aurora
89 changes: 89 additions & 0 deletions src/platform/deviceintegrationplugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-or-later

#include <QCoreApplication>
#include <QDir>
#include <QPluginLoader>
#include <QJsonDocument>

#include "auroracoreloggingcategories.h"
#include "deviceintegrationplugin.h"

namespace Aurora {

namespace Platform {

DeviceIntegrationPlugin::DeviceIntegrationPlugin(QObject *parent)
: QObject(parent)
{
}

QStringList DeviceIntegrationFactory::keys(const QString &pluginPath)
{
QStringList list;

if (!pluginPath.isEmpty())
QCoreApplication::addLibraryPath(pluginPath);

const auto paths = QCoreApplication::libraryPaths();
for (const auto &path : paths) {
const auto absolutePath =
QDir(path).absoluteFilePath(QStringLiteral("aurora/deviceintegration"));
QDir dir(absolutePath);

const auto fileNames = dir.entryList(QDir::Files);
for (const auto &fileName : fileNames) {
QPluginLoader loader(dir.absoluteFilePath(fileName));

if (loader.load()) {
const auto metaData =
loader.metaData().value(QLatin1String("MetaData")).toVariant().toMap();
list += metaData.value(QStringLiteral("Keys"), QStringList()).toStringList();
}

loader.unload();
}
}

qCDebug(gLcAuroraPlatform) << "Device integration plugin keys:" << list;
return list;
}

DeviceIntegration *DeviceIntegrationFactory::create(const QString &name, const QString &pluginPath)
{
if (!pluginPath.isEmpty())
QCoreApplication::addLibraryPath(pluginPath);

const auto paths = QCoreApplication::libraryPaths();
for (const auto &path : paths) {
const auto absolutePath =
QDir(path).absoluteFilePath(QStringLiteral("aurora/deviceintegration"));
QDir dir(absolutePath);

const auto fileNames = dir.entryList(QDir::Files);
for (const auto &fileName : fileNames) {
QPluginLoader loader(dir.absoluteFilePath(fileName));

if (loader.load()) {
const auto metaData =
loader.metaData().value(QLatin1String("MetaData")).toVariant().toMap();
const auto keys =
metaData.value(QStringLiteral("Keys"), QStringList()).toStringList();

if (keys.contains(name)) {
auto *plugin = dynamic_cast<DeviceIntegrationPlugin *>(loader.instance());
if (plugin)
return plugin->create();
}
}

loader.unload();
}
}

return nullptr;
}

} // namespace Platform

} // namespace Aurora
Loading

0 comments on commit 92779ed

Please sign in to comment.