mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-20 22:47:04 +02:00
Ported from QML branch. Main "big" change is that EmuThread is now a shared state in QtCommon, not individually managed/passed around by GRenderWindow and MainWindow. Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3916 Reviewed-by: Lizzie <lizzie@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
107 lines
3.7 KiB
C++
107 lines
3.7 KiB
C++
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <QSurface>
|
|
#include "common/logging.h"
|
|
#include "common/settings.h"
|
|
#include "core/frontend/graphics_context.h"
|
|
|
|
#ifdef HAS_OPENGL
|
|
#include <QOffscreenSurface>
|
|
#include <QOpenGLContext>
|
|
#endif
|
|
|
|
#ifdef HAS_OPENGL
|
|
class OpenGLSharedContext : public Core::Frontend::GraphicsContext {
|
|
public:
|
|
/// Create the original context that should be shared from
|
|
explicit OpenGLSharedContext(QSurface* surface_) : surface{surface_} {
|
|
QSurfaceFormat format;
|
|
format.setVersion(4, 6);
|
|
format.setProfile(QSurfaceFormat::CompatibilityProfile);
|
|
format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
|
|
if (Settings::values.renderer_debug) {
|
|
format.setOption(QSurfaceFormat::FormatOption::DebugContext);
|
|
}
|
|
// TODO: expose a setting for buffer value (ie default/single/double/triple)
|
|
format.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior);
|
|
format.setSwapInterval(0);
|
|
|
|
context = std::make_unique<QOpenGLContext>();
|
|
context->setFormat(format);
|
|
if (!context->create()) {
|
|
LOG_ERROR(Frontend, "Unable to create main openGL context");
|
|
}
|
|
}
|
|
|
|
/// Create the shared contexts for rendering and presentation
|
|
explicit OpenGLSharedContext(QOpenGLContext* share_context, QSurface* main_surface = nullptr) {
|
|
|
|
// disable vsync for any shared contexts
|
|
auto format = share_context->format();
|
|
const int swap_interval =
|
|
Settings::values.vsync_mode.GetValue() == Settings::VSyncMode::Immediate ? 0 : 1;
|
|
|
|
format.setSwapInterval(main_surface ? swap_interval : 0);
|
|
|
|
context = std::make_unique<QOpenGLContext>();
|
|
context->setShareContext(share_context);
|
|
context->setFormat(format);
|
|
if (!context->create()) {
|
|
LOG_ERROR(Frontend, "Unable to create shared openGL context");
|
|
}
|
|
|
|
if (!main_surface) {
|
|
offscreen_surface = std::make_unique<QOffscreenSurface>(nullptr);
|
|
offscreen_surface->setFormat(format);
|
|
offscreen_surface->create();
|
|
surface = offscreen_surface.get();
|
|
} else {
|
|
surface = main_surface;
|
|
}
|
|
}
|
|
|
|
~OpenGLSharedContext() {
|
|
DoneCurrent();
|
|
}
|
|
|
|
void SwapBuffers() override {
|
|
context->swapBuffers(surface);
|
|
}
|
|
|
|
void MakeCurrent() override {
|
|
// We can't track the current state of the underlying context in this wrapper class because
|
|
// Qt may make the underlying context not current for one reason or another. In particular,
|
|
// the WebBrowser uses GL, so it seems to conflict if we aren't careful.
|
|
// Instead of always just making the context current (which does not have any caching to
|
|
// check if the underlying context is already current) we can check for the current context
|
|
// in the thread local data by calling `currentContext()` and checking if its ours.
|
|
if (QOpenGLContext::currentContext() != context.get()) {
|
|
context->makeCurrent(surface);
|
|
}
|
|
}
|
|
|
|
void DoneCurrent() override {
|
|
context->doneCurrent();
|
|
}
|
|
|
|
QOpenGLContext* GetShareContext() {
|
|
return context.get();
|
|
}
|
|
|
|
const QOpenGLContext* GetShareContext() const {
|
|
return context.get();
|
|
}
|
|
|
|
private:
|
|
// Avoid using Qt parent system here since we might move the QObjects to new threads
|
|
// As a note, this means we should avoid using slots/signals with the objects too
|
|
std::unique_ptr<QOpenGLContext> context;
|
|
std::unique_ptr<QOffscreenSurface> offscreen_surface{};
|
|
QSurface* surface;
|
|
};
|
|
#endif
|
|
|
|
class DummyContext : public Core::Frontend::GraphicsContext {};
|