Browse Source

OpenGL tweaks, including fix for flickering GL windows when resizing in OSX.

tags/2021-05-28
jules 13 years ago
parent
commit
cf781ecb75
3 changed files with 85 additions and 115 deletions
  1. +32
    -86
      modules/juce_opengl/native/juce_OpenGL_osx.h
  2. +49
    -20
      modules/juce_opengl/opengl/juce_OpenGLContext.cpp
  3. +4
    -9
      modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp

+ 32
- 86
modules/juce_opengl/native/juce_OpenGL_osx.h View File

@@ -23,87 +23,6 @@
==============================================================================
*/
struct ThreadSafeNSOpenGLViewClass : public ObjCClass <NSOpenGLView>
{
ThreadSafeNSOpenGLViewClass() : ObjCClass <NSOpenGLView> ("JUCEGLView_")
{
addIvar <CriticalSection*> ("lock");
addIvar <BOOL> ("needsUpdate");
addMethod (@selector (update), update, "v@:");
addMethod (@selector (reshape), reshape, "v@:");
addMethod (@selector (_surfaceNeedsUpdate:), surfaceNeedsUpdate, "v@:@");
addMethod (@selector (rightMouseDown:), rightMouseDown, "v@:@");
addMethod (@selector (rightMouseUp:), rightMouseUp, "v@:@");
addMethod (@selector (acceptsFirstMouse:), acceptsFirstMouse, "v@:@");
registerClass();
}
static void init (id self)
{
object_setInstanceVariable (self, "lock", new CriticalSection());
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([self respondsToSelector: @selector (setWantsBestResolutionOpenGLSurface:)])
[self setWantsBestResolutionOpenGLSurface: YES];
#endif
setNeedsUpdate (self, YES);
}
static bool makeActive (id self)
{
const ScopedLock sl (*getLock (self));
if ([(NSOpenGLView*) self openGLContext] == nil)
return false;
[[(NSOpenGLView*) self openGLContext] makeCurrentContext];
if (getIvar<void*> (self, "needsUpdate"))
{
sendSuperclassMessage (self, @selector (update));
setNeedsUpdate (self, NO);
}
return true;
}
private:
static CriticalSection* getLock (id self)
{
return getIvar<CriticalSection*> (self, "lock");
}
static void setNeedsUpdate (id self, BOOL b)
{
object_setInstanceVariable (self, "needsUpdate", (void*) b);
}
static void setNeedsUpdateLocked (id self, BOOL b)
{
const ScopedLock sl (*getLock (self));
setNeedsUpdate (self, b);
}
static void dealloc (id self, SEL)
{
delete getLock (self);
sendSuperclassMessage (self, @selector (dealloc));
}
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }
static void surfaceNeedsUpdate (id self, SEL, NSNotification*) { setNeedsUpdateLocked (self, YES); }
static void update (id self, SEL) { setNeedsUpdateLocked (self, YES); }
static void reshape (id self, SEL) { setNeedsUpdateLocked (self, YES); }
static void rightMouseDown (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; }
static void rightMouseUp (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseUp: ev]; }
};
//==============================================================================
class OpenGLContext::NativeContext
{
public:
@@ -130,10 +49,14 @@ public:
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
static ThreadSafeNSOpenGLViewClass cls;
static MouseForwardingNSOpenGLViewClass cls;
view = [cls.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
ThreadSafeNSOpenGLViewClass::init (view);
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([view respondsToSelector: @selector (setWantsBestResolutionOpenGLSurface:)])
[view setWantsBestResolutionOpenGLSurface: YES];
#endif
[[NSNotificationCenter defaultCenter] addObserver: view
selector: @selector (_surfaceNeedsUpdate:)
@@ -172,8 +95,13 @@ public:
if ([renderContext view] != view)
[renderContext setView: view];
ThreadSafeNSOpenGLViewClass::makeActive (view);
return true;
if (NSOpenGLContext* context = [view openGLContext])
{
[context makeCurrentContext];
return true;
}
return false;
}
bool isActive() const noexcept
@@ -225,11 +153,29 @@ public:
return numFrames;
}
private:
NSOpenGLContext* renderContext;
NSOpenGLView* view;
ReferenceCountedObjectPtr<ReferenceCountedObject> viewAttachment;
//==============================================================================
struct MouseForwardingNSOpenGLViewClass : public ObjCClass <NSOpenGLView>
{
MouseForwardingNSOpenGLViewClass() : ObjCClass <NSOpenGLView> ("JUCEGLView_")
{
addMethod (@selector (rightMouseDown:), rightMouseDown, "v@:@");
addMethod (@selector (rightMouseUp:), rightMouseUp, "v@:@");
addMethod (@selector (acceptsFirstMouse:), acceptsFirstMouse, "v@:@");
registerClass();
}
private:
static void rightMouseDown (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; }
static void rightMouseUp (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseUp: ev]; }
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
};


+ 49
- 20
modules/juce_opengl/opengl/juce_OpenGLContext.cpp View File

@@ -37,6 +37,7 @@ public:
#else
shadersAvailable (false),
#endif
hasInitialised (false),
needsUpdate (1)
{
nativeContext = new NativeContext (component, pixFormat, contextToShare);
@@ -65,6 +66,7 @@ public:
#if ! JUCE_ANDROID
stopThread (10000);
#endif
hasInitialised = false;
}
//==============================================================================
@@ -276,6 +278,19 @@ public:
#endif
}
void handleResize()
{
updateViewportSize (true);
#if JUCE_MAC
if (hasInitialised)
{
[nativeContext->view update];
renderFrame();
}
#endif
}
//==============================================================================
void run()
{
@@ -286,15 +301,14 @@ public:
return;
}
nativeContext->makeActive();
nativeContext->setSwapInterval (1);
initialiseOnThread();
#if JUCE_USE_OPENGL_SHADERS && ! JUCE_OPENGL_ES
shadersAvailable = OpenGLShaderProgram::getLanguageVersion() > 0;
#endif
hasInitialised = true;
while (! threadShouldExit())
{
if (! renderFrame())
@@ -306,15 +320,15 @@ public:
void initialiseOnThread()
{
associatedObjectNames.clear();
associatedObjects.clear();
cachedImageFrameBuffer.release();
jassert (associatedObjectNames.size() == 0);
jassert (! cachedImageFrameBuffer.isValid());
context.makeActive();
nativeContext->initialiseOnRenderThread();
glViewport (0, 0, component.getWidth(), component.getHeight());
context.extensions.initialise();
nativeContext->setSwapInterval (1);
if (context.renderer != nullptr)
context.renderer->newOpenGLContextCreated();
@@ -353,7 +367,7 @@ public:
ReferenceCountedArray<ReferenceCountedObject> associatedObjects;
WaitableEvent canPaintNowFlag, finishedPaintingFlag;
bool shadersAvailable;
bool shadersAvailable, hasInitialised;
Atomic<int> needsUpdate;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedImage)
@@ -411,7 +425,7 @@ public:
&& context.nativeContext != nullptr)
{
if (CachedImage* const c = CachedImage::get (comp))
c->updateViewportSize (true);
c->handleResize();
context.nativeContext->updateWindowPosition (comp.getTopLevelComponent()
->getLocalArea (&comp, comp.getLocalBounds()));
@@ -562,22 +576,37 @@ Component* OpenGLContext::getTargetComponent() const noexcept
return attachment != nullptr ? attachment->getComponent() : nullptr;
}
static ThreadLocalValue<OpenGLContext*> currentThreadActiveContext;
OpenGLContext* OpenGLContext::getCurrentContext()
{
#if JUCE_ANDROID
if (NativeContext* const nc = NativeContext::getActiveContext())
if (CachedImage* currentContext = CachedImage::get (nc->component))
#else
if (CachedImage* currentContext = dynamic_cast <CachedImage*> (Thread::getCurrentThread()))
#endif
return &currentContext->context;
return currentThreadActiveContext.get();
}
return nullptr;
bool OpenGLContext::makeActive() const noexcept
{
OpenGLContext*& current = currentThreadActiveContext.get();
if (nativeContext != nullptr && nativeContext->makeActive())
{
current = const_cast <OpenGLContext*> (this);
return true;
}
current = nullptr;
return false;
}
bool OpenGLContext::makeActive() const noexcept { return nativeContext != nullptr && nativeContext->makeActive(); }
bool OpenGLContext::isActive() const noexcept { return nativeContext != nullptr && nativeContext->isActive(); }
void OpenGLContext::deactivateCurrentContext() { NativeContext::deactivateCurrentContext(); }
bool OpenGLContext::isActive() const noexcept
{
return nativeContext != nullptr && nativeContext->isActive();
}
void OpenGLContext::deactivateCurrentContext()
{
NativeContext::deactivateCurrentContext();
currentThreadActiveContext.get() = nullptr;
}
void OpenGLContext::triggerRepaint()
{


+ 4
- 9
modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp View File

@@ -26,16 +26,11 @@
class OpenGLFrameBuffer::Pimpl
{
public:
Pimpl (OpenGLContext& context_, const int width_, const int height_,
Pimpl (OpenGLContext& c, const int w, const int h,
const bool wantsDepthBuffer, const bool wantsStencilBuffer)
: context (context_),
width (width_),
height (height_),
textureID (0),
frameBufferID (0),
depthOrStencilBuffer (0),
hasDepthBuffer (false),
hasStencilBuffer (false)
: context (c), width (w), height (h),
textureID (0), frameBufferID (0), depthOrStencilBuffer (0),
hasDepthBuffer (false), hasStencilBuffer (false)
{
// Framebuffer objects can only be created when the current thread has an active OpenGL
// context. You'll need to create this object in one of the OpenGLContext's callbacks.


Loading…
Cancel
Save