commit dca5c9d4765cf8283ef6b5936e6a9044233c759f
parent b1683bebbcd7feac04d3124982c4c34bb42a26c6
Author: falkTX <falktx@falktx.com>
Date: Sat, 3 Jul 2021 21:28:41 +0100
Alternative approach to initial window OpenGL context scope
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
7 files changed, 192 insertions(+), 133 deletions(-)
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
@@ -105,6 +105,43 @@ public:
#endif // DGL_FILE_BROWSER_DISABLED
/**
+ Window graphics context as a scoped struct.
+ This class gives graphics context drawing time to a window's widgets.
+ Typically used for allowing OpenGL drawing operations during a window + widget constructor.
+
+ Unless you are subclassing the Window or StandaloneWindow classes, you do not need to care.
+ In such cases you will need to use this struct as a way to get a valid OpenGL context.
+ For example in a standalone application:
+ ```
+ int main()
+ {
+ Application app;
+ Window win(app);
+ ScopedPointer<MyCustomTopLevelWidget> widget;
+ {
+ const ScopedGraphicsContext sgc(win);
+ widget = new MyCustomTopLevelWidget(win);
+ }
+ app.exec();
+ return 0;
+ }
+ ```
+
+ This struct is necessary because we cannot automatically make the window leave the OpenGL context in custom code.
+ We must always cleanly enter and leave the OpenGL context.
+ In order to avoid messing up the global host context, this class is used around widget creation.
+ */
+ class ScopedGraphicsContext
+ {
+ Window& window;
+ public:
+ explicit ScopedGraphicsContext(Window& window);
+ ~ScopedGraphicsContext();
+ DISTRHO_DECLARE_NON_COPYABLE(ScopedGraphicsContext)
+ DISTRHO_PREVENT_HEAP_ALLOCATION
+ };
+
+ /**
Constructor for a regular, standalone window.
*/
explicit Window(Application& app);
@@ -362,9 +399,6 @@ public:
DISTRHO_DEPRECATED_BY("runAsModal(bool)")
inline void exec(bool blockWait = false) { runAsModal(blockWait); }
- // TESTING, DO NOT USE
- void leaveContext();
-
protected:
/**
A function called when the window is attempted to be closed.
@@ -414,6 +448,7 @@ private:
struct PrivateData;
PrivateData* const pData;
friend class Application;
+ friend class PluginWindow;
friend class TopLevelWidget;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window);
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -21,6 +21,20 @@
START_NAMESPACE_DGL
// -----------------------------------------------------------------------
+// ScopedGraphicsContext
+
+Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win)
+ : window(win)
+{
+ puglBackendEnter(window.pData->view);
+}
+
+Window::ScopedGraphicsContext::~ScopedGraphicsContext()
+{
+ puglBackendLeave(window.pData->view);
+}
+
+// -----------------------------------------------------------------------
// Window
Window::Window(Application& app)
@@ -265,11 +279,6 @@ void Window::runAsModal(bool blockWait)
pData->runAsModal(blockWait);
}
-void Window::leaveContext()
-{
- pData->leaveContext();
-}
-
void Window::setGeometryConstraints(const uint minimumWidth,
const uint minimumHeight,
const bool keepAspectRatio,
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -237,9 +237,6 @@ void Window::PrivateData::initPost()
// create view now, as a few methods we allow devs to use require it
puglRealize(view);
- // FIXME this is bad, the enter/leave should be well scoped. try to find a better place for it..
- puglBackendEnter(view);
-
if (isEmbed)
{
appData->oneWindowShown();
@@ -631,14 +628,6 @@ void Window::PrivateData::runAsModal(const bool blockWait)
}
// -----------------------------------------------------------------------
-// TESTING
-
-void Window::PrivateData::leaveContext()
-{
- puglBackendLeave(view);
-}
-
-// -----------------------------------------------------------------------
// pugl events
void Window::PrivateData::onPuglConfigure(const double width, const double height)
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -161,9 +161,6 @@ struct Window::PrivateData : IdleCallback {
void stopModal();
void runAsModal(bool blockWait);
- // TESTING
- void leaveContext();
-
// pugl events
void onPuglConfigure(double width, double height);
void onPuglExpose();
diff --git a/distrho/DistrhoUI.hpp b/distrho/DistrhoUI.hpp
@@ -48,6 +48,10 @@ typedef DGL_NAMESPACE::NanoTopLevelWidget UIWidget;
typedef DGL_NAMESPACE::TopLevelWidget UIWidget;
#endif
+START_NAMESPACE_DGL
+class PluginWindow;
+END_NAMESPACE_DGL
+
START_NAMESPACE_DISTRHO
/* ------------------------------------------------------------------------------------------------------------
@@ -311,7 +315,7 @@ protected:
private:
struct PrivateData;
PrivateData* const uiData;
- friend class PluginWindow;
+ friend class DGL_NAMESPACE::PluginWindow;
friend class UIExporter;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI)
diff --git a/distrho/src/DistrhoUI.cpp b/distrho/src/DistrhoUI.cpp
@@ -39,7 +39,7 @@ UI::PrivateData* UI::PrivateData::s_nextPrivateData = nullptr;
PluginWindow& UI::PrivateData::createNextWindow(UI* const ui, const uint width, const uint height)
{
UI::PrivateData* const pData = s_nextPrivateData;
- pData->window = new PluginWindow(ui, pData, width, height);
+ pData->window = new PluginWindow(ui, pData->app, pData->winId, width, height, pData->scaleFactor);
return pData->window.getObject();
}
diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp
@@ -20,8 +20,9 @@
#include "../DistrhoUI.hpp"
#include "../../dgl/Application.hpp"
-#ifndef DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-# include "../../dgl/Window.hpp"
+#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+# include "../../dgl/src/WindowPrivateData.hpp"
+# include "../../dgl/src/pugl.hpp"
#endif
#if defined(DISTRHO_PLUGIN_TARGET_JACK) || defined(DISTRHO_PLUGIN_TARGET_DSSI)
@@ -35,20 +36,9 @@
# define DISTRHO_UI_USER_RESIZABLE 0
#endif
-START_NAMESPACE_DISTRHO
-
-using DGL_NAMESPACE::Application;
-using DGL_NAMESPACE::Window;
-
// -----------------------------------------------------------------------
-// UI callbacks
-typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started);
-typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value);
-typedef void (*setStateFunc) (void* ptr, const char* key, const char* value);
-typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo);
-typedef void (*setSizeFunc) (void* ptr, uint width, uint height);
-typedef bool (*fileRequestFunc) (void* ptr, const char* key);
+START_NAMESPACE_DGL
// -----------------------------------------------------------------------
// Plugin Application, will set class name based on plugin details
@@ -73,7 +63,136 @@ public:
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication)
};
-class PluginWindow;
+// -----------------------------------------------------------------------
+// Plugin Window, will pass some Window events to UI
+
+#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+// TODO external ui stuff
+class PluginWindow
+{
+ UI* const ui;
+
+public:
+ explicit PluginWindow(UI* const uiPtr,
+ PluginApplication& app,
+ const uintptr_t parentWindowHandle,
+ const uint width,
+ const uint height,
+ const double scaleFactor)
+ : Window(app, parentWindowHandle, width, height, scaleFactor, DISTRHO_UI_USER_RESIZABLE),
+ ui(uiPtr) {}
+
+ uint getWidth() const noexcept
+ {
+ return ui->getWidth();
+ }
+
+ uint getHeight() const noexcept
+ {
+ return ui->getHeight();
+ }
+
+ bool isVisible() const noexcept
+ {
+ return ui->isRunning();
+ }
+
+ uintptr_t getNativeWindowHandle() const noexcept
+ {
+ return 0;
+ }
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
+};
+#else
+class PluginWindow : public Window
+{
+ UI* const ui;
+
+public:
+ explicit PluginWindow(UI* const uiPtr,
+ PluginApplication& app,
+ const uintptr_t parentWindowHandle,
+ const uint width,
+ const uint height,
+ const double scaleFactor)
+ : Window(app, parentWindowHandle, width, height, scaleFactor, DISTRHO_UI_USER_RESIZABLE),
+ ui(uiPtr)
+ {
+ puglBackendEnter(pData->view);
+ }
+
+ void leaveContext()
+ {
+ puglBackendLeave(pData->view);
+ }
+
+protected:
+ void onFocus(const bool focus, const DGL_NAMESPACE::CrossingMode mode) override
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
+
+ ui->uiFocus(focus, mode);
+ }
+
+ void onReshape(const uint width, const uint height) override
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
+
+ ui->uiReshape(width, height);
+ }
+
+ void onScaleFactorChanged(const double scaleFactor) override
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
+
+ ui->uiScaleFactorChanged(scaleFactor);
+ }
+
+# ifndef DGL_FILE_BROWSER_DISABLED
+ void onFileSelected(const char* const filename) override
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
+
+# if DISTRHO_PLUGIN_WANT_STATEFILES
+ if (char* const key = ui->uiData->uiStateFileKeyRequest)
+ {
+ ui->uiData->uiStateFileKeyRequest = nullptr;
+ // notify DSP
+ ui->setState(key, filename);
+ // notify UI
+ ui->stateChanged(key, filename);
+ std::free(key);
+ return;
+ }
+# endif
+
+ ui->uiFileBrowserSelected(filename);
+ }
+# endif
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
+};
+#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
+
+END_NAMESPACE_DGL
+
+// -----------------------------------------------------------------------
+
+START_NAMESPACE_DISTRHO
+
+using DGL_NAMESPACE::PluginApplication;
+using DGL_NAMESPACE::PluginWindow;
+
+// -----------------------------------------------------------------------
+// UI callbacks
+
+typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started);
+typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value);
+typedef void (*setStateFunc) (void* ptr, const char* key, const char* value);
+typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo);
+typedef void (*setSizeFunc) (void* ptr, uint width, uint height);
+typedef bool (*fileRequestFunc) (void* ptr, const char* key);
// -----------------------------------------------------------------------
// UI private data
@@ -195,100 +314,6 @@ struct UI::PrivateData {
};
// -----------------------------------------------------------------------
-// Plugin Window, will pass some Window events to UI
-
-#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-// TODO external ui stuff
-class PluginWindow
-{
- UI* const ui;
-
-public:
- explicit PluginWindow(UI* const uiPtr, UI::PrivateData* const pData, const uint width, const uint height)
- : Window(pData->app, pData->winId, pData->scaleFactor, width, height, DISTRHO_UI_USER_RESIZABLE),
- ui(uiPtr) {}
-
- uint getWidth() const noexcept
- {
- return ui->getWidth();
- }
-
- uint getHeight() const noexcept
- {
- return ui->getHeight();
- }
-
- bool isVisible() const noexcept
- {
- return ui->isRunning();
- }
-
- uintptr_t getNativeWindowHandle() const noexcept
- {
- return 0;
- }
-
- DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
-};
-#else
-class PluginWindow : public Window
-{
- UI* const ui;
-
-public:
- explicit PluginWindow(UI* const uiPtr, UI::PrivateData* const pData, const uint width, const uint height)
- : Window(pData->app, pData->winId, width, height, pData->scaleFactor, DISTRHO_UI_USER_RESIZABLE),
- ui(uiPtr) {}
-
-protected:
- void onFocus(const bool focus, const DGL_NAMESPACE::CrossingMode mode) override
- {
- DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
-
- ui->uiFocus(focus, mode);
- }
-
- void onReshape(const uint width, const uint height) override
- {
- DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
-
- ui->uiReshape(width, height);
- }
-
- void onScaleFactorChanged(const double scaleFactor) override
- {
- DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
-
- ui->uiScaleFactorChanged(scaleFactor);
- }
-
-# ifndef DGL_FILE_BROWSER_DISABLED
- void onFileSelected(const char* const filename) override
- {
- DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
-
-# if DISTRHO_PLUGIN_WANT_STATEFILES
- if (char* const key = ui->uiData->uiStateFileKeyRequest)
- {
- ui->uiData->uiStateFileKeyRequest = nullptr;
- // notify DSP
- ui->setState(key, filename);
- // notify UI
- ui->stateChanged(key, filename);
- std::free(key);
- return;
- }
-# endif
-
- ui->uiFileBrowserSelected(filename);
- }
-# endif
-
- DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
-};
-#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
-
-// -----------------------------------------------------------------------
// UI private data fileRequestCallback, which requires PluginWindow definitions
inline bool UI::PrivateData::fileRequestCallback(const char* const key)