diff --git a/modules/juce_opengl/native/juce_OpenGL_android.h b/modules/juce_opengl/native/juce_OpenGL_android.h index 84c414f7a6..f7c35e1489 100644 --- a/modules/juce_opengl/native/juce_OpenGL_android.h +++ b/modules/juce_opengl/native/juce_OpenGL_android.h @@ -37,7 +37,8 @@ class OpenGLContext::NativeContext public: NativeContext (Component& comp, const OpenGLPixelFormat& pixelFormat, - void* /*contextToShareWith*/) + void* /*contextToShareWith*/, + bool /*useMultisampling*/) : component (comp), isInsideGLCallback (false) { diff --git a/modules/juce_opengl/native/juce_OpenGL_ios.h b/modules/juce_opengl/native/juce_OpenGL_ios.h index a72b91cabe..6c63be6fb9 100644 --- a/modules/juce_opengl/native/juce_OpenGL_ios.h +++ b/modules/juce_opengl/native/juce_OpenGL_ios.h @@ -45,10 +45,13 @@ class OpenGLContext::NativeContext public: NativeContext (Component& component, const OpenGLPixelFormat& pixelFormat, - void* contextToShareWith) + void* contextToShareWith, + bool useMultisampling) : frameBufferHandle (0), colorBufferHandle (0), depthBufferHandle (0), + msaaColorHandle (0), msaaBufferHandle (0), lastWidth (0), lastHeight (0), needToRebuildBuffers (false), - swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0) + swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0), + useMSAA (useMultisampling) { JUCE_AUTORELEASEPOOL { @@ -67,6 +70,7 @@ public: glLayer = (CAEAGLLayer*) [view layer]; glLayer.contentsScale = Desktop::getInstance().getDisplays().getMainDisplay().scale; + glLayer.opaque = true; [((UIView*) peer->getNativeHandle()) addSubview: view]; @@ -114,7 +118,8 @@ public: if (! [EAGLContext setCurrentContext: context]) return false; - glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle); + glBindFramebuffer (GL_FRAMEBUFFER, useMSAA ? msaaBufferHandle + : frameBufferHandle); return true; } @@ -169,11 +174,13 @@ private: JuceGLView* view; CAEAGLLayer* glLayer; EAGLContext* context; - GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle; + GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle, + msaaColorHandle, msaaBufferHandle; + int volatile lastWidth, lastHeight; bool volatile needToRebuildBuffers; int swapFrames; - bool useDepthBuffer; + bool useDepthBuffer, useMSAA; //============================================================================== void createGLBuffers() @@ -181,28 +188,43 @@ private: glGenFramebuffers (1, &frameBufferHandle); glGenRenderbuffers (1, &colorBufferHandle); + glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle); glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle); + + glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle); + bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer]; jassert (ok); (void) ok; - if (useDepthBuffer) - { - GLint width, height; - glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); - glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); + GLint width, height; + glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); + glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); - glGenRenderbuffers (1, &depthBufferHandle); - glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle); - glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + if (useMSAA) + { + glGenFramebuffers (1, &msaaBufferHandle); + glGenRenderbuffers (1, &msaaColorHandle); + + glBindFramebuffer (GL_FRAMEBUFFER, msaaBufferHandle); + glBindRenderbuffer (GL_RENDERBUFFER, msaaColorHandle); + + glRenderbufferStorageMultisampleAPPLE (GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height); + + glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColorHandle); } - glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle); - - glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle); - glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle); - if (useDepthBuffer) + { + glGenRenderbuffers (1, &depthBufferHandle); + glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle); + + if (useMSAA) + glRenderbufferStorageMultisampleAPPLE (GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height); + else + glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferHandle); + } jassert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); JUCE_CHECK_OPENGL_ERROR @@ -213,27 +235,18 @@ private: JUCE_CHECK_OPENGL_ERROR [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil]; - if (frameBufferHandle != 0) - { - glDeleteFramebuffers (1, &frameBufferHandle); - frameBufferHandle = 0; - } - - if (colorBufferHandle != 0) - { - glDeleteRenderbuffers (1, &colorBufferHandle); - colorBufferHandle = 0; - } - - if (depthBufferHandle != 0) - { - glDeleteRenderbuffers (1, &depthBufferHandle); - depthBufferHandle = 0; - } + deleteFrameBuffer (frameBufferHandle); + deleteFrameBuffer (msaaBufferHandle); + deleteRenderBuffer (colorBufferHandle); + deleteRenderBuffer (depthBufferHandle); + deleteRenderBuffer (msaaColorHandle); JUCE_CHECK_OPENGL_ERROR } + static void deleteFrameBuffer (GLuint& i) { if (i != 0) glDeleteFramebuffers (1, &i); i = 0; } + static void deleteRenderBuffer (GLuint& i) { if (i != 0) glDeleteRenderbuffers (1, &i); i = 0; } + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext) }; diff --git a/modules/juce_opengl/native/juce_OpenGL_linux.h b/modules/juce_opengl/native/juce_OpenGL_linux.h index f45bbd7660..0d47e8175b 100644 --- a/modules/juce_opengl/native/juce_OpenGL_linux.h +++ b/modules/juce_opengl/native/juce_OpenGL_linux.h @@ -31,7 +31,8 @@ class OpenGLContext::NativeContext public: NativeContext (Component& component, const OpenGLPixelFormat& pixelFormat, - void* shareContext) + void* shareContext, + bool /*useMultisampling*/) : renderContext (0), embeddedWindow (0), swapFrames (0), bestVisual (0), contextToShareWith (shareContext) { diff --git a/modules/juce_opengl/native/juce_OpenGL_osx.h b/modules/juce_opengl/native/juce_OpenGL_osx.h index 594b6e8a9c..ab7b789d6a 100644 --- a/modules/juce_opengl/native/juce_OpenGL_osx.h +++ b/modules/juce_opengl/native/juce_OpenGL_osx.h @@ -27,7 +27,8 @@ class OpenGLContext::NativeContext public: NativeContext (Component& component, const OpenGLPixelFormat& pixFormat, - void* contextToShare) + void* contextToShare, + bool /*useMultisampling*/) : lastSwapTime (0), minSwapTimeMs (0), underrunCounter (0) { NSOpenGLPixelFormatAttribute attribs[] = diff --git a/modules/juce_opengl/native/juce_OpenGL_win32.h b/modules/juce_opengl/native/juce_OpenGL_win32.h index 346601d707..3338b9e758 100644 --- a/modules/juce_opengl/native/juce_OpenGL_win32.h +++ b/modules/juce_opengl/native/juce_OpenGL_win32.h @@ -30,7 +30,8 @@ class OpenGLContext::NativeContext public: NativeContext (Component& component, const OpenGLPixelFormat& pixelFormat, - void* contextToShareWith) + void* contextToShareWith, + bool /*useMultisampling*/) { createNativeWindow (component); diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index 2726f2043e..8bd131685c 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -39,7 +39,7 @@ public: hasInitialised (false), needsUpdate (1) { - nativeContext = new NativeContext (component, pixFormat, contextToShare); + nativeContext = new NativeContext (component, pixFormat, contextToShare, c.useMultisampling); if (nativeContext->createdOk()) context.nativeContext = nativeContext; @@ -521,7 +521,7 @@ private: //============================================================================== OpenGLContext::OpenGLContext() : nativeContext (nullptr), renderer (nullptr), contextToShareWith (nullptr), - renderComponents (true) + renderComponents (true), useMultisampling (false) { } @@ -566,6 +566,15 @@ void OpenGLContext::setNativeSharedContext (void* nativeContextToShareWith) noex contextToShareWith = nativeContextToShareWith; } +void OpenGLContext::setMultisamplingEnabled (bool b) noexcept +{ + // This method must not be called when the context has already been attached! + // Call it before attaching your context, or use detach() first, before calling this! + jassert (nativeContext == nullptr); + + useMultisampling = b; +} + void OpenGLContext::attachTo (Component& component) { component.repaint(); diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.h b/modules/juce_opengl/opengl/juce_OpenGLContext.h index 7cba146cb5..b9cd4ba770 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.h +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.h @@ -92,6 +92,11 @@ public: */ void setNativeSharedContext (void* nativeContextToShareWith) noexcept; + /** Enables multisampling on platforms where this is implemented. + If enabling this, you must call this method before attachTo(). + */ + void setMultisamplingEnabled (bool) noexcept; + //============================================================================== /** Attaches the context to a target component. @@ -242,7 +247,7 @@ private: ScopedPointer attachment; OpenGLPixelFormat pixelFormat; void* contextToShareWith; - bool renderComponents; + bool renderComponents, useMultisampling; CachedImage* getCachedImage() const noexcept;