1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-29 02:40:05 +00:00

VST mouse hook fix. AU assertion fix.

This commit is contained in:
Julian Storer 2011-04-28 10:45:44 +01:00
parent a9b1676028
commit bef3828ce2
8 changed files with 435 additions and 438 deletions

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:
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);
OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_)
renderThread->startThread (6);
}
void OpenGLComponent::stopRenderThread()
{
if (renderThread != nullptr)
{
renderThread->stopThread (5000);
renderThread = nullptr;
}
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}
#if ! JUCE_LINUX
deleteContext();
#endif
}
void componentPeerChanged()
{
owner->stopRendering();
}
void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopRendering();
}
void handleAsyncUpdate()
{
owner->stopRendering();
}
private:
OpenGLComponent* const owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponentWatcher);
};
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,15 +77210,115 @@ OpenGLComponent::OpenGLComponent (const OpenGLType type_)
OpenGLComponent::~OpenGLComponent()
{
stopRendering();
renderThread = nullptr;
stopBackgroundThread();
componentWatcher = nullptr;
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != nullptr)
pf = context->getPixelFormat();
return pf;
}
void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
if (! (preferredPixelFormat == formatToUse))
{
const ScopedLock sl (contextLock);
preferredPixelFormat = formatToUse;
recreateContextAsync();
}
}
void OpenGLComponent::shareWith (OpenGLContext* c)
{
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
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 (context == nullptr)
{
context = createContext();
if (context != nullptr)
{
#if JUCE_LINUX
if (! useThread)
#endif
updateContextPosition();
if (context->makeActive())
{
newOpenGLContextCreated();
context->makeInactive();
}
}
}
}
}
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
context = nullptr;
if (context != nullptr)
{
if (context->makeActive())
{
releaseOpenGLContext();
context->makeInactive();
}
context = nullptr;
}
needToDeleteContext = false;
}
void OpenGLComponent::updateContextPosition()
@ -77226,121 +77343,42 @@ void OpenGLComponent::updateContextPosition()
}
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
void OpenGLComponent::stopBackgroundThread()
{
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != nullptr)
pf = context->getPixelFormat();
return pf;
}
void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
if (! (preferredPixelFormat == formatToUse))
if (threadStarted)
{
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
stopRenderThread();
threadStarted = false;
}
}
void OpenGLComponent::shareWith (OpenGLContext* c)
{
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
deleteContext();
contextToShareListsWith = c;
}
}
bool OpenGLComponent::makeCurrentContextActive()
{
if (context == nullptr)
{
const ScopedLock sl (contextLock);
if (isShowing() && getTopLevelComponent()->getPeer() != nullptr)
{
context = createContext();
if (context != nullptr)
{
if (! useThread)
updateContextPosition();
if (context->makeActive())
newOpenGLContextCreated();
}
}
}
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::setUsingDedicatedThread (bool useDedicatedThread) noexcept
{
useThread = useDedicatedThread;
}
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()
{
releaseOpenGLContext();
#if JUCE_LINUX
deleteContext();
#else
makeCurrentContextInactive();
#endif
componentWatcher->triggerAsyncUpdate();
}
bool OpenGLComponent::renderAndSwapBuffers()
{
const ScopedLock sl (contextLock);
if (! makeCurrentContextActive())
return false;
#if JUCE_LINUX
updateContext();
#endif
if (needToUpdateViewport)
if (context != nullptr)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
if (! makeCurrentContextActive())
return false;
renderOpenGL();
swapBuffers();
if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
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;
}

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

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

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:";

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.

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_)
if (renderThread == nullptr)
renderThread = new OpenGLComponentRenderThread (*this);
renderThread->startThread (6);
}
void OpenGLComponent::stopRenderThread()
{
if (renderThread != nullptr)
{
renderThread->stopThread (5000);
renderThread = nullptr;
}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
owner->updateContextPosition();
}
void componentPeerChanged()
{
owner->stopRendering();
}
void componentVisibilityChanged()
{
if (! owner->isShowing())
owner->stopRendering();
}
void handleAsyncUpdate()
{
owner->stopRendering();
}
//==============================================================================
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,15 +235,115 @@ OpenGLComponent::OpenGLComponent (const OpenGLType type_)
OpenGLComponent::~OpenGLComponent()
{
stopRendering();
renderThread = nullptr;
stopBackgroundThread();
componentWatcher = nullptr;
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != nullptr)
pf = context->getPixelFormat();
return pf;
}
void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
if (! (preferredPixelFormat == formatToUse))
{
const ScopedLock sl (contextLock);
preferredPixelFormat = formatToUse;
recreateContextAsync();
}
}
void OpenGLComponent::shareWith (OpenGLContext* c)
{
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
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 (context == nullptr)
{
context = createContext();
if (context != nullptr)
{
#if JUCE_LINUX
if (! useThread)
#endif
updateContextPosition();
if (context->makeActive())
{
newOpenGLContextCreated();
context->makeInactive();
}
}
}
}
}
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
context = nullptr;
if (context != nullptr)
{
if (context->makeActive())
{
releaseOpenGLContext();
context->makeInactive();
}
context = nullptr;
}
needToDeleteContext = false;
}
void OpenGLComponent::updateContextPosition()
@ -252,121 +368,42 @@ void OpenGLComponent::updateContextPosition()
}
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
void OpenGLComponent::stopBackgroundThread()
{
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != nullptr)
pf = context->getPixelFormat();
return pf;
}
void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
if (! (preferredPixelFormat == formatToUse))
if (threadStarted)
{
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
stopRenderThread();
threadStarted = false;
}
}
void OpenGLComponent::shareWith (OpenGLContext* c)
{
if (contextToShareListsWith != c)
{
const ScopedLock sl (contextLock);
deleteContext();
contextToShareListsWith = c;
}
}
bool OpenGLComponent::makeCurrentContextActive()
{
if (context == nullptr)
{
const ScopedLock sl (contextLock);
if (isShowing() && getTopLevelComponent()->getPeer() != nullptr)
{
context = createContext();
if (context != nullptr)
{
if (! useThread)
updateContextPosition();
if (context->makeActive())
newOpenGLContextCreated();
}
}
}
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::setUsingDedicatedThread (bool useDedicatedThread) noexcept
{
useThread = useDedicatedThread;
}
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()
{
releaseOpenGLContext();
#if JUCE_LINUX
deleteContext();
#else
makeCurrentContextInactive();
#endif
componentWatcher->triggerAsyncUpdate();
}
bool OpenGLComponent::renderAndSwapBuffers()
{
const ScopedLock sl (contextLock);
if (! makeCurrentContextActive())
return false;
#if JUCE_LINUX
updateContext();
#endif
if (needToUpdateViewport)
if (context != nullptr)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
if (! makeCurrentContextActive())
return false;
renderOpenGL();
swapBuffers();
if (needToUpdateViewport)
{
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
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);

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

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;
}