Browse Source

Alternative approach to initial window OpenGL context scope

Signed-off-by: falkTX <falktx@falktx.com>
pull/297/head
falkTX 3 years ago
parent
commit
dca5c9d476
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
7 changed files with 192 additions and 133 deletions
  1. +38
    -3
      dgl/Window.hpp
  2. +14
    -5
      dgl/src/Window.cpp
  3. +0
    -11
      dgl/src/WindowPrivateData.cpp
  4. +0
    -3
      dgl/src/WindowPrivateData.hpp
  5. +5
    -1
      distrho/DistrhoUI.hpp
  6. +1
    -1
      distrho/src/DistrhoUI.cpp
  7. +134
    -109
      distrho/src/DistrhoUIPrivateData.hpp

+ 38
- 3
dgl/Window.hpp View File

@@ -104,6 +104,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.
*/
@@ -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);


+ 14
- 5
dgl/src/Window.cpp View File

@@ -20,6 +20,20 @@

START_NAMESPACE_DGL

// -----------------------------------------------------------------------
// ScopedGraphicsContext

Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win)
: window(win)
{
puglBackendEnter(window.pData->view);
}

Window::ScopedGraphicsContext::~ScopedGraphicsContext()
{
puglBackendLeave(window.pData->view);
}

// -----------------------------------------------------------------------
// Window

@@ -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,


+ 0
- 11
dgl/src/WindowPrivateData.cpp View File

@@ -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();
@@ -630,14 +627,6 @@ void Window::PrivateData::runAsModal(const bool blockWait)
}
}

// -----------------------------------------------------------------------
// TESTING

void Window::PrivateData::leaveContext()
{
puglBackendLeave(view);
}

// -----------------------------------------------------------------------
// pugl events



+ 0
- 3
dgl/src/WindowPrivateData.hpp View File

@@ -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();


+ 5
- 1
distrho/DistrhoUI.hpp View File

@@ -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)


+ 1
- 1
distrho/src/DistrhoUI.cpp View File

@@ -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();
}



+ 134
- 109
distrho/src/DistrhoUIPrivateData.hpp View File

@@ -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
@@ -194,100 +313,6 @@ struct UI::PrivateData {
static PluginWindow& createNextWindow(UI* ui, uint width, uint height);
};

// -----------------------------------------------------------------------
// 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



Loading…
Cancel
Save