aboutsummaryrefslogtreecommitdiff
path: root/src/qt_common/render/context.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt_common/render/context.h')
-rw-r--r--src/qt_common/render/context.h107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/qt_common/render/context.h b/src/qt_common/render/context.h
new file mode 100644
index 0000000000..a0ecade9c8
--- /dev/null
+++ b/src/qt_common/render/context.h
@@ -0,0 +1,107 @@
+// 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 {};