Skip to content

Commit

Permalink
Say hello to AuroraCore
Browse files Browse the repository at this point in the history
AuroraCore 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 Aug 23, 2023
1 parent 4edaf1b commit d413d67
Show file tree
Hide file tree
Showing 24 changed files with 1,656 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/core)
add_subdirectory(src/compositor)
if(FEATURE_aurora_brcm)
add_subdirectory(src/plugins/hardwareintegration/compositor/brcm-egl)
Expand Down
36 changes: 36 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <[email protected]>
# SPDX-License-Identifier: BSD-3-Clause

include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(
AuroraCore_SOURCES
HEADER "auroracoreloggingcategories.h"
IDENTIFIER "Aurora::Core::gLcAuroraCore"
CATEGORY_NAME "aurora.core"
DEFAULT_SEVERITY "Info"
DESCRIPTION "Aurora platform abstraction"
)

liri_add_module(AuroraCore
DESCRIPTION
"Aurora core library"
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
session.cpp session.h
session_noop.cpp session_noop_p.h
window.cpp window.h
${AuroraCore_SOURCES}
DEFINES
QT_NO_CAST_FROM_ASCII
PUBLIC_LIBRARIES
Qt5::Core
Qt5::Gui
)

liri_finalize_module(AuroraCore)
123 changes: 123 additions & 0 deletions src/core/deviceintegration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <[email protected]>
// 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 Core {

/*
* 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::Core::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 Core

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

#pragma once

#include <QSurfaceFormat>

#include <LiriAuroraCore/Output>

#include <EGL/egl.h>

#include <memory>

class QPlatformSurface;

namespace Aurora {

namespace Core {

class DeviceIntegrationPrivate;
class InputManager;
class Window;

class LIRIAURORACORE_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(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 Core

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

#pragma once

#include <LiriAuroraCore/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 Core {

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

bool ready = false;

protected:
DeviceIntegration *q_ptr = nullptr;
};

} // namespace Core

} // namespace Aurora
86 changes: 86 additions & 0 deletions src/core/deviceintegrationplugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <[email protected]>
// 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 Core {

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(gLcAuroraCore) << "EGL 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 Core

} // namespace Aurora
Loading

0 comments on commit d413d67

Please sign in to comment.