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:
parent
a9b1676028
commit
bef3828ce2
8 changed files with 435 additions and 438 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:";
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue