1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-13 00:04:19 +00:00

Added Animated App template and examples

This commit is contained in:
Felix Faire 2014-10-29 15:55:23 +00:00
parent fefcf7aca6
commit ff6520a89a
1141 changed files with 438491 additions and 94 deletions

View file

@ -0,0 +1,148 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
/** These are important openGL values that aren't defined by default
by the GL headers on various platforms.
*/
enum MissingOpenGLDefinitions
{
#ifndef GL_CLAMP_TO_EDGE
GL_CLAMP_TO_EDGE = 0x812f,
#endif
#ifndef GL_NUM_EXTENSIONS
GL_NUM_EXTENSIONS = 0x821d,
#endif
#ifndef GL_BGRA_EXT
GL_BGRA_EXT = 0x80e1,
#endif
#ifndef GL_DEPTH24_STENCIL8
GL_DEPTH24_STENCIL8 = 0x88F0,
#endif
#ifndef GL_RGBA8
GL_RGBA8 = GL_RGBA,
#endif
#ifndef GL_COLOR_ATTACHMENT0
GL_COLOR_ATTACHMENT0 = 0x8CE0,
#endif
#ifndef GL_DEPTH_ATTACHMENT
GL_DEPTH_ATTACHMENT = 0x8D00,
#endif
#ifndef GL_FRAMEBUFFER
GL_FRAMEBUFFER = 0x8D40,
#endif
#ifndef GL_FRAMEBUFFER_BINDING
GL_FRAMEBUFFER_BINDING = 0x8CA6,
#endif
#ifndef GL_FRAMEBUFFER_COMPLETE
GL_FRAMEBUFFER_COMPLETE = 0x8CD5,
#endif
#ifndef GL_RENDERBUFFER
GL_RENDERBUFFER = 0x8D41,
#endif
#ifndef GL_RENDERBUFFER_DEPTH_SIZE
GL_RENDERBUFFER_DEPTH_SIZE = 0x8D54,
#endif
#ifndef GL_STENCIL_ATTACHMENT
GL_STENCIL_ATTACHMENT = 0x8D20,
#endif
#if JUCE_WINDOWS && ! defined (GL_TEXTURE0)
GL_OPERAND0_RGB = 0x8590,
GL_OPERAND1_RGB = 0x8591,
GL_OPERAND0_ALPHA = 0x8598,
GL_OPERAND1_ALPHA = 0x8599,
GL_SRC0_RGB = 0x8580,
GL_SRC1_RGB = 0x8581,
GL_SRC0_ALPHA = 0x8588,
GL_SRC1_ALPHA = 0x8589,
GL_TEXTURE0 = 0x84C0,
GL_TEXTURE1 = 0x84C1,
GL_TEXTURE2 = 0x84C2,
GL_COMBINE = 0x8570,
GL_COMBINE_RGB = 0x8571,
GL_COMBINE_ALPHA = 0x8572,
GL_PREVIOUS = 0x8578,
GL_COMPILE_STATUS = 0x8B81,
GL_LINK_STATUS = 0x8B82,
GL_SHADING_LANGUAGE_VERSION = 0x8B8C,
GL_FRAGMENT_SHADER = 0x8B30,
GL_VERTEX_SHADER = 0x8B31,
GL_ARRAY_BUFFER = 0x8892,
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
GL_STATIC_DRAW = 0x88E4,
GL_DYNAMIC_DRAW = 0x88E8,
GL_STREAM_DRAW = 0x88E0,
WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000,
WGL_DRAW_TO_WINDOW_ARB = 0x2001,
WGL_ACCELERATION_ARB = 0x2003,
WGL_SWAP_METHOD_ARB = 0x2007,
WGL_SUPPORT_OPENGL_ARB = 0x2010,
WGL_PIXEL_TYPE_ARB = 0x2013,
WGL_DOUBLE_BUFFER_ARB = 0x2011,
WGL_COLOR_BITS_ARB = 0x2014,
WGL_RED_BITS_ARB = 0x2015,
WGL_GREEN_BITS_ARB = 0x2017,
WGL_BLUE_BITS_ARB = 0x2019,
WGL_ALPHA_BITS_ARB = 0x201B,
WGL_DEPTH_BITS_ARB = 0x2022,
WGL_STENCIL_BITS_ARB = 0x2023,
WGL_FULL_ACCELERATION_ARB = 0x2027,
WGL_ACCUM_RED_BITS_ARB = 0x201E,
WGL_ACCUM_GREEN_BITS_ARB = 0x201F,
WGL_ACCUM_BLUE_BITS_ARB = 0x2020,
WGL_ACCUM_ALPHA_BITS_ARB = 0x2021,
WGL_STEREO_ARB = 0x2012,
WGL_SAMPLE_BUFFERS_ARB = 0x2041,
WGL_SAMPLES_ARB = 0x2042,
WGL_TYPE_RGBA_ARB = 0x202B,
WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091,
WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092,
WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126,
#endif
#if JUCE_ANDROID
JUCE_RGBA_FORMAT = GL_RGBA
#else
JUCE_RGBA_FORMAT = GL_BGRA_EXT
#endif
};
#if JUCE_WINDOWS
typedef char GLchar;
typedef pointer_sized_int GLsizeiptr;
typedef pointer_sized_int GLintptr;
#endif

View file

@ -0,0 +1,128 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_OPENGLEXTENSIONS_H_INCLUDED
#define JUCE_OPENGLEXTENSIONS_H_INCLUDED
#if JUCE_MAC && (JUCE_PPC || ((! defined (MAC_OS_X_VERSION_10_6)) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6))
#define JUCE_EXT(func) func ## EXT
#else
#define JUCE_EXT(func) func
#endif
/** @internal This macro contains a list of GL extension functions that need to be dynamically loaded on Windows/Linux.
@see OpenGLExtensionFunctions
*/
#define JUCE_GL_EXTENSION_FUNCTIONS(USE_FUNCTION, EXT_FUNCTION) \
USE_FUNCTION (glActiveTexture, void, (GLenum p1), (p1))\
USE_FUNCTION (glBindBuffer, void, (GLenum p1, GLuint p2), (p1, p2))\
USE_FUNCTION (glDeleteBuffers, void, (GLsizei p1, const GLuint* p2), (p1, p2))\
USE_FUNCTION (glGenBuffers, void, (GLsizei p1, GLuint* p2), (p1, p2))\
USE_FUNCTION (glBufferData, void, (GLenum p1, GLsizeiptr p2, const GLvoid* p3, GLenum p4), (p1, p2, p3, p4))\
USE_FUNCTION (glBufferSubData, void, (GLenum p1, GLintptr p2, GLsizeiptr p3, const GLvoid* p4), (p1, p2, p3, p4))\
EXT_FUNCTION (glIsRenderbuffer, GLboolean, (GLuint p1), (p1))\
EXT_FUNCTION (glBindRenderbuffer, void, (GLenum p1, GLuint p2), (p1, p2))\
EXT_FUNCTION (glDeleteRenderbuffers, void, (GLsizei p1, const GLuint* p2), (p1, p2))\
EXT_FUNCTION (glGenRenderbuffers, void, (GLsizei p1, GLuint* p2), (p1, p2))\
EXT_FUNCTION (glRenderbufferStorage, void, (GLenum p1, GLenum p2, GLsizei p3, GLsizei p4), (p1, p2, p3, p4))\
EXT_FUNCTION (glGetRenderbufferParameteriv, void, (GLenum p1, GLenum p2, GLint* p3), (p1, p2, p3))\
EXT_FUNCTION (glIsFramebuffer, GLboolean, (GLuint p1), (p1))\
EXT_FUNCTION (glBindFramebuffer, void, (GLenum p1, GLuint p2), (p1, p2))\
EXT_FUNCTION (glDeleteFramebuffers, void, (GLsizei p1, const GLuint* p2), (p1, p2))\
EXT_FUNCTION (glGenFramebuffers, void, (GLsizei p1, GLuint* p2), (p1, p2))\
EXT_FUNCTION (glCheckFramebufferStatus, GLenum, (GLenum p1), (p1))\
EXT_FUNCTION (glFramebufferTexture2D, void, (GLenum p1, GLenum p2, GLenum p3, GLuint p4, GLint p5), (p1, p2, p3, p4, p5))\
EXT_FUNCTION (glFramebufferRenderbuffer, void, (GLenum p1, GLenum p2, GLenum p3, GLuint p4), (p1, p2, p3, p4))\
EXT_FUNCTION (glGetFramebufferAttachmentParameteriv, void, (GLenum p1, GLenum p2, GLenum p3, GLint* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glCreateProgram, GLuint, (), ())\
USE_FUNCTION (glDeleteProgram, void, (GLuint p1), (p1))\
USE_FUNCTION (glCreateShader, GLuint, (GLenum p1), (p1))\
USE_FUNCTION (glDeleteShader, void, (GLuint p1), (p1))\
USE_FUNCTION (glShaderSource, void, (GLuint p1, GLsizei p2, const GLchar** p3, const GLint* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glCompileShader, void, (GLuint p1), (p1))\
USE_FUNCTION (glAttachShader, void, (GLuint p1, GLuint p2), (p1, p2))\
USE_FUNCTION (glLinkProgram, void, (GLuint p1), (p1))\
USE_FUNCTION (glUseProgram, void, (GLuint p1), (p1))\
USE_FUNCTION (glGetShaderiv, void, (GLuint p1, GLenum p2, GLint* p3), (p1, p2, p3))\
USE_FUNCTION (glGetShaderInfoLog, void, (GLuint p1, GLsizei p2, GLsizei* p3, GLchar* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glGetProgramInfoLog, void, (GLuint p1, GLsizei p2, GLsizei* p3, GLchar* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glGetProgramiv, void, (GLuint p1, GLenum p2, GLint* p3), (p1, p2, p3))\
USE_FUNCTION (glGetUniformLocation, GLint, (GLuint p1, const GLchar* p2), (p1, p2))\
USE_FUNCTION (glGetAttribLocation, GLint, (GLuint p1, const GLchar* p2), (p1, p2))\
USE_FUNCTION (glVertexAttribPointer, void, (GLuint p1, GLint p2, GLenum p3, GLboolean p4, GLsizei p5, const GLvoid* p6), (p1, p2, p3, p4, p5, p6))\
USE_FUNCTION (glEnableVertexAttribArray, void, (GLuint p1), (p1))\
USE_FUNCTION (glDisableVertexAttribArray, void, (GLuint p1), (p1))\
USE_FUNCTION (glUniform1f, void, (GLint p1, GLfloat p2), (p1, p2))\
USE_FUNCTION (glUniform1i, void, (GLint p1, GLint p2), (p1, p2))\
USE_FUNCTION (glUniform2f, void, (GLint p1, GLfloat p2, GLfloat p3), (p1, p2, p3))\
USE_FUNCTION (glUniform3f, void, (GLint p1, GLfloat p2, GLfloat p3, GLfloat p4), (p1, p2, p3, p4))\
USE_FUNCTION (glUniform4f, void, (GLint p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5), (p1, p2, p3, p4, p5))\
USE_FUNCTION (glUniform4i, void, (GLint p1, GLint p2, GLint p3, GLint p4, GLint p5), (p1, p2, p3, p4, p5))\
USE_FUNCTION (glUniform1fv, void, (GLint p1, GLsizei p2, const GLfloat* p3), (p1, p2, p3))\
USE_FUNCTION (glUniformMatrix2fv, void, (GLint p1, GLsizei p2, GLboolean p3, const GLfloat* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glUniformMatrix3fv, void, (GLint p1, GLsizei p2, GLboolean p3, const GLfloat* p4), (p1, p2, p3, p4))\
USE_FUNCTION (glUniformMatrix4fv, void, (GLint p1, GLsizei p2, GLboolean p3, const GLfloat* p4), (p1, p2, p3, p4))
/** This class contains a generated list of OpenGL extension functions, which are either dynamically loaded
for a specific GL context, or simply call-through to the appropriate OS function where available.
*/
struct OpenGLExtensionFunctions
{
void initialise();
#if JUCE_WINDOWS && ! DOXYGEN
typedef char GLchar;
typedef pointer_sized_int GLsizeiptr;
typedef pointer_sized_int GLintptr;
#endif
//==============================================================================
#if JUCE_WINDOWS
#define JUCE_DECLARE_GL_FUNCTION(name, returnType, params, callparams) typedef returnType (__stdcall *type_ ## name) params; type_ ## name name;
JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION, JUCE_DECLARE_GL_FUNCTION)
//==============================================================================
#elif JUCE_LINUX
#define JUCE_DECLARE_GL_FUNCTION(name, returnType, params, callparams) typedef returnType (*type_ ## name) params; type_ ## name name;
JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION, JUCE_DECLARE_GL_FUNCTION)
//==============================================================================
#elif JUCE_OPENGL_ES
#define JUCE_DECLARE_GL_FUNCTION(name, returnType, params, callparams) static returnType name params;
JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION, JUCE_DECLARE_GL_FUNCTION)
//==============================================================================
#else
#define JUCE_DECLARE_GL_FUNCTION(name, returnType, params, callparams) inline static returnType name params { return ::name callparams; }
#if JUCE_OPENGL3
JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION, JUCE_DECLARE_GL_FUNCTION)
#else
#define JUCE_DECLARE_GL_FUNCTION_EXT(name, returnType, params, callparams) inline static returnType name params { return ::name ## EXT callparams; }
JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION, JUCE_DECLARE_GL_FUNCTION_EXT)
#undef JUCE_DECLARE_GL_FUNCTION_EXT
#endif
#endif
#undef JUCE_DECLARE_GL_FUNCTION
};
#endif // JUCE_OPENGLEXTENSIONS_H_INCLUDED

View file

@ -0,0 +1,182 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (layout, "layout", "(IIII)V") \
METHOD (requestRender, "requestRender", "()V") \
DECLARE_JNI_CLASS (OpenGLView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView");
#undef JNI_CLASS_MEMBERS
extern jobject createOpenGLView (ComponentPeer*);
//==============================================================================
class OpenGLContext::NativeContext
{
public:
NativeContext (Component& comp,
const OpenGLPixelFormat& pixelFormat,
void* /*contextToShareWith*/,
bool /*useMultisampling*/,
OpenGLVersion)
: component (comp),
isInsideGLCallback (false)
{
{
const ScopedLock sl (contextListLock);
glView = GlobalRef (createOpenGLView (component.getPeer()));
contextList.add (this);
}
updateWindowPosition (component.getTopLevelComponent()
->getLocalArea (&component, component.getLocalBounds()));
}
~NativeContext()
{
{
const ScopedLock sl (contextListLock);
contextList.removeFirstMatchingValue (this);
}
android.activity.callVoidMethod (JuceAppActivity.deleteView, glView.get());
glView.clear();
}
void initialiseOnRenderThread (OpenGLContext&) {}
void shutdownOnRenderThread() {}
bool makeActive() const noexcept { return isInsideGLCallback; }
bool isActive() const noexcept { return isInsideGLCallback; }
static void deactivateCurrentContext() {}
void swapBuffers() const noexcept {}
bool setSwapInterval (const int) { return false; }
int getSwapInterval() const { return 0; }
bool createdOk() const noexcept { return getRawContext() != nullptr; }
void* getRawContext() const noexcept { return glView.get(); }
GLuint getFrameBufferID() const noexcept { return 0; }
void updateWindowPosition (const Rectangle<int>& bounds)
{
if (lastBounds != bounds)
{
lastBounds = bounds;
glView.callVoidMethod (OpenGLView.layout,
bounds.getX(), bounds.getY(),
bounds.getRight(), bounds.getBottom());
}
}
void triggerRepaint()
{
glView.callVoidMethod (OpenGLView.requestRender);
}
//==============================================================================
void contextCreatedCallback();
void contextChangedSize() {}
void renderCallback();
//==============================================================================
static NativeContext* findContextFor (JNIEnv* env, jobject glView)
{
const ScopedLock sl (contextListLock);
for (int i = contextList.size(); --i >= 0;)
{
NativeContext* const c = contextList.getUnchecked(i);
if (env->IsSameObject (c->glView.get(), glView))
return c;
}
return nullptr;
}
static NativeContext* getActiveContext() noexcept
{
const ScopedLock sl (contextListLock);
for (int i = contextList.size(); --i >= 0;)
{
NativeContext* const c = contextList.getUnchecked(i);
if (c->isInsideGLCallback)
return c;
}
return nullptr;
}
struct Locker { Locker (NativeContext&) {} };
Component& component;
private:
GlobalRef glView;
Rectangle<int> lastBounds;
bool isInsideGLCallback;
typedef Array<NativeContext*> ContextArray;
static CriticalSection contextListLock;
static ContextArray contextList;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
};
CriticalSection OpenGLContext::NativeContext::contextListLock;
OpenGLContext::NativeContext::ContextArray OpenGLContext::NativeContext::contextList;
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return OpenGLContext::NativeContext::getActiveContext() != nullptr;
}
//==============================================================================
#define GL_VIEW_CLASS_NAME JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024OpenGLView)
JUCE_JNI_CALLBACK (GL_VIEW_CLASS_NAME, contextCreated, void, (JNIEnv* env, jobject view))
{
threadLocalJNIEnvHolder.getOrAttach();
if (OpenGLContext::NativeContext* const context = OpenGLContext::NativeContext::findContextFor (env, view))
context->contextCreatedCallback();
else
jassertfalse;
}
JUCE_JNI_CALLBACK (GL_VIEW_CLASS_NAME, contextChangedSize, void, (JNIEnv* env, jobject view))
{
if (OpenGLContext::NativeContext* const context = OpenGLContext::NativeContext::findContextFor (env, view))
context->contextChangedSize();
}
JUCE_JNI_CALLBACK (GL_VIEW_CLASS_NAME, render, void, (JNIEnv* env, jobject view))
{
if (OpenGLContext::NativeContext* const context = OpenGLContext::NativeContext::findContextFor (env, view))
context->renderCallback();
}

View file

@ -0,0 +1,294 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
} // (juce namespace)
@interface JuceGLView : UIView
{
}
+ (Class) layerClass;
@end
@implementation JuceGLView
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
@end
namespace juce
{
class OpenGLContext::NativeContext
{
public:
NativeContext (Component& component,
const OpenGLPixelFormat& pixFormat,
void* contextToShare,
bool multisampling,
OpenGLVersion version)
: context (nil), frameBufferHandle (0), colorBufferHandle (0),
depthBufferHandle (0), msaaColorHandle (0), msaaBufferHandle (0),
lastWidth (0), lastHeight (0), needToRebuildBuffers (false),
swapFrames (0), useDepthBuffer (pixFormat.depthBufferBits > 0),
useMSAA (multisampling)
{
JUCE_AUTORELEASEPOOL
{
ComponentPeer* const peer = component.getPeer();
jassert (peer != nullptr);
const Rectangle<int> bounds (peer->getComponent().getLocalArea (&component, component.getLocalBounds()));
lastWidth = bounds.getWidth();
lastHeight = bounds.getHeight();
view = [[JuceGLView alloc] initWithFrame: convertToCGRect (bounds)];
view.opaque = YES;
view.hidden = NO;
view.backgroundColor = [UIColor blackColor];
view.userInteractionEnabled = NO;
glLayer = (CAEAGLLayer*) [view layer];
glLayer.contentsScale = Desktop::getInstance().getDisplays().getMainDisplay().scale;
glLayer.opaque = true;
[((UIView*) peer->getNativeHandle()) addSubview: view];
#if defined (__IPHONE_7_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
if (version == OpenGLContext::openGL3_2 && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0)
{
if (! createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))
{
releaseContext();
createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);
}
}
else
#endif
{
createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);
}
jassert (context != nil);
// I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing
// so causes myserious timing-related failures.
[EAGLContext setCurrentContext: context];
createGLBuffers();
deactivateCurrentContext();
}
}
~NativeContext()
{
releaseContext();
[view removeFromSuperview];
[view release];
}
void initialiseOnRenderThread (OpenGLContext&) {}
void shutdownOnRenderThread()
{
JUCE_CHECK_OPENGL_ERROR
freeGLBuffers();
deactivateCurrentContext();
}
bool createdOk() const noexcept { return getRawContext() != nullptr; }
void* getRawContext() const noexcept { return context; }
GLuint getFrameBufferID() const noexcept { return useMSAA ? msaaBufferHandle : frameBufferHandle; }
bool makeActive() const noexcept
{
if (! [EAGLContext setCurrentContext: context])
return false;
glBindFramebuffer (GL_FRAMEBUFFER, useMSAA ? msaaBufferHandle
: frameBufferHandle);
return true;
}
bool isActive() const noexcept
{
return [EAGLContext currentContext] == context;
}
static void deactivateCurrentContext()
{
[EAGLContext setCurrentContext: nil];
}
void swapBuffers()
{
if (useMSAA)
{
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, frameBufferHandle);
glBindFramebuffer (GL_READ_FRAMEBUFFER, msaaBufferHandle);
#if defined (__IPHONE_7_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
glBlitFramebuffer (0, 0, lastWidth, lastHeight, 0, 0, lastWidth, lastHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
#else
glResolveMultisampleFramebufferAPPLE();
#endif
}
glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
[context presentRenderbuffer: GL_RENDERBUFFER];
if (needToRebuildBuffers)
{
needToRebuildBuffers = false;
freeGLBuffers();
createGLBuffers();
makeActive();
}
}
void updateWindowPosition (const Rectangle<int>& bounds)
{
view.frame = convertToCGRect (bounds);
if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
{
lastWidth = bounds.getWidth();
lastHeight = bounds.getHeight();
needToRebuildBuffers = true;
}
}
bool setSwapInterval (const int numFramesPerSwap) noexcept
{
swapFrames = numFramesPerSwap;
return false;
}
int getSwapInterval() const noexcept { return swapFrames; }
struct Locker { Locker (NativeContext&) {} };
private:
JuceGLView* view;
CAEAGLLayer* glLayer;
EAGLContext* context;
GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle,
msaaColorHandle, msaaBufferHandle;
int volatile lastWidth, lastHeight;
bool volatile needToRebuildBuffers;
int swapFrames;
bool useDepthBuffer, useMSAA;
bool createContext (EAGLRenderingAPI type, void* contextToShare)
{
jassert (context == nil);
context = [EAGLContext alloc];
context = contextToShare != nullptr
? [context initWithAPI: type sharegroup: [(EAGLContext*) contextToShare sharegroup]]
: [context initWithAPI: type];
return context != nil;
}
void releaseContext()
{
[context release];
context = nil;
}
//==============================================================================
void createGLBuffers()
{
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;
GLint width, height;
glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
if (useMSAA)
{
glGenFramebuffers (1, &msaaBufferHandle);
glGenRenderbuffers (1, &msaaColorHandle);
glBindFramebuffer (GL_FRAMEBUFFER, msaaBufferHandle);
glBindRenderbuffer (GL_RENDERBUFFER, msaaColorHandle);
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_RGBA8, width, height);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColorHandle);
}
if (useDepthBuffer)
{
glGenRenderbuffers (1, &depthBufferHandle);
glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle);
if (useMSAA)
glRenderbufferStorageMultisample (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
}
void freeGLBuffers()
{
JUCE_CHECK_OPENGL_ERROR
[context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];
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)
};
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return [EAGLContext currentContext] != nil;
}

View file

@ -0,0 +1,195 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
extern Display* display;
extern XContext windowHandleXContext;
//==============================================================================
class OpenGLContext::NativeContext
{
public:
NativeContext (Component& component,
const OpenGLPixelFormat& pixelFormat,
void* shareContext,
bool /*useMultisampling*/,
OpenGLVersion)
: renderContext (0), embeddedWindow (0), swapFrames (0), bestVisual (0),
contextToShareWith (shareContext)
{
ScopedXLock xlock;
XSync (display, False);
GLint attribs[] =
{
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, pixelFormat.redBits,
GLX_GREEN_SIZE, pixelFormat.greenBits,
GLX_BLUE_SIZE, pixelFormat.blueBits,
GLX_ALPHA_SIZE, pixelFormat.alphaBits,
GLX_DEPTH_SIZE, pixelFormat.depthBufferBits,
GLX_STENCIL_SIZE, pixelFormat.stencilBufferBits,
GLX_ACCUM_RED_SIZE, pixelFormat.accumulationBufferRedBits,
GLX_ACCUM_GREEN_SIZE, pixelFormat.accumulationBufferGreenBits,
GLX_ACCUM_BLUE_SIZE, pixelFormat.accumulationBufferBlueBits,
GLX_ACCUM_ALPHA_SIZE, pixelFormat.accumulationBufferAlphaBits,
None
};
bestVisual = glXChooseVisual (display, DefaultScreen (display), attribs);
if (bestVisual == nullptr)
return;
ComponentPeer* const peer = component.getPeer();
Window windowH = (Window) peer->getNativeHandle();
Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone);
XSetWindowAttributes swa;
swa.colormap = colourMap;
swa.border_pixel = 0;
swa.event_mask = ExposureMask | StructureNotifyMask;
const Rectangle<int> bounds (component.getTopLevelComponent()
->getLocalArea (&component, component.getLocalBounds()));
embeddedWindow = XCreateWindow (display, windowH,
bounds.getX(), bounds.getY(),
jmax (1, bounds.getWidth()),
jmax (1, bounds.getHeight()),
0, bestVisual->depth,
InputOutput,
bestVisual->visual,
CWBorderPixel | CWColormap | CWEventMask,
&swa);
XSaveContext (display, (XID) embeddedWindow, windowHandleXContext, (XPointer) peer);
XMapWindow (display, embeddedWindow);
XFreeColormap (display, colourMap);
XSync (display, False);
}
~NativeContext()
{
if (embeddedWindow != 0)
{
ScopedXLock xlock;
XUnmapWindow (display, embeddedWindow);
XDestroyWindow (display, embeddedWindow);
}
if (bestVisual != nullptr)
XFree (bestVisual);
}
void initialiseOnRenderThread (OpenGLContext& context)
{
ScopedXLock xlock;
renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE);
context.makeActive();
}
void shutdownOnRenderThread()
{
deactivateCurrentContext();
glXDestroyContext (display, renderContext);
renderContext = nullptr;
}
bool makeActive() const noexcept
{
return renderContext != 0
&& glXMakeCurrent (display, embeddedWindow, renderContext);
}
bool isActive() const noexcept
{
return glXGetCurrentContext() == renderContext && renderContext != 0;
}
static void deactivateCurrentContext()
{
glXMakeCurrent (display, None, 0);
}
void swapBuffers()
{
glXSwapBuffers (display, embeddedWindow);
}
void updateWindowPosition (const Rectangle<int>& newBounds)
{
bounds = newBounds;
ScopedXLock xlock;
XMoveResizeWindow (display, embeddedWindow,
bounds.getX(), bounds.getY(),
jmax (1, bounds.getWidth()),
jmax (1, bounds.getHeight()));
}
bool setSwapInterval (int numFramesPerSwap)
{
if (numFramesPerSwap == swapFrames)
return true;
PFNGLXSWAPINTERVALSGIPROC GLXSwapIntervalSGI
= (PFNGLXSWAPINTERVALSGIPROC) OpenGLHelpers::getExtensionFunction ("glXSwapIntervalSGI");
if (GLXSwapIntervalSGI != nullptr)
{
swapFrames = numFramesPerSwap;
GLXSwapIntervalSGI (numFramesPerSwap);
return true;
}
return false;
}
int getSwapInterval() const { return swapFrames; }
bool createdOk() const noexcept { return true; }
void* getRawContext() const noexcept { return renderContext; }
GLuint getFrameBufferID() const noexcept { return 0; }
struct Locker { Locker (NativeContext&) {} };
private:
GLXContext renderContext;
Window embeddedWindow;
int swapFrames;
Rectangle<int> bounds;
XVisualInfo* bestVisual;
void* contextToShareWith;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
};
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
ScopedXLock xlock;
return glXGetCurrentContext() != 0;
}

View file

@ -0,0 +1,225 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
class OpenGLContext::NativeContext
{
public:
NativeContext (Component& component,
const OpenGLPixelFormat& pixFormat,
void* contextToShare,
bool /*useMultisampling*/,
OpenGLVersion version)
: lastSwapTime (0), minSwapTimeMs (0), underrunCounter (0)
{
(void) version;
NSOpenGLPixelFormatAttribute attribs[] =
{
#if JUCE_OPENGL3
NSOpenGLPFAOpenGLProfile, version >= openGL3_2 ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy,
#endif
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAClosestPolicy,
NSOpenGLPFANoRecovery,
NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) (pixFormat.redBits + pixFormat.greenBits + pixFormat.blueBits),
NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) pixFormat.alphaBits,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) pixFormat.depthBufferBits,
NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute) pixFormat.stencilBufferBits,
NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) (pixFormat.accumulationBufferRedBits + pixFormat.accumulationBufferGreenBits
+ pixFormat.accumulationBufferBlueBits + pixFormat.accumulationBufferAlphaBits),
pixFormat.multisamplingLevel > 0 ? NSOpenGLPFASamples : (NSOpenGLPixelFormatAttribute) 0,
(NSOpenGLPixelFormatAttribute) pixFormat.multisamplingLevel,
0
};
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
static MouseForwardingNSOpenGLViewClass cls;
view = [cls.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
#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:)
name: NSViewGlobalFrameDidChangeNotification
object: view];
renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
shareContext: (NSOpenGLContext*) contextToShare] autorelease];
[view setOpenGLContext: renderContext];
[format release];
viewAttachment = NSViewComponent::attachViewToComponent (component, view);
}
~NativeContext()
{
[[NSNotificationCenter defaultCenter] removeObserver: view];
[renderContext clearDrawable];
[renderContext setView: nil];
[view setOpenGLContext: nil];
renderContext = nil;
}
void initialiseOnRenderThread (OpenGLContext&) {}
void shutdownOnRenderThread() { deactivateCurrentContext(); }
bool createdOk() const noexcept { return getRawContext() != nullptr; }
void* getRawContext() const noexcept { return static_cast <void*> (renderContext); }
GLuint getFrameBufferID() const noexcept { return 0; }
bool makeActive() const noexcept
{
jassert (renderContext != nil);
if ([renderContext view] != view)
[renderContext setView: view];
if (NSOpenGLContext* context = [view openGLContext])
{
[context makeCurrentContext];
return true;
}
return false;
}
bool isActive() const noexcept
{
return [NSOpenGLContext currentContext] == renderContext;
}
static void deactivateCurrentContext()
{
[NSOpenGLContext clearCurrentContext];
}
struct Locker
{
Locker (NativeContext& nc) : cglContext ((CGLContextObj) [nc.renderContext CGLContextObj])
{
CGLLockContext (cglContext);
}
~Locker()
{
CGLUnlockContext (cglContext);
}
private:
CGLContextObj cglContext;
};
void swapBuffers()
{
[renderContext flushBuffer];
sleepIfRenderingTooFast();
}
void updateWindowPosition (const Rectangle<int>&) {}
bool setSwapInterval (int numFramesPerSwap)
{
minSwapTimeMs = (numFramesPerSwap * 1000) / 60;
[renderContext setValues: (const GLint*) &numFramesPerSwap
forParameter: NSOpenGLCPSwapInterval];
return true;
}
int getSwapInterval() const
{
GLint numFrames = 0;
[renderContext getValues: &numFrames
forParameter: NSOpenGLCPSwapInterval];
return numFrames;
}
void sleepIfRenderingTooFast()
{
// When our window is entirely occluded by other windows, the system
// fails to correctly implement the swap interval time, so the render
// loop spins at full speed, burning CPU. This hack detects when things
// are going too fast and slows things down if necessary.
if (minSwapTimeMs > 0)
{
const double now = Time::getMillisecondCounterHiRes();
const int elapsed = (int) (now - lastSwapTime);
lastSwapTime = now;
if (isPositiveAndBelow (elapsed, minSwapTimeMs - 3))
{
if (underrunCounter > 3)
Thread::sleep (minSwapTimeMs - elapsed);
else
++underrunCounter;
}
else
{
underrunCounter = 0;
}
}
}
NSOpenGLContext* renderContext;
NSOpenGLView* view;
ReferenceCountedObjectPtr<ReferenceCountedObject> viewAttachment;
double lastSwapTime;
int minSwapTimeMs, underrunCounter;
//==============================================================================
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)
};
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return CGLGetCurrentContext() != 0;
}

View file

@ -0,0 +1,266 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
extern ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component&, void* parent);
//==============================================================================
class OpenGLContext::NativeContext
{
public:
NativeContext (Component& component,
const OpenGLPixelFormat& pixelFormat,
void* contextToShareWith,
bool /*useMultisampling*/,
OpenGLVersion)
: context (nullptr)
{
dummyComponent = new DummyComponent (*this);
createNativeWindow (component);
PIXELFORMATDESCRIPTOR pfd;
initialisePixelFormatDescriptor (pfd, pixelFormat);
const int pixFormat = ChoosePixelFormat (dc, &pfd);
if (pixFormat != 0)
SetPixelFormat (dc, pixFormat, &pfd);
renderContext = wglCreateContext (dc);
if (renderContext != 0)
{
makeActive();
initialiseGLExtensions();
const int wglFormat = wglChoosePixelFormatExtension (pixelFormat);
deactivateCurrentContext();
if (wglFormat != pixFormat && wglFormat != 0)
{
// can't change the pixel format of a window, so need to delete the
// old one and create a new one..
releaseDC();
nativeWindow = nullptr;
createNativeWindow (component);
if (SetPixelFormat (dc, wglFormat, &pfd))
{
deleteRenderContext();
renderContext = wglCreateContext (dc);
}
}
if (contextToShareWith != nullptr)
wglShareLists ((HGLRC) contextToShareWith, renderContext);
component.getTopLevelComponent()->repaint();
component.repaint();
}
}
~NativeContext()
{
deleteRenderContext();
releaseDC();
}
void initialiseOnRenderThread (OpenGLContext& c) { context = &c; }
void shutdownOnRenderThread() { deactivateCurrentContext(); context = nullptr; }
static void deactivateCurrentContext() { wglMakeCurrent (0, 0); }
bool makeActive() const noexcept { return isActive() || wglMakeCurrent (dc, renderContext) != FALSE; }
bool isActive() const noexcept { return wglGetCurrentContext() == renderContext; }
void swapBuffers() const noexcept { SwapBuffers (dc); }
bool setSwapInterval (int numFramesPerSwap)
{
jassert (isActive()); // this can only be called when the context is active..
return wglSwapIntervalEXT != nullptr && wglSwapIntervalEXT (numFramesPerSwap) != FALSE;
}
int getSwapInterval() const
{
jassert (isActive()); // this can only be called when the context is active..
return wglGetSwapIntervalEXT != nullptr ? wglGetSwapIntervalEXT() : 0;
}
void updateWindowPosition (const Rectangle<int>& bounds)
{
if (nativeWindow != nullptr)
SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0,
bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
bool createdOk() const noexcept { return getRawContext() != nullptr; }
void* getRawContext() const noexcept { return renderContext; }
unsigned int getFrameBufferID() const noexcept { return 0; }
void triggerRepaint()
{
if (context != nullptr)
context->triggerRepaint();
}
struct Locker { Locker (NativeContext&) {} };
private:
struct DummyComponent : public Component
{
DummyComponent (NativeContext& c) : context (c) {}
// The windowing code will call this when a paint callback happens
void handleCommandMessage (int) override { context.triggerRepaint(); }
NativeContext& context;
};
ScopedPointer<DummyComponent> dummyComponent;
ScopedPointer<ComponentPeer> nativeWindow;
HGLRC renderContext;
HDC dc;
OpenGLContext* context;
#define JUCE_DECLARE_WGL_EXTENSION_FUNCTION(name, returnType, params) \
typedef returnType (__stdcall *type_ ## name) params; type_ ## name name;
JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglChoosePixelFormatARB, BOOL, (HDC, const int*, const FLOAT*, UINT, int*, UINT*))
JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglSwapIntervalEXT, BOOL, (int))
JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglGetSwapIntervalEXT, int, ())
#undef JUCE_DECLARE_WGL_EXTENSION_FUNCTION
void initialiseGLExtensions()
{
#define JUCE_INIT_WGL_FUNCTION(name) name = (type_ ## name) OpenGLHelpers::getExtensionFunction (#name);
JUCE_INIT_WGL_FUNCTION (wglChoosePixelFormatARB);
JUCE_INIT_WGL_FUNCTION (wglSwapIntervalEXT);
JUCE_INIT_WGL_FUNCTION (wglGetSwapIntervalEXT);
#undef JUCE_INIT_WGL_FUNCTION
}
void createNativeWindow (Component& component)
{
Component* topComp = component.getTopLevelComponent();
nativeWindow = createNonRepaintingEmbeddedWindowsPeer (*dummyComponent, topComp->getWindowHandle());
if (ComponentPeer* peer = topComp->getPeer())
updateWindowPosition (peer->getAreaCoveredBy (component));
nativeWindow->setVisible (true);
dc = GetDC ((HWND) nativeWindow->getNativeHandle());
}
void deleteRenderContext()
{
if (renderContext != 0)
{
wglDeleteContext (renderContext);
renderContext = 0;
}
}
void releaseDC()
{
ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc);
}
static void initialisePixelFormatDescriptor (PIXELFORMATDESCRIPTOR& pfd, const OpenGLPixelFormat& pixelFormat)
{
zerostruct (pfd);
pfd.nSize = sizeof (pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cColorBits = (BYTE) (pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits);
pfd.cRedBits = (BYTE) pixelFormat.redBits;
pfd.cGreenBits = (BYTE) pixelFormat.greenBits;
pfd.cBlueBits = (BYTE) pixelFormat.blueBits;
pfd.cAlphaBits = (BYTE) pixelFormat.alphaBits;
pfd.cDepthBits = (BYTE) pixelFormat.depthBufferBits;
pfd.cStencilBits = (BYTE) pixelFormat.stencilBufferBits;
pfd.cAccumBits = (BYTE) (pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits
+ pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits);
pfd.cAccumRedBits = (BYTE) pixelFormat.accumulationBufferRedBits;
pfd.cAccumGreenBits = (BYTE) pixelFormat.accumulationBufferGreenBits;
pfd.cAccumBlueBits = (BYTE) pixelFormat.accumulationBufferBlueBits;
pfd.cAccumAlphaBits = (BYTE) pixelFormat.accumulationBufferAlphaBits;
}
int wglChoosePixelFormatExtension (const OpenGLPixelFormat& pixelFormat) const
{
int format = 0;
if (wglChoosePixelFormatARB != nullptr)
{
int atts[64];
int n = 0;
atts[n++] = WGL_DRAW_TO_WINDOW_ARB; atts[n++] = GL_TRUE;
atts[n++] = WGL_SUPPORT_OPENGL_ARB; atts[n++] = GL_TRUE;
atts[n++] = WGL_DOUBLE_BUFFER_ARB; atts[n++] = GL_TRUE;
atts[n++] = WGL_PIXEL_TYPE_ARB; atts[n++] = WGL_TYPE_RGBA_ARB;
atts[n++] = WGL_ACCELERATION_ARB;
atts[n++] = WGL_FULL_ACCELERATION_ARB;
atts[n++] = WGL_COLOR_BITS_ARB; atts[n++] = pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits;
atts[n++] = WGL_RED_BITS_ARB; atts[n++] = pixelFormat.redBits;
atts[n++] = WGL_GREEN_BITS_ARB; atts[n++] = pixelFormat.greenBits;
atts[n++] = WGL_BLUE_BITS_ARB; atts[n++] = pixelFormat.blueBits;
atts[n++] = WGL_ALPHA_BITS_ARB; atts[n++] = pixelFormat.alphaBits;
atts[n++] = WGL_DEPTH_BITS_ARB; atts[n++] = pixelFormat.depthBufferBits;
atts[n++] = WGL_STENCIL_BITS_ARB; atts[n++] = pixelFormat.stencilBufferBits;
atts[n++] = WGL_ACCUM_RED_BITS_ARB; atts[n++] = pixelFormat.accumulationBufferRedBits;
atts[n++] = WGL_ACCUM_GREEN_BITS_ARB; atts[n++] = pixelFormat.accumulationBufferGreenBits;
atts[n++] = WGL_ACCUM_BLUE_BITS_ARB; atts[n++] = pixelFormat.accumulationBufferBlueBits;
atts[n++] = WGL_ACCUM_ALPHA_BITS_ARB; atts[n++] = pixelFormat.accumulationBufferAlphaBits;
if (pixelFormat.multisamplingLevel > 0
&& OpenGLHelpers::isExtensionSupported ("GL_ARB_multisample"))
{
atts[n++] = WGL_SAMPLE_BUFFERS_ARB;
atts[n++] = 1;
atts[n++] = WGL_SAMPLES_ARB;
atts[n++] = pixelFormat.multisamplingLevel;
}
atts[n++] = 0;
jassert (n <= numElementsInArray (atts));
UINT formatsCount = 0;
wglChoosePixelFormatARB (dc, atts, nullptr, 1, &format, &formatsCount);
}
return format;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
};
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return wglGetCurrentContext() != 0;
}