Browse Source

VST mouse hook fix. AU assertion fix.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
bef3828ce2
8 changed files with 372 additions and 375 deletions
  1. +162
    -156
      juce_amalgamated.cpp
  2. +22
    -22
      juce_amalgamated.h
  3. +2
    -15
      src/audio/plugin_client/VST/juce_VST_Wrapper.cpp
  4. +5
    -6
      src/audio/plugin_host/formats/juce_AudioUnitPluginFormat.mm
  5. +1
    -1
      src/core/juce_StandardHeader.h
  6. +158
    -153
      src/gui/components/special/juce_OpenGLComponent.cpp
  7. +21
    -21
      src/gui/components/special/juce_OpenGLComponent.h
  8. +1
    -1
      src/native/mac/juce_mac_OpenGLComponent.mm

+ 162
- 156
juce_amalgamated.cpp View File

@@ -31827,11 +31827,10 @@ namespace AudioUnitFormatHelpers

const String osTypeToString (OSType type)
{
char s[4];
s[0] = (char) (((uint32) type) >> 24);
s[1] = (char) (((uint32) type) >> 16);
s[2] = (char) (((uint32) type) >> 8);
s[3] = (char) ((uint32) type);
const juce_wchar s[4] = { (juce_wchar) (((uint32) type) >> 24),
(juce_wchar) (((uint32) type) >> 16),
(juce_wchar) (((uint32) type) >> 8),
(juce_wchar) ((uint32) type) };
return String (s, 4);
}

@@ -31842,7 +31841,7 @@ namespace AudioUnitFormatHelpers
return (((OSType) (unsigned char) s[0]) << 24)
| (((OSType) (unsigned char) s[1]) << 16)
| (((OSType) (unsigned char) s[2]) << 8)
| ((OSType) (unsigned char) s[3]);
| ((OSType) (unsigned char) s[3]);
}

static const char* auIdentifierPrefix = "AudioUnit:";
@@ -77111,10 +77110,41 @@ OpenGLContext* OpenGLContext::getCurrentContext()
return nullptr;
}

class OpenGLComponent::OpenGLComponentRenderThread : public Thread
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
{
public:

OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_)
{
}

void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}

void componentPeerChanged()
{
owner->recreateContextAsync();
}

void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopBackgroundThread();
}

private:
OpenGLComponent* const owner;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};

class OpenGLComponent::OpenGLComponentRenderThread : public Thread
{
public:
OpenGLComponentRenderThread (OpenGLComponent& owner_)
: Thread ("OpenGL Render"),
owner (owner_)
@@ -77134,7 +77164,9 @@ public:
Thread::sleep (jmax (1, 20 - elapsed));
}

owner.stopRenderThread();
#if JUCE_LINUX
owner.deleteContext();
#endif
}

private:
@@ -77143,49 +77175,34 @@ private:
JUCE_DECLARE_NON_COPYABLE (OpenGLComponentRenderThread);
};

class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher,
public AsyncUpdater
void OpenGLComponent::startRenderThread()
{
public:

OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_)
{
}
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);

void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}

void componentPeerChanged()
{
owner->stopRendering();
}

void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopRendering();
}
renderThread->startThread (6);
}

void handleAsyncUpdate()
void OpenGLComponent::stopRenderThread()
{
if (renderThread != nullptr)
{
owner->stopRendering();
renderThread->stopThread (5000);
renderThread = nullptr;
}

private:
OpenGLComponent* const owner;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
#if ! JUCE_LINUX
deleteContext();
#endif
}

OpenGLComponent::OpenGLComponent (const OpenGLType type_)
OpenGLComponent::OpenGLComponent (const OpenGLType type_, const bool useBackgroundThread)
: type (type_),
contextToShareListsWith (nullptr),
needToUpdateViewport (true),
useThread (false)
needToDeleteContext (false),
threadStarted (false),
useThread (useBackgroundThread)
{
setOpaque (true);
componentWatcher = new OpenGLComponentWatcher (this);
@@ -77193,39 +77210,10 @@ OpenGLComponent::OpenGLComponent (const OpenGLType type_)

OpenGLComponent::~OpenGLComponent()
{
stopRendering();
renderThread = nullptr;
stopBackgroundThread();
componentWatcher = nullptr;
}

void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
context = nullptr;
}

void OpenGLComponent::updateContextPosition()
{
needToUpdateViewport = true;

if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();

if (topComp->getPeer() != nullptr)
{
const ScopedLock sl (contextLock);

if (context != nullptr)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
}

const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
OpenGLPixelFormat pf;
@@ -77242,8 +77230,8 @@ void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
if (! (preferredPixelFormat == formatToUse))
{
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
recreateContextAsync();
}
}

@@ -77252,95 +77240,145 @@ void OpenGLComponent::shareWith (OpenGLContext* c)
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
deleteContext();
contextToShareListsWith = c;
recreateContextAsync();
}
}

void OpenGLComponent::recreateContextAsync()
{
const ScopedLock sl (contextLock);
needToDeleteContext = true;
repaint();
}

bool OpenGLComponent::makeCurrentContextActive()
{
return context != nullptr && context->makeActive();
}

void OpenGLComponent::makeCurrentContextInactive()
{
if (context != nullptr)
context->makeInactive();
}

bool OpenGLComponent::isActiveContext() const noexcept
{
return context != nullptr && context->isActive();
}

void OpenGLComponent::swapBuffers()
{
if (context != nullptr)
context->swapBuffers();
}

void OpenGLComponent::updateContext()
{
if (needToDeleteContext)
deleteContext();

if (context == nullptr)
{
const ScopedLock sl (contextLock);

if (isShowing() && getTopLevelComponent()->getPeer() != nullptr)
if (context == nullptr)
{
context = createContext();

if (context != nullptr)
{
#if JUCE_LINUX
if (! useThread)
#endif
updateContextPosition();

if (context->makeActive())
{
newOpenGLContextCreated();
context->makeInactive();
}
}
}
}

return context != nullptr && context->makeActive();
}

void OpenGLComponent::makeCurrentContextInactive()
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
if (context != nullptr)
context->makeInactive();
}
{
if (context->makeActive())
{
releaseOpenGLContext();
context->makeInactive();
}

bool OpenGLComponent::isActiveContext() const noexcept
{
return context != nullptr && context->isActive();
context = nullptr;
}

needToDeleteContext = false;
}

void OpenGLComponent::swapBuffers()
void OpenGLComponent::updateContextPosition()
{
if (context != nullptr)
context->swapBuffers();
needToUpdateViewport = true;

if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();

if (topComp->getPeer() != nullptr)
{
const ScopedLock sl (contextLock);

if (context != nullptr)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
}

void OpenGLComponent::setUsingDedicatedThread (bool useDedicatedThread) noexcept
void OpenGLComponent::stopBackgroundThread()
{
useThread = useDedicatedThread;
if (threadStarted)
{
stopRenderThread();
threadStarted = false;
}
}

void OpenGLComponent::paint (Graphics&)
{
ComponentPeer* const peer = getPeer();

if (useThread)
{
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);

if (! renderThread->isThreadRunning())
if (peer != nullptr && isShowing())
{
componentWatcher->handleUpdateNowIfNeeded(); // may still be shutting down as well

#if ! JUCE_LINUX
// Except for Linux, create the context first
const ScopedLock sl (contextLock);

if (makeCurrentContextActive()) // Make active just to create
makeCurrentContextInactive();
updateContext();
#endif

startRenderThread();
if (! threadStarted)
{
threadStarted = true;
startRenderThread();
}
}

// fall-through and update the masking region
}
else
{
if (renderThread != nullptr)
{
stopRendering();
renderThread = nullptr;
}
updateContext();

if (! renderAndSwapBuffers())
return;
}

ComponentPeer* const peer = getPeer();

if (peer != nullptr)
{
const Point<int> topLeft (getScreenPosition() - peer->getScreenPosition());
@@ -77348,64 +77386,32 @@ void OpenGLComponent::paint (Graphics&)
}
}

void OpenGLComponent::startRenderThread()
{
// If this is overriden, user will provide a thread. The renderThread object will
// not be used
jassert (renderThread != nullptr);

renderThread->startThread (6);
}

void OpenGLComponent::stopRenderThread()
bool OpenGLComponent::renderAndSwapBuffers()
{
releaseOpenGLContext();
const ScopedLock sl (contextLock);

#if JUCE_LINUX
deleteContext();
#else
makeCurrentContextInactive();
updateContext();
#endif

componentWatcher->triggerAsyncUpdate();
}

bool OpenGLComponent::renderAndSwapBuffers()
{
const ScopedLock sl (contextLock);
if (context != nullptr)
{
if (! makeCurrentContextActive())
return false;

if (! makeCurrentContextActive())
return false;
if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}

if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
renderOpenGL();
swapBuffers();
}

renderOpenGL();
swapBuffers();

return true;
}

void OpenGLComponent::stopRendering()
{
componentWatcher->cancelPendingUpdate();

if (renderThread != nullptr)
renderThread->stopThread (5000);

if (context != nullptr && makeCurrentContextActive())
{
// On Linux, when threaded, context will have already been cleared
const ScopedLock sl (contextLock);

releaseOpenGLContext();
deleteContext();
}
}

void OpenGLComponent::internalRepaint (int x, int y, int w, int h)
{
Component::internalRepaint (x, y, w, h);
@@ -275158,7 +275164,7 @@ private:
OpenGLContext* OpenGLComponent::createContext()
{
ScopedPointer<WindowedGLContext> c (new WindowedGLContext (*this, preferredPixelFormat,
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : 0));
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : nil));

return (c->renderContext != nil) ? c.release() : nullptr;
}
@@ -281055,7 +281061,7 @@ private:
OpenGLContext* OpenGLComponent::createContext()
{
ScopedPointer<WindowedGLContext> c (new WindowedGLContext (*this, preferredPixelFormat,
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : 0));
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : nil));

return (c->renderContext != nil) ? c.release() : nullptr;
}


+ 22
- 22
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 82
#define JUCE_BUILDNUMBER 83

/** Current Juce version number.

@@ -64090,8 +64090,13 @@ public:
#endif
};

/** Creates an OpenGLComponent. */
OpenGLComponent (OpenGLType type = openGLDefault);
/** Creates an OpenGLComponent.
If useBackgroundThread is true, the component will launch a background thread
to do the rendering. If false, then renderOpenGL() will be called as part of the
normal paint() method.
*/
OpenGLComponent (OpenGLType type = openGLDefault,
bool useBackgroundThread = false);

/** Destructor. */
~OpenGLComponent();
@@ -64126,14 +64131,9 @@ public:
/** Flips the openGL buffers over. */
void swapBuffers();

/** Indicates whether the component should perform its rendering on a background thread.
By default, this is set to false, and the renderOpenGL() callback happens on the main
UI thread, in response to a repaint. If set to true, then the component will create
a background thread which it uses to repeatedly call renderOpenGL().
/** Returns true if the component is performing the rendering on a background thread.
This property is specified in the constructor.
*/
void setUsingDedicatedThread (bool useDedicatedThread) noexcept;

/** Returns true if the component is performing the rendering on a background thread. */
bool isUsingDedicatedThread() const noexcept { return useThread; }

/** This replaces the normal paint() callback - use it to draw your openGL stuff.
@@ -64211,7 +64211,7 @@ public:
*/
void makeCurrentContextInactive();

/** Returns true if this component is the active openGL context for the
/** Returns true if this component's context is the active openGL context for the
current thread.

@see OpenGLContext::isActive
@@ -64219,12 +64219,7 @@ public:
bool isActiveContext() const noexcept;

/** Calls the rendering callback, and swaps the buffers afterwards.

This is called automatically by paint() when the component needs to be rendered.

It can be overridden if you need to decouple the rendering from the paint callback
and render with a custom thread.

Returns true if the operation succeeded.
*/
virtual bool renderAndSwapBuffers();
@@ -64238,6 +64233,12 @@ public:
*/
CriticalSection& getContextLock() noexcept { return contextLock; }

/** Delete the context.
You should only need to call this if you've written a custom thread - if so, make
sure that your thread calls this before it terminates.
*/
void deleteContext();

/** Returns the native handle of an embedded heavyweight window, if there is one.

E.g. On windows, this will return the HWND of the sub-window containing
@@ -64245,10 +64246,6 @@ public:
*/
void* getNativeWindowHandle() const;

/** Delete the context.
This can be called back on the same thread that created the context. */
void deleteContext();

protected:
/** Kicks off a thread to start rendering.
The default implementation creates and manages an internal thread that tries
@@ -64282,12 +64279,15 @@ private:

CriticalSection contextLock;
OpenGLPixelFormat preferredPixelFormat;
bool needToUpdateViewport, useThread;
bool needToUpdateViewport, needToDeleteContext, threadStarted;
const bool useThread;

OpenGLContext* createContext();
void updateContext();
void updateContextPosition();
void stopBackgroundThread();
void recreateContextAsync();
void internalRepaint (int x, int y, int w, int h);
void stopRendering();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent);
};


+ 2
- 15
src/audio/plugin_client/VST/juce_VST_Wrapper.cpp View File

@@ -210,22 +210,9 @@ namespace
LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam)
{
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x20a
struct MSLLHOOKSTRUCT
{
POINT pt;
DWORD mouseData;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
};
#endif
if (nCode >= 0 && wParam == WM_MOUSEWHEEL)
{
const MSLLHOOKSTRUCT& hs = *(MSLLHOOKSTRUCT*) lParam;
const MOUSEHOOKSTRUCTEX& hs = *(MOUSEHOOKSTRUCTEX*) lParam;
Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x,
hs.pt.y));
@@ -240,7 +227,7 @@ namespace
void registerMouseWheelHook()
{
if (mouseHookUsers++ == 0)
mouseWheelHook = SetWindowsHookEx (7 /*WH_MOUSE*/, mouseWheelHookCallback,
mouseWheelHook = SetWindowsHookEx (WH_MOUSE, mouseWheelHookCallback,
(HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(),
GetCurrentThreadId());
}


+ 5
- 6
src/audio/plugin_host/formats/juce_AudioUnitPluginFormat.mm View File

@@ -72,11 +72,10 @@ namespace AudioUnitFormatHelpers
const String osTypeToString (OSType type)
{
char s[4];
s[0] = (char) (((uint32) type) >> 24);
s[1] = (char) (((uint32) type) >> 16);
s[2] = (char) (((uint32) type) >> 8);
s[3] = (char) ((uint32) type);
const juce_wchar s[4] = { (juce_wchar) (((uint32) type) >> 24),
(juce_wchar) (((uint32) type) >> 16),
(juce_wchar) (((uint32) type) >> 8),
(juce_wchar) ((uint32) type) };
return String (s, 4);
}
@@ -87,7 +86,7 @@ namespace AudioUnitFormatHelpers
return (((OSType) (unsigned char) s[0]) << 24)
| (((OSType) (unsigned char) s[1]) << 16)
| (((OSType) (unsigned char) s[2]) << 8)
| ((OSType) (unsigned char) s[3]);
| ((OSType) (unsigned char) s[3]);
}
static const char* auIdentifierPrefix = "AudioUnit:";


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 82
#define JUCE_BUILDNUMBER 83
/** Current Juce version number.


+ 158
- 153
src/gui/components/special/juce_OpenGLComponent.cpp View File

@@ -131,10 +131,44 @@ OpenGLContext* OpenGLContext::getCurrentContext()
}
//==============================================================================
class OpenGLComponent::OpenGLComponentRenderThread : public Thread
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher
{
public:
//==============================================================================
OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_)
{
}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}
void componentPeerChanged()
{
owner->recreateContextAsync();
}
void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopBackgroundThread();
}
//==============================================================================
private:
OpenGLComponent* const owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
//==============================================================================
class OpenGLComponent::OpenGLComponentRenderThread : public Thread
{
public:
OpenGLComponentRenderThread (OpenGLComponent& owner_)
: Thread ("OpenGL Render"),
owner (owner_)
@@ -154,64 +188,46 @@ public:
Thread::sleep (jmax (1, 20 - elapsed));
}
owner.stopRenderThread();
#if JUCE_LINUX
owner.deleteContext();
#endif
}
//==============================================================================
private:
OpenGLComponent& owner;
JUCE_DECLARE_NON_COPYABLE (OpenGLComponentRenderThread);
};
//==============================================================================
class OpenGLComponent::OpenGLComponentWatcher : public ComponentMovementWatcher,
public AsyncUpdater
void OpenGLComponent::startRenderThread()
{
public:
//==============================================================================
OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_)
{
}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}
void componentPeerChanged()
{
owner->stopRendering();
}
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);
void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopRendering();
}
renderThread->startThread (6);
}
void handleAsyncUpdate()
void OpenGLComponent::stopRenderThread()
{
if (renderThread != nullptr)
{
owner->stopRendering();
renderThread->stopThread (5000);
renderThread = nullptr;
}
//==============================================================================
private:
OpenGLComponent* const owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
#if ! JUCE_LINUX
deleteContext();
#endif
}
//==============================================================================
OpenGLComponent::OpenGLComponent (const OpenGLType type_)
OpenGLComponent::OpenGLComponent (const OpenGLType type_, const bool useBackgroundThread)
: type (type_),
contextToShareListsWith (nullptr),
needToUpdateViewport (true),
useThread (false)
needToDeleteContext (false),
threadStarted (false),
useThread (useBackgroundThread)
{
setOpaque (true);
componentWatcher = new OpenGLComponentWatcher (this);
@@ -219,39 +235,10 @@ OpenGLComponent::OpenGLComponent (const OpenGLType type_)
OpenGLComponent::~OpenGLComponent()
{
stopRendering();
renderThread = nullptr;
stopBackgroundThread();
componentWatcher = nullptr;
}
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
context = nullptr;
}
void OpenGLComponent::updateContextPosition()
{
needToUpdateViewport = true;
if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();
if (topComp->getPeer() != nullptr)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
OpenGLPixelFormat pf;
@@ -268,8 +255,8 @@ void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
if (! (preferredPixelFormat == formatToUse))
{
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
recreateContextAsync();
}
}
@@ -278,95 +265,145 @@ void OpenGLComponent::shareWith (OpenGLContext* c)
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
deleteContext();
contextToShareListsWith = c;
recreateContextAsync();
}
}
void OpenGLComponent::recreateContextAsync()
{
const ScopedLock sl (contextLock);
needToDeleteContext = true;
repaint();
}
bool OpenGLComponent::makeCurrentContextActive()
{
return context != nullptr && context->makeActive();
}
void OpenGLComponent::makeCurrentContextInactive()
{
if (context != nullptr)
context->makeInactive();
}
bool OpenGLComponent::isActiveContext() const noexcept
{
return context != nullptr && context->isActive();
}
void OpenGLComponent::swapBuffers()
{
if (context != nullptr)
context->swapBuffers();
}
void OpenGLComponent::updateContext()
{
if (needToDeleteContext)
deleteContext();
if (context == nullptr)
{
const ScopedLock sl (contextLock);
if (isShowing() && getTopLevelComponent()->getPeer() != nullptr)
if (context == nullptr)
{
context = createContext();
if (context != nullptr)
{
#if JUCE_LINUX
if (! useThread)
#endif
updateContextPosition();
if (context->makeActive())
{
newOpenGLContextCreated();
context->makeInactive();
}
}
}
}
return context != nullptr && context->makeActive();
}
void OpenGLComponent::makeCurrentContextInactive()
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
if (context != nullptr)
context->makeInactive();
}
{
if (context->makeActive())
{
releaseOpenGLContext();
context->makeInactive();
}
bool OpenGLComponent::isActiveContext() const noexcept
{
return context != nullptr && context->isActive();
context = nullptr;
}
needToDeleteContext = false;
}
void OpenGLComponent::swapBuffers()
void OpenGLComponent::updateContextPosition()
{
if (context != nullptr)
context->swapBuffers();
needToUpdateViewport = true;
if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();
if (topComp->getPeer() != nullptr)
{
const ScopedLock sl (contextLock);
if (context != nullptr)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
}
void OpenGLComponent::setUsingDedicatedThread (bool useDedicatedThread) noexcept
void OpenGLComponent::stopBackgroundThread()
{
useThread = useDedicatedThread;
if (threadStarted)
{
stopRenderThread();
threadStarted = false;
}
}
void OpenGLComponent::paint (Graphics&)
{
ComponentPeer* const peer = getPeer();
if (useThread)
{
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);
if (! renderThread->isThreadRunning())
if (peer != nullptr && isShowing())
{
componentWatcher->handleUpdateNowIfNeeded(); // may still be shutting down as well
#if ! JUCE_LINUX
// Except for Linux, create the context first
const ScopedLock sl (contextLock);
if (makeCurrentContextActive()) // Make active just to create
makeCurrentContextInactive();
updateContext();
#endif
startRenderThread();
if (! threadStarted)
{
threadStarted = true;
startRenderThread();
}
}
// fall-through and update the masking region
}
else
{
if (renderThread != nullptr)
{
stopRendering();
renderThread = nullptr;
}
updateContext();
if (! renderAndSwapBuffers())
return;
}
ComponentPeer* const peer = getPeer();
if (peer != nullptr)
{
const Point<int> topLeft (getScreenPosition() - peer->getScreenPosition());
@@ -374,64 +411,32 @@ void OpenGLComponent::paint (Graphics&)
}
}
void OpenGLComponent::startRenderThread()
{
// If this is overriden, user will provide a thread. The renderThread object will
// not be used
jassert (renderThread != nullptr);
renderThread->startThread (6);
}
void OpenGLComponent::stopRenderThread()
bool OpenGLComponent::renderAndSwapBuffers()
{
releaseOpenGLContext();
const ScopedLock sl (contextLock);
#if JUCE_LINUX
deleteContext();
#else
makeCurrentContextInactive();
updateContext();
#endif
componentWatcher->triggerAsyncUpdate();
}
bool OpenGLComponent::renderAndSwapBuffers()
{
const ScopedLock sl (contextLock);
if (context != nullptr)
{
if (! makeCurrentContextActive())
return false;
if (! makeCurrentContextActive())
return false;
if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
renderOpenGL();
swapBuffers();
}
renderOpenGL();
swapBuffers();
return true;
}
void OpenGLComponent::stopRendering()
{
componentWatcher->cancelPendingUpdate();
if (renderThread != nullptr)
renderThread->stopThread (5000);
if (context != nullptr && makeCurrentContextActive())
{
// On Linux, when threaded, context will have already been cleared
const ScopedLock sl (contextLock);
releaseOpenGLContext();
deleteContext();
}
}
void OpenGLComponent::internalRepaint (int x, int y, int w, int h)
{
Component::internalRepaint (x, y, w, h);


+ 21
- 21
src/gui/components/special/juce_OpenGLComponent.h View File

@@ -198,8 +198,13 @@ public:
#endif
};
/** Creates an OpenGLComponent. */
OpenGLComponent (OpenGLType type = openGLDefault);
/** Creates an OpenGLComponent.
If useBackgroundThread is true, the component will launch a background thread
to do the rendering. If false, then renderOpenGL() will be called as part of the
normal paint() method.
*/
OpenGLComponent (OpenGLType type = openGLDefault,
bool useBackgroundThread = false);
/** Destructor. */
~OpenGLComponent();
@@ -237,14 +242,9 @@ public:
/** Flips the openGL buffers over. */
void swapBuffers();
/** Indicates whether the component should perform its rendering on a background thread.
By default, this is set to false, and the renderOpenGL() callback happens on the main
UI thread, in response to a repaint. If set to true, then the component will create
a background thread which it uses to repeatedly call renderOpenGL().
/** Returns true if the component is performing the rendering on a background thread.
This property is specified in the constructor.
*/
void setUsingDedicatedThread (bool useDedicatedThread) noexcept;
/** Returns true if the component is performing the rendering on a background thread. */
bool isUsingDedicatedThread() const noexcept { return useThread; }
/** This replaces the normal paint() callback - use it to draw your openGL stuff.
@@ -323,7 +323,7 @@ public:
*/
void makeCurrentContextInactive();
/** Returns true if this component is the active openGL context for the
/** Returns true if this component's context is the active openGL context for the
current thread.
@see OpenGLContext::isActive
@@ -333,12 +333,7 @@ public:
//==============================================================================
/** Calls the rendering callback, and swaps the buffers afterwards.
This is called automatically by paint() when the component needs to be rendered.
It can be overridden if you need to decouple the rendering from the paint callback
and render with a custom thread.
Returns true if the operation succeeded.
*/
virtual bool renderAndSwapBuffers();
@@ -352,6 +347,12 @@ public:
*/
CriticalSection& getContextLock() noexcept { return contextLock; }
/** Delete the context.
You should only need to call this if you've written a custom thread - if so, make
sure that your thread calls this before it terminates.
*/
void deleteContext();
//==============================================================================
/** Returns the native handle of an embedded heavyweight window, if there is one.
@@ -360,10 +361,6 @@ public:
*/
void* getNativeWindowHandle() const;
/** Delete the context.
This can be called back on the same thread that created the context. */
void deleteContext();
protected:
/** Kicks off a thread to start rendering.
The default implementation creates and manages an internal thread that tries
@@ -398,12 +395,15 @@ private:
CriticalSection contextLock;
OpenGLPixelFormat preferredPixelFormat;
bool needToUpdateViewport, useThread;
bool needToUpdateViewport, needToDeleteContext, threadStarted;
const bool useThread;
OpenGLContext* createContext();
void updateContext();
void updateContextPosition();
void stopBackgroundThread();
void recreateContextAsync();
void internalRepaint (int x, int y, int w, int h);
void stopRendering();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent);
};


+ 1
- 1
src/native/mac/juce_mac_OpenGLComponent.mm View File

@@ -271,7 +271,7 @@ private:
OpenGLContext* OpenGLComponent::createContext()
{
ScopedPointer<WindowedGLContext> c (new WindowedGLContext (*this, preferredPixelFormat,
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : 0));
contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : nil));
return (c->renderContext != nil) ? c.release() : nullptr;
}


Loading…
Cancel
Save