Browse Source

tags/2021-05-28
jules 18 years ago
parent
commit
73257b4f4f
9 changed files with 1049 additions and 435 deletions
  1. +133
    -91
      build/linux/platform_specific_code/juce_linux_Windowing.cpp
  2. +155
    -57
      build/macosx/platform_specific_code/juce_mac_Windowing.cpp
  3. +400
    -95
      build/win32/platform_specific_code/juce_win32_Windowing.cpp
  4. +1
    -0
      docs/JUCE changelist.txt
  5. +2
    -2
      extras/juce demo/build/linux/JuceDemo.make
  6. +2
    -2
      extras/juce demo/build/linux/jucedemo_premake.lua
  7. +26
    -0
      extras/juce demo/src/demos/OpenGLDemo.cpp
  8. +144
    -158
      src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp
  9. +186
    -30
      src/juce_appframework/gui/components/special/juce_OpenGLComponent.h

+ 133
- 91
build/linux/platform_specific_code/juce_linux_Windowing.cpp View File

@@ -2795,59 +2795,70 @@ Image* juce_createIconForFile (const File& file)
//==============================================================================
#if JUCE_OPENGL
struct OpenGLContextInfo
{
Window embeddedWindow;
GLXContext renderContext;
};
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
//==============================================================================
class WindowedGLContext : public OpenGLContext
{
XSync (display, False);
jassert (component != 0);
if (component == 0)
return 0;
LinuxComponentPeer* const peer
= dynamic_cast <LinuxComponentPeer*> (component->getTopLevelComponent()->getPeer());
if (peer == 0)
return 0;
GLint attribList[] =
{
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 8,
None
};
XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribList);
public:
WindowedGLContext (Component* const component,
const OpenGLPixelFormat& pixelFormat_,
GLXContext sharedContext)
: renderContext (0),
embeddedWindow (0),
pixelFormat (pixelFormat_)
{
jassert (component != 0);
LinuxComponentPeer* const peer = dynamic_cast <LinuxComponentPeer*> (component->getTopLevelComponent()->getPeer());
if (peer == 0)
return;
if (bestVisual == 0)
return 0;
XSync (display, False);
OpenGLContextInfo* const oc = new OpenGLContextInfo();
GLint attribs [64];
int n = 0;
attribs[n++] = GLX_RGBA;
attribs[n++] = GLX_DOUBLEBUFFER;
attribs[n++] = GLX_RED_SIZE;
attribs[n++] = pixelFormat.redBits;
attribs[n++] = GLX_GREEN_SIZE;
attribs[n++] = pixelFormat.greenBits;
attribs[n++] = GLX_BLUE_SIZE;
attribs[n++] = pixelFormat.blueBits;
attribs[n++] = GLX_ALPHA_SIZE;
attribs[n++] = pixelFormat.alphaBits;
attribs[n++] = GLX_DEPTH_SIZE;
attribs[n++] = pixelFormat.depthBufferBits;
attribs[n++] = GLX_STENCIL_SIZE;
attribs[n++] = pixelFormat.stencilBufferBits;
attribs[n++] = GLX_ACCUM_RED_SIZE;
attribs[n++] = pixelFormat.accumulationBufferRedBits;
attribs[n++] = GLX_ACCUM_GREEN_SIZE;
attribs[n++] = pixelFormat.accumulationBufferGreenBits;
attribs[n++] = GLX_ACCUM_BLUE_SIZE;
attribs[n++] = pixelFormat.accumulationBufferBlueBits;
attribs[n++] = GLX_ACCUM_ALPHA_SIZE;
attribs[n++] = pixelFormat.accumulationBufferAlphaBits;
// xxx not sure how to do fullSceneAntiAliasingNumSamples on linux..
attribs[n++] = None;
XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribs);
if (bestVisual == 0)
return;
oc->renderContext = glXCreateContext (display, bestVisual,
(sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext
: 0,
GL_TRUE);
renderContext = glXCreateContext (display, bestVisual, sharedContext, GL_TRUE);
Window windowH = (Window) peer->getNativeHandle();
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;
Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone);
XSetWindowAttributes swa;
swa.colormap = colourMap;
swa.border_pixel = 0;
swa.event_mask = ExposureMask | StructureNotifyMask;
oc->embeddedWindow = XCreateWindow (display, windowH,
embeddedWindow = XCreateWindow (display, windowH,
0, 0, 1, 1, 0,
bestVisual->depth,
InputOutput,
@@ -2855,73 +2866,104 @@ void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
CWBorderPixel | CWColormap | CWEventMask,
&swa);
XSaveContext (display, (XID) oc->embeddedWindow, improbableNumber, (XPointer) peer);
XSaveContext (display, (XID) embeddedWindow, improbableNumber, (XPointer) peer);
XMapWindow (display, oc->embeddedWindow);
XFreeColormap (display, colourMap);
XMapWindow (display, embeddedWindow);
XFreeColormap (display, colourMap);
XFree (bestVisual);
XSync (display, False);
XFree (bestVisual);
XSync (display, False);
}
return oc;
}
~WindowedGLContext()
{
makeInactive();
void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp)
{
jassert (context != 0);
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
XMoveResizeWindow (display, oc->embeddedWindow,
owner->getScreenX() - topComp->getScreenX(),
owner->getScreenY() - topComp->getScreenY(),
jmax (1, owner->getWidth()),
jmax (1, owner->getHeight()));
}
glXDestroyContext (display, renderContext);
void juce_deleteOpenGLContext (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
XUnmapWindow (display, embeddedWindow);
XDestroyWindow (display, embeddedWindow);
}
if (oc != 0)
bool makeActive() throw()
{
glXDestroyContext (display, oc->renderContext);
jassert (renderContext != 0);
XUnmapWindow (display, oc->embeddedWindow);
XDestroyWindow (display, oc->embeddedWindow);
return glXMakeCurrent (display, embeddedWindow, renderContext)
&& XSync (display, False);
}
delete oc;
bool makeInactive() throw()
{
return (! isActive()) || glXMakeCurrent (display, None, 0);
}
}
bool juce_makeOpenGLContextCurrent (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
bool isActive() const throw()
{
return glXGetCurrentContext() == renderContext;
}
if (oc != 0)
return glXMakeCurrent (display, oc->embeddedWindow, oc->renderContext)
&& XSync (display, False);
else
return glXMakeCurrent (display, None, 0);
}
const OpenGLPixelFormat getPixelFormat() const
{
return pixelFormat;
}
bool juce_isActiveOpenGLContext (void* context) throw()
void* getRawContext() const throw()
{
return renderContext;
}
void updateWindowPosition (int x, int y, int w, int h, int)
{
XMoveResizeWindow (display, embeddedWindow,
x, y, jmax (1, w), jmax (1, h));
}
void swapBuffers()
{
glXSwapBuffers (display, embeddedWindow);
}
void repaint()
{
}
//==============================================================================
juce_UseDebuggingNewOperator
GLXContext renderContext;
private:
Window embeddedWindow;
OpenGLPixelFormat pixelFormat;
//==============================================================================
WindowedGLContext (const WindowedGLContext&);
const WindowedGLContext& operator= (const WindowedGLContext&);
};
//==============================================================================
OpenGLContext* OpenGLContext::createContextForWindow (Component* const component,
const OpenGLPixelFormat& pixelFormat,
const OpenGLContext* const contextToShareWith)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
WindowedGLContext* c = new WindowedGLContext (component, pixelFormat,
contextToShareWith != 0 ? (GLXContext) contextToShareWith->getRawContext() : 0);
jassert (oc != 0);
return glXGetCurrentContext() == oc->renderContext;
if (c->renderContext == 0)
deleteAndZero (c);
return c;
}
void juce_swapOpenGLBuffers (void* context)
void juce_glViewport (const int w, const int h)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
if (oc != 0)
glXSwapBuffers (display, oc->embeddedWindow);
glViewport (0, 0, w, h);
}
void juce_repaintOpenGLWindow (void* context)
void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
results.add (new OpenGLPixelFormat()); // xxx
}
#endif


+ 155
- 57
build/macosx/platform_specific_code/juce_mac_Windowing.cpp View File

@@ -3292,93 +3292,191 @@ void AppleRemoteDevice::handleCallbackInternal()
//==============================================================================
#if JUCE_OPENGL
struct OpenGLContextInfo
//==============================================================================
class WindowedGLContext : public OpenGLContext
{
AGLContext renderContext;
};
public:
WindowedGLContext (Component* const component,
const OpenGLPixelFormat& pixelFormat_,
AGLContext sharedContext)
: renderContext (0),
pixelFormat (pixelFormat_)
{
jassert (component != 0);
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
{
jassert (component != 0);
HIViewComponentPeer* const peer = dynamic_cast <HIViewComponentPeer*> (component->getTopLevelComponent()->getPeer());
if (peer == 0)
return;
HIViewComponentPeer* const peer = dynamic_cast <HIViewComponentPeer*> (component->getTopLevelComponent()->getPeer());
GLint attribs [64];
int n = 0;
attribs[n++] = AGL_RGBA;
attribs[n++] = AGL_DOUBLEBUFFER;
attribs[n++] = AGL_ACCELERATED;
attribs[n++] = AGL_RED_SIZE;
attribs[n++] = pixelFormat.redBits;
attribs[n++] = AGL_GREEN_SIZE;
attribs[n++] = pixelFormat.greenBits;
attribs[n++] = AGL_BLUE_SIZE;
attribs[n++] = pixelFormat.blueBits;
attribs[n++] = AGL_ALPHA_SIZE;
attribs[n++] = pixelFormat.alphaBits;
attribs[n++] = AGL_DEPTH_SIZE;
attribs[n++] = pixelFormat.depthBufferBits;
attribs[n++] = AGL_STENCIL_SIZE;
attribs[n++] = pixelFormat.stencilBufferBits;
attribs[n++] = AGL_ACCUM_RED_SIZE;
attribs[n++] = pixelFormat.accumulationBufferRedBits;
attribs[n++] = AGL_ACCUM_GREEN_SIZE;
attribs[n++] = pixelFormat.accumulationBufferGreenBits;
attribs[n++] = AGL_ACCUM_BLUE_SIZE;
attribs[n++] = pixelFormat.accumulationBufferBlueBits;
attribs[n++] = AGL_ACCUM_ALPHA_SIZE;
attribs[n++] = pixelFormat.accumulationBufferAlphaBits;
if (peer == 0)
return 0;
// xxx not sure how to do fullSceneAntiAliasingNumSamples..
OpenGLContextInfo* const oc = new OpenGLContextInfo();
attribs[n++] = AGL_SAMPLE_BUFFERS_ARB;
attribs[n++] = 1;
attribs[n++] = AGL_SAMPLES_ARB;
attribs[n++] = 4;
attribs[n++] = AGL_CLOSEST_POLICY;
attribs[n++] = AGL_NO_RECOVERY;
attribs[n++] = AGL_NONE;
GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER,
AGL_RED_SIZE, 8,
AGL_ALPHA_SIZE, 8,
AGL_DEPTH_SIZE, 24,
AGL_CLOSEST_POLICY, AGL_NO_RECOVERY,
AGL_SAMPLE_BUFFERS_ARB, 1,
AGL_SAMPLES_ARB, 4,
AGL_NONE };
renderContext = aglCreateContext (aglChoosePixelFormat (0, 0, attribs),
sharedContext);
oc->renderContext = aglCreateContext (aglChoosePixelFormat (0, 0, attrib),
(sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext
: 0);
aglSetDrawable (renderContext, GetWindowPort (peer->windowRef));
}
aglSetDrawable (oc->renderContext,
GetWindowPort (peer->windowRef));
~WindowedGLContext()
{
makeInactive();
aglSetDrawable (renderContext, 0);
aglDestroyContext (renderContext);
}
return oc;
}
bool makeActive() throw()
{
jassert (renderContext != 0);
void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp)
{
jassert (context != 0);
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
return aglSetCurrentContext (renderContext);
}
GLint bufferRect[4];
bool makeInactive() throw()
{
return (! isActive()) || aglSetCurrentContext (0);
}
bufferRect[0] = owner->getScreenX() - topComp->getScreenX();
bufferRect[1] = topComp->getHeight() - (owner->getHeight() + owner->getScreenY() - topComp->getScreenY());
bufferRect[2] = owner->getWidth();
bufferRect[3] = owner->getHeight();
bool isActive() const throw()
{
return aglGetCurrentContext() == renderContext;
}
aglSetInteger (oc->renderContext, AGL_BUFFER_RECT, bufferRect);
aglEnable (oc->renderContext, AGL_BUFFER_RECT);
}
const OpenGLPixelFormat getPixelFormat() const
{
return pixelFormat;
}
void juce_deleteOpenGLContext (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
void* getRawContext() const throw()
{
return renderContext;
}
aglDestroyContext (oc->renderContext);
void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight)
{
GLint bufferRect[4];
bufferRect[0] = x;
bufferRect[1] = outerWindowHeight - (y + h);
bufferRect[2] = w;
bufferRect[3] = h;
delete oc;
}
aglSetInteger (renderContext, AGL_BUFFER_RECT, bufferRect);
aglEnable (renderContext, AGL_BUFFER_RECT);
}
bool juce_makeOpenGLContextCurrent (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
void swapBuffers()
{
aglSwapBuffers (renderContext);
}
return aglSetCurrentContext ((oc != 0) ? oc->renderContext : 0);
}
void repaint()
{
}
//==============================================================================
juce_UseDebuggingNewOperator
AGLContext renderContext;
bool juce_isActiveOpenGLContext (void* context) throw()
private:
OpenGLPixelFormat pixelFormat;
//==============================================================================
WindowedGLContext (const WindowedGLContext&);
const WindowedGLContext& operator= (const WindowedGLContext&);
};
//==============================================================================
OpenGLContext* OpenGLContext::createContextForWindow (Component* const component,
const OpenGLPixelFormat& pixelFormat,
const OpenGLContext* const contextToShareWith)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
WindowedGLContext* c = new WindowedGLContext (component, pixelFormat,
contextToShareWith != 0 ? (AGLContext) contextToShareWith->getRawContext() : 0);
jassert (oc != 0);
return aglGetCurrentContext() == oc->renderContext;
if (c->renderContext == 0)
deleteAndZero (c);
return c;
}
void juce_swapOpenGLBuffers (void* context)
void juce_glViewport (const int w, const int h)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
glViewport (0, 0, w, h);
}
if (oc != 0)
aglSwapBuffers (oc->renderContext);
static int getAGLAttribute (AGLPixelFormat p, const GLint attrib)
{
GLint result = 0;
aglDescribePixelFormat (p, attrib, &result);
return result;
}
void juce_repaintOpenGLWindow (void* context)
void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
GLint attribs [64];
int n = 0;
attribs[n++] = AGL_RGBA;
attribs[n++] = AGL_DOUBLEBUFFER;
attribs[n++] = AGL_ACCELERATED;
attribs[n++] = AGL_NO_RECOVERY;
attribs[n++] = AGL_NONE;
AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs);
while (p != 0)
{
OpenGLPixelFormat* const pf = new OpenGLPixelFormat();
pf->redBits = getAGLAttribute (p, AGL_RED_SIZE);
pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE);
pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE);
pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE);
pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE);
pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE);
pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE);
pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE);
pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE);
pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE);
results.add (pf);
p = aglNextPixelFormat (p);
}
}
#endif
END_JUCE_NAMESPACE

+ 400
- 95
build/win32/platform_specific_code/juce_win32_Windowing.cpp View File

@@ -2640,6 +2640,7 @@ void MouseCursor::showInAllWindows() const throw()
showInWindow (0);
}
//==============================================================================
//==============================================================================
class JuceDropSource : public IDropSource
{
@@ -2970,13 +2971,13 @@ static HDROP createHDrop (const StringArray& fileNames) throw()
return hDrop;
}
static bool performDragDrop (FORMATETC* format, STGMEDIUM* medium, const DWORD whatToDo) throw()
static bool performDragDrop (FORMATETC* const format, STGMEDIUM* const medium, const DWORD whatToDo) throw()
{
JuceDropSource* const source = new JuceDropSource();
JuceDataObject* const data = new JuceDataObject (source, format, medium, 1);
DWORD effect;
HRESULT res = DoDragDrop (data, source, whatToDo, &effect);
const HRESULT res = DoDragDrop (data, source, whatToDo, &effect);
data->Release();
source->Release();
@@ -3026,152 +3027,456 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
}
//==============================================================================
//==============================================================================
#if JUCE_OPENGL
struct OpenGLContextInfo
#define WGL_EXT_FUNCTION_INIT(extType, extFunc) \
((extFunc = (extType) wglGetProcAddress (#extFunc)) != 0)
typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_SWAP_METHOD_ARB 0x2007
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_ACCUM_RED_BITS_ARB 0x201E
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_STEREO_ARB 0x2012
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#define WGL_TYPE_RGBA_ARB 0x202B
static void getWglExtensions (HDC dc, StringArray& result) throw()
{
Win32ComponentPeer* nativeWindow;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0;
if (WGL_EXT_FUNCTION_INIT (PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB))
result.addTokens (String (wglGetExtensionsStringARB (dc)), false);
else
jassertfalse // If this fails, it may be because you didn't activate the openGL context
}
HDC dc;
HGLRC renderContext;
};
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
//==============================================================================
class WindowedGLContext : public OpenGLContext
{
jassert (component != 0);
public:
WindowedGLContext (Component* const component, HGLRC contextToShareWith)
: renderContext (0),
nativeWindow (0)
{
jassert (component != 0);
Win32ComponentPeer* const peer = dynamic_cast <Win32ComponentPeer*> (component->getTopLevelComponent()->getPeer());
Win32ComponentPeer* const peer = dynamic_cast <Win32ComponentPeer*> (component->getTopLevelComponent()->getPeer());
nativeWindow = new Win32ComponentPeer (component, 0);
nativeWindow->dontRepaint = true;
nativeWindow->setVisible (true);
if (peer == 0)
return 0;
HWND hwnd = (HWND) nativeWindow->getNativeHandle();
OpenGLContextInfo* const oc = new OpenGLContextInfo();
if (peer != 0)
{
SetParent (hwnd, (HWND) peer->getNativeHandle());
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true);
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false);
}
oc->nativeWindow = new Win32ComponentPeer (component, 0);
oc->nativeWindow->dontRepaint = true;
oc->nativeWindow->setVisible (true);
HWND hwnd = (HWND) oc->nativeWindow->getNativeHandle();
dc = GetDC (hwnd);
SetParent (hwnd, (HWND) peer->getNativeHandle());
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true);
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false);
// Use a default pixel format that should be supported everywhere
PIXELFORMATDESCRIPTOR pfd;
zerostruct (pfd);
pfd.nSize = sizeof (pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 16;
pfd.cDepthBits = 16;
oc->dc = GetDC (hwnd);
const int format = ChoosePixelFormat (dc, &pfd);
PIXELFORMATDESCRIPTOR pfd;
zerostruct (pfd);
pfd.nSize = sizeof (pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
if (format != 0)
SetPixelFormat (dc, format, &pfd);
int format = ChoosePixelFormat (oc->dc, &pfd);
renderContext = wglCreateContext (dc);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
if (contextToShareWith != 0 && renderContext != 0)
wglShareLists (renderContext, contextToShareWith);
}
~WindowedGLContext()
{
makeInactive();
wglDeleteContext (renderContext);
ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc);
delete nativeWindow;
}
bool makeActive() throw()
{
jassert (renderContext != 0);
return wglMakeCurrent (dc, renderContext) != 0;
}
bool makeInactive() throw()
{
return (! isActive()) || (wglMakeCurrent (0, 0) != 0);
}
bool isActive() const throw()
{
// try some less ambitious formats if it fails..
pfd.cColorBits = 24;
format = ChoosePixelFormat (oc->dc, &pfd);
return wglGetCurrentContext() == renderContext;
}
const OpenGLPixelFormat getPixelFormat() const
{
OpenGLPixelFormat pf;
StringArray availableExtensions;
getWglExtensions (dc, availableExtensions);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
fillInPixelFormatDetails (GetPixelFormat (dc), pf, availableExtensions);
return pf;
}
void* getRawContext() const throw()
{
return renderContext;
}
bool setPixelFormat (const OpenGLPixelFormat& pixelFormat)
{
jassert (renderContext != 0);
makeActive();
StringArray availableExtensions;
getWglExtensions (dc, availableExtensions);
PIXELFORMATDESCRIPTOR pfd;
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 = pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits;
pfd.cRedBits = pixelFormat.redBits;
pfd.cGreenBits = pixelFormat.greenBits;
pfd.cBlueBits = pixelFormat.blueBits;
pfd.cAlphaBits = pixelFormat.alphaBits;
pfd.cDepthBits = pixelFormat.depthBufferBits;
pfd.cStencilBits = pixelFormat.stencilBufferBits;
pfd.cAccumBits = pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits
+ pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits;
pfd.cAccumRedBits = pixelFormat.accumulationBufferRedBits;
pfd.cAccumGreenBits = pixelFormat.accumulationBufferGreenBits;
pfd.cAccumBlueBits = pixelFormat.accumulationBufferBlueBits;
pfd.cAccumAlphaBits = pixelFormat.accumulationBufferAlphaBits;
int format = 0;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = 0;
if (availableExtensions.contains ("WGL_ARB_pixel_format")
&& WGL_EXT_FUNCTION_INIT (PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB))
{
pfd.cDepthBits = 16;
format = ChoosePixelFormat (oc->dc, &pfd);
int attributes[64];
int n = 0;
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
attributes[n++] = WGL_DRAW_TO_WINDOW_ARB;
attributes[n++] = GL_TRUE;
attributes[n++] = WGL_SUPPORT_OPENGL_ARB;
attributes[n++] = GL_TRUE;
attributes[n++] = WGL_ACCELERATION_ARB;
attributes[n++] = WGL_FULL_ACCELERATION_ARB;
attributes[n++] = WGL_DOUBLE_BUFFER_ARB;
attributes[n++] = GL_TRUE;
attributes[n++] = WGL_PIXEL_TYPE_ARB;
attributes[n++] = WGL_TYPE_RGBA_ARB;
attributes[n++] = WGL_COLOR_BITS_ARB;
attributes[n++] = pfd.cColorBits;
attributes[n++] = WGL_RED_BITS_ARB;
attributes[n++] = pixelFormat.redBits;
attributes[n++] = WGL_GREEN_BITS_ARB;
attributes[n++] = pixelFormat.greenBits;
attributes[n++] = WGL_BLUE_BITS_ARB;
attributes[n++] = pixelFormat.blueBits;
attributes[n++] = WGL_ALPHA_BITS_ARB;
attributes[n++] = pixelFormat.alphaBits;
attributes[n++] = WGL_DEPTH_BITS_ARB;
attributes[n++] = pixelFormat.depthBufferBits;
if (pixelFormat.stencilBufferBits > 0)
{
pfd.cColorBits = 32;
format = ChoosePixelFormat (oc->dc, &pfd);
attributes[n++] = WGL_STENCIL_BITS_ARB;
attributes[n++] = pixelFormat.stencilBufferBits;
}
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
{
jassertfalse // can't find a suitable pixel format that works for opengl
}
attributes[n++] = WGL_ACCUM_RED_BITS_ARB;
attributes[n++] = pixelFormat.accumulationBufferRedBits;
attributes[n++] = WGL_ACCUM_GREEN_BITS_ARB;
attributes[n++] = pixelFormat.accumulationBufferGreenBits;
attributes[n++] = WGL_ACCUM_BLUE_BITS_ARB;
attributes[n++] = pixelFormat.accumulationBufferBlueBits;
attributes[n++] = WGL_ACCUM_ALPHA_BITS_ARB;
attributes[n++] = pixelFormat.accumulationBufferAlphaBits;
if (availableExtensions.contains ("WGL_ARB_multisample")
&& pixelFormat.fullSceneAntiAliasingNumSamples > 0)
{
attributes[n++] = WGL_SAMPLE_BUFFERS_ARB;
attributes[n++] = 1;
attributes[n++] = WGL_SAMPLES_ARB;
attributes[n++] = pixelFormat.fullSceneAntiAliasingNumSamples;
}
attributes[n++] = 0;
UINT formatsCount;
const BOOL ok = wglChoosePixelFormatARB (dc, attributes, 0, 1, &format, &formatsCount);
(void) ok;
jassert (ok);
}
else
{
format = ChoosePixelFormat (dc, &pfd);
}
}
oc->renderContext = wglCreateContext (oc->dc);
if (format != 0)
{
makeInactive();
if (sharedContext != 0)
wglShareLists (((OpenGLContextInfo*) sharedContext)->renderContext, oc->renderContext);
// Create the real context..
if (SetPixelFormat (dc, format, &pfd))
{
wglDeleteContext (renderContext);
renderContext = wglCreateContext (dc);
return oc;
}
jassert (renderContext != 0);
return renderContext != 0;
}
}
void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp)
{
jassert (context != 0);
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
SetWindowPos ((HWND) oc->nativeWindow->getNativeHandle(), 0,
owner->getScreenX() - topComp->getScreenX(),
owner->getScreenY() - topComp->getScreenY(),
owner->getWidth(),
owner->getHeight(),
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
}
return false;
}
void juce_deleteOpenGLContext (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
void updateWindowPosition (int x, int y, int w, int h, int)
{
SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0,
x, y, w, h,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
}
if (oc != 0)
void repaint()
{
wglDeleteContext (oc->renderContext);
ReleaseDC ((HWND) oc->nativeWindow->getNativeHandle(), oc->dc);
int x, y, w, h;
nativeWindow->getBounds (x, y, w, h);
nativeWindow->repaint (0, 0, w, h);
}
deleteAndZero (oc->nativeWindow);
void swapBuffers()
{
SwapBuffers (dc);
}
delete oc;
void findAlternativeOpenGLPixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
jassert (isActive());
StringArray availableExtensions;
getWglExtensions (dc, availableExtensions);
PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0;
int numTypes = 0;
if (availableExtensions.contains("WGL_ARB_pixel_format")
&& WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB))
{
int attributes = WGL_NUMBER_PIXEL_FORMATS_ARB;
if (! wglGetPixelFormatAttribivARB (dc, 1, 0, 1, &attributes, &numTypes))
jassertfalse
}
else
{
numTypes = DescribePixelFormat (dc, 0, 0, 0);
}
OpenGLPixelFormat pf;
for (int i = 0; i < numTypes; ++i)
{
if (fillInPixelFormatDetails (i + 1, pf, availableExtensions))
{
bool alreadyListed = false;
for (int j = results.size(); --j >= 0;)
if (pf == *results.getUnchecked(j))
alreadyListed = true;
if (! alreadyListed)
results.add (new OpenGLPixelFormat (pf));
}
}
}
}
bool juce_makeOpenGLContextCurrent (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
//==============================================================================
juce_UseDebuggingNewOperator
if (oc != 0)
return wglMakeCurrent (oc->dc, oc->renderContext) != 0;
else
return wglMakeCurrent (0, 0) != 0;
}
HGLRC renderContext;
bool juce_isActiveOpenGLContext (void* context) throw()
private:
Win32ComponentPeer* nativeWindow;
HDC dc;
//==============================================================================
bool fillInPixelFormatDetails (const int pixelFormatIndex,
OpenGLPixelFormat& result,
const StringArray& availableExtensions) const throw()
{
PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0;
if (availableExtensions.contains ("WGL_ARB_pixel_format")
&& WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB))
{
int attributes[32];
int numAttributes = 0;
attributes[numAttributes++] = WGL_DRAW_TO_WINDOW_ARB;
attributes[numAttributes++] = WGL_SUPPORT_OPENGL_ARB;
attributes[numAttributes++] = WGL_ACCELERATION_ARB;
attributes[numAttributes++] = WGL_DOUBLE_BUFFER_ARB;
attributes[numAttributes++] = WGL_PIXEL_TYPE_ARB;
attributes[numAttributes++] = WGL_RED_BITS_ARB;
attributes[numAttributes++] = WGL_GREEN_BITS_ARB;
attributes[numAttributes++] = WGL_BLUE_BITS_ARB;
attributes[numAttributes++] = WGL_ALPHA_BITS_ARB;
attributes[numAttributes++] = WGL_DEPTH_BITS_ARB;
attributes[numAttributes++] = WGL_STENCIL_BITS_ARB;
attributes[numAttributes++] = WGL_ACCUM_RED_BITS_ARB;
attributes[numAttributes++] = WGL_ACCUM_GREEN_BITS_ARB;
attributes[numAttributes++] = WGL_ACCUM_BLUE_BITS_ARB;
attributes[numAttributes++] = WGL_ACCUM_ALPHA_BITS_ARB;
if (availableExtensions.contains ("WGL_ARB_multisample"))
attributes[numAttributes++] = WGL_SAMPLES_ARB;
int values[32];
zeromem (values, sizeof (values));
if (wglGetPixelFormatAttribivARB (dc, pixelFormatIndex, 0, numAttributes, attributes, values))
{
int n = 0;
bool isValidFormat = (values[n++] == GL_TRUE); // WGL_DRAW_TO_WINDOW_ARB
isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_SUPPORT_OPENGL_ARB
isValidFormat = (values[n++] == WGL_FULL_ACCELERATION_ARB) && isValidFormat; // WGL_ACCELERATION_ARB
isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_DOUBLE_BUFFER_ARB:
isValidFormat = (values[n++] == WGL_TYPE_RGBA_ARB) && isValidFormat; // WGL_PIXEL_TYPE_ARB
result.redBits = values[n++]; // WGL_RED_BITS_ARB
result.greenBits = values[n++]; // WGL_GREEN_BITS_ARB
result.blueBits = values[n++]; // WGL_BLUE_BITS_ARB
result.alphaBits = values[n++]; // WGL_ALPHA_BITS_ARB
result.depthBufferBits = values[n++]; // WGL_DEPTH_BITS_ARB
result.stencilBufferBits = values[n++]; // WGL_STENCIL_BITS_ARB
result.accumulationBufferRedBits = values[n++]; // WGL_ACCUM_RED_BITS_ARB
result.accumulationBufferGreenBits = values[n++]; // WGL_ACCUM_GREEN_BITS_ARB
result.accumulationBufferBlueBits = values[n++]; // WGL_ACCUM_BLUE_BITS_ARB
result.accumulationBufferAlphaBits = values[n++]; // WGL_ACCUM_ALPHA_BITS_ARB
result.fullSceneAntiAliasingNumSamples = values[n++]; // WGL_SAMPLES_ARB
return isValidFormat;
}
else
{
jassertfalse
}
}
else
{
PIXELFORMATDESCRIPTOR pfd;
if (DescribePixelFormat (dc, pixelFormatIndex, sizeof (pfd), &pfd))
{
result.redBits = pfd.cRedBits;
result.greenBits = pfd.cGreenBits;
result.blueBits = pfd.cBlueBits;
result.alphaBits = pfd.cAlphaBits;
result.depthBufferBits = pfd.cDepthBits;
result.stencilBufferBits = pfd.cStencilBits;
result.accumulationBufferRedBits = pfd.cAccumRedBits;
result.accumulationBufferGreenBits = pfd.cAccumGreenBits;
result.accumulationBufferBlueBits = pfd.cAccumBlueBits;
result.accumulationBufferAlphaBits = pfd.cAccumAlphaBits;
result.fullSceneAntiAliasingNumSamples = 0;
return true;
}
else
{
jassertfalse
}
}
return false;
}
WindowedGLContext (const WindowedGLContext&);
const WindowedGLContext& operator= (const WindowedGLContext&);
};
//==============================================================================
OpenGLContext* OpenGLContext::createContextForWindow (Component* const component,
const OpenGLPixelFormat& pixelFormat,
const OpenGLContext* const contextToShareWith)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
WindowedGLContext* c = new WindowedGLContext (component,
contextToShareWith != 0 ? (HGLRC) contextToShareWith->getRawContext() : 0);
jassert (oc != 0);
return wglGetCurrentContext() == oc->renderContext;
if (c->renderContext == 0 || ! c->setPixelFormat (pixelFormat))
deleteAndZero (c);
return c;
}
void juce_swapOpenGLBuffers (void* context)
void juce_glViewport (const int w, const int h)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
if (oc != 0)
SwapBuffers (oc->dc);
glViewport (0, 0, w, h);
}
void juce_repaintOpenGLWindow (void* context)
void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
Component tempComp;
if (oc != 0)
{
int x, y, w, h;
oc->nativeWindow->getBounds (x, y, w, h);
oc->nativeWindow->repaint (0, 0, w, h);
WindowedGLContext wc (&tempComp, 0);
wc.makeActive();
wc.findAlternativeOpenGLPixelFormats (results);
}
}
#endif
//==============================================================================
//==============================================================================
class JuceIStorage : public IStorage
{


+ 1
- 0
docs/JUCE changelist.txt View File

@@ -14,6 +14,7 @@ Changelist for version 1.45
- new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath.
- added a critical section option to ReferenceCountedArray
- refactored and added features to the Socket class, replacing it with StreamableSocket (basically the same as the original class), and DatagramSocket.
- refactored the OpenGLComponent, adding new classes OpenGLPixelFormat and OpenGLContext

==============================================================================
Changelist for version 1.44


+ 2
- 2
extras/juce demo/build/linux/JuceDemo.make View File

@@ -13,7 +13,7 @@ ifeq ($(CONFIG),Debug)
CPPFLAGS := -MMD -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include"
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -D_DEBUG -ggdb
CXXFLAGS := $(CFLAGS)
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -mwindows -L"/usr/X11R6/lib/" -L"../../../../bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -ljuce_debug
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -mwindows -L"/usr/X11R6/lib/" -L"../../../../bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -lXss -ljuce_debug
LDDEPS :=
RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include"
TARGET := jucedemo
@@ -28,7 +28,7 @@ ifeq ($(CONFIG),Release)
CPPFLAGS := -MMD -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include"
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O2
CXXFLAGS := $(CFLAGS)
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -mwindows -s -L"/usr/X11R6/lib/" -L"../../../../bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -ljuce
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -mwindows -s -L"/usr/X11R6/lib/" -L"../../../../bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -lXss -ljuce
LDDEPS :=
RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include"
TARGET := jucedemo


+ 2
- 2
extras/juce demo/build/linux/jucedemo_premake.lua View File

@@ -31,11 +31,11 @@ package.libpaths = {
}
package.config["Debug"].links = {
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce_debug"
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "Xss", "juce_debug"
}
package.config["Release"].links = {
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce"
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "Xss", "juce"
}
package.linkflags = { "static-runtime" }


+ 26
- 0
extras/juce demo/src/demos/OpenGLDemo.cpp View File

@@ -81,6 +81,32 @@ public:
delete im;
startTimer (20);
// Just for demo purposes, let's dump a list of all the available pixel formats..
OwnedArray <OpenGLPixelFormat> availablePixelFormats;
OpenGLPixelFormat::getAvailablePixelFormats (availablePixelFormats);
for (int i = 0; i < availablePixelFormats.size(); ++i)
{
const OpenGLPixelFormat* const pixFormat = availablePixelFormats[i];
String formatDescription;
formatDescription
<< i << ": RGBA=(" << pixFormat->redBits
<< ", " << pixFormat->greenBits
<< ", " << pixFormat->blueBits
<< ", " << pixFormat->alphaBits
<< "), depth=" << pixFormat->depthBufferBits
<< ", stencil=" << pixFormat->stencilBufferBits
<< ", accum RGBA=(" << pixFormat->accumulationBufferRedBits
<< ", " << pixFormat->accumulationBufferGreenBits
<< ", " << pixFormat->accumulationBufferBlueBits
<< ", " << pixFormat->accumulationBufferAlphaBits
<< "), full-scene AA="
<< pixFormat->fullSceneAntiAliasingNumSamples;
Logger::outputDebugString (formatDescription);
}
}
~DemoOpenGLCanvas()


+ 144
- 158
src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp View File

@@ -29,229 +29,216 @@
==============================================================================
*/
#ifdef _MSC_VER
#pragma warning (disable: 4514)
#pragma warning (push)
#endif
#include "../../../../../juce_Config.h"
#include "../../../../juce_core/basics/juce_StandardHeader.h"
#if JUCE_OPENGL
#ifdef _WIN32
#include <windows.h>
#include <gl/gl.h>
#else
#ifdef LINUX
#include <GL/glx.h>
#else
#include <agl/agl.h>
#endif
#endif
#include "../../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#undef KeyPress
#include "juce_OpenGLComponent.h"
#include "../../graphics/geometry/juce_RectangleList.h"
#include "../../../events/juce_Timer.h"
#include "../layout/juce_ComponentMovementWatcher.h"
#include "../../../../juce_core/threads/juce_ScopedLock.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
//==============================================================================
extern void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext);
extern void juce_deleteOpenGLContext (void* context);
extern bool juce_makeOpenGLContextCurrent (void* context);
extern void juce_swapOpenGLBuffers (void* context);
extern void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp);
extern void juce_repaintOpenGLWindow (void* context);
extern bool juce_isActiveOpenGLContext (void* context) throw();
static VoidArray activeGLWindows (2);
extern void juce_glViewport (const int w, const int h);
//==============================================================================
class InternalGLContextHolder : public ComponentMovementWatcher
OpenGLPixelFormat::OpenGLPixelFormat (const int bitsPerRGBComponent,
const int alphaBits_,
const int depthBufferBits_,
const int stencilBufferBits_) throw()
: redBits (bitsPerRGBComponent),
greenBits (bitsPerRGBComponent),
blueBits (bitsPerRGBComponent),
alphaBits (alphaBits_),
depthBufferBits (depthBufferBits_),
stencilBufferBits (stencilBufferBits_),
accumulationBufferRedBits (0),
accumulationBufferGreenBits (0),
accumulationBufferBlueBits (0),
accumulationBufferAlphaBits (0),
fullSceneAntiAliasingNumSamples (0)
{
private:
OpenGLComponent* owner;
void* context;
InternalGLContextHolder* sharedContext;
bool wasShowing;
}
bool OpenGLPixelFormat::operator== (const OpenGLPixelFormat& other) const throw()
{
return memcmp (this, &other, sizeof (other)) == 0;
}
public:
bool needToUpdateViewport;
//==============================================================================
class OpenGLComponentWatcher : public ComponentMovementWatcher
{
public:
//==============================================================================
InternalGLContextHolder (OpenGLComponent* const owner_,
InternalGLContextHolder* const sharedContext_)
OpenGLComponentWatcher (OpenGLComponent* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_),
context (0),
sharedContext (sharedContext_),
wasShowing (false),
needToUpdateViewport (true)
wasShowing (false)
{
}
~InternalGLContextHolder()
~OpenGLComponentWatcher() {}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
release();
owner->updateContextPosition();
}
//==============================================================================
void release()
void componentPeerChanged()
{
if (context != 0)
{
juce_deleteOpenGLContext (context);
context = 0;
}
const ScopedLock sl (owner->getContextLock());
owner->deleteContext();
owner->createContext();
}
void initialise()
void componentVisibilityChanged (Component&)
{
jassert (context == 0);
const bool isShowingNow = owner->isShowing();
if (context == 0)
if (wasShowing != isShowingNow)
{
context = juce_createOpenGLContext (owner,
sharedContext != 0 ? sharedContext->context
: 0);
if (context != 0)
{
componentMovedOrResized (true, true);
if (makeCurrent())
owner->newOpenGLContextCreated();
}
wasShowing = isShowingNow;
owner->updateContextPosition();
}
}
//==============================================================================
bool makeCurrent() const
{
return context != 0 && juce_makeOpenGLContextCurrent (context);
}
juce_UseDebuggingNewOperator
bool isActive() const throw()
{
return context != 0 && juce_isActiveOpenGLContext (context);
}
private:
OpenGLComponent* const owner;
bool wasShowing;
};
void swapBuffers() const
{
if (context != 0)
juce_swapOpenGLBuffers (context);
}
//==============================================================================
OpenGLComponent::OpenGLComponent()
: context (0),
componentToShareListsWith (0),
needToUpdateViewport (true)
{
setOpaque (true);
componentWatcher = new OpenGLComponentWatcher (this);
}
void repaint() const
{
if (context != 0)
juce_repaintOpenGLWindow (context);
}
OpenGLComponent::~OpenGLComponent()
{
deleteContext();
delete componentWatcher;
}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
void OpenGLComponent::createContext()
{
const ScopedLock sl (contextLock);
jassert (context == 0);
if (context == 0 && isShowing() && getTopLevelComponent()->getPeer() != 0)
{
if (owner->getWidth() > 0 && owner->getHeight() > 0)
context = OpenGLContext::createContextForWindow (this,
preferredPixelFormat,
componentToShareListsWith != 0
? componentToShareListsWith->context
: 0);
if (context != 0)
{
Component* const topComp = owner->getTopLevelComponent();
if (topComp->getPeer() != 0)
{
needToUpdateViewport = true;
if (context == 0)
{
if (owner->isShowing())
initialise();
else
return;
}
if (context != 0)
juce_updateOpenGLWindowPos (context, owner, topComp);
}
updateContextPosition();
if (makeCurrentContextActive())
newOpenGLContextCreated();
}
}
}
void componentPeerChanged()
{
release();
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
deleteAndZero (context);
}
if (owner->isShowing() && owner->getTopLevelComponent()->getPeer() != 0)
initialise();
}
void OpenGLComponent::updateContextPosition()
{
needToUpdateViewport = true;
void componentVisibilityChanged (Component&)
if (getWidth() > 0 && getHeight() > 0)
{
if (wasShowing != owner->isShowing())
Component* const topComp = getTopLevelComponent();
if (topComp->getPeer() != 0)
{
wasShowing = owner->isShowing();
componentMovedOrResized (true, true);
const ScopedLock sl (contextLock);
if (context == 0)
createContext();
if (context != 0)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
};
}
//==============================================================================
OpenGLComponent::OpenGLComponent (OpenGLComponent* share)
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
setOpaque (true);
internalData = new InternalGLContextHolder (this, (InternalGLContextHolder*) (share != 0 ? share->internalData : 0));
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != 0)
pf = context->getPixelFormat();
activeGLWindows.add (this);
return pf;
}
OpenGLComponent::~OpenGLComponent()
bool OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
activeGLWindows.removeValue ((void*) this);
if (preferredPixelFormat == formatToUse)
return true;
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
createContext();
return context != 0;
}
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
delete context;
void OpenGLComponent::shareWith (OpenGLComponent* const comp)
{
if (componentToShareListsWith != comp)
{
const ScopedLock sl (contextLock);
deleteContext();
componentToShareListsWith = comp;
createContext();
}
}
bool OpenGLComponent::makeCurrentContextActive()
{
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
return context->makeCurrent();
return context != 0 && context->makeActive();
}
void OpenGLComponent::makeCurrentContextInactive()
{
juce_makeOpenGLContextCurrent (0);
if (context != 0)
context->makeInactive();
}
bool OpenGLComponent::isActiveContext() const throw()
{
const InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
return context != 0 && context->isActive();
}
OpenGLComponent* OpenGLComponent::getCurrentlyActiveContextComponent() throw()
{
for (int i = activeGLWindows.size(); --i >= 0;)
{
OpenGLComponent* const component = (OpenGLComponent*) activeGLWindows.getUnchecked(i);
if (component->isActiveContext())
return component;
}
return 0;
}
void OpenGLComponent::swapBuffers()
{
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
if (context != 0)
context->swapBuffers();
}
@@ -273,20 +260,19 @@ void OpenGLComponent::paint (Graphics&)
bool OpenGLComponent::renderAndSwapBuffers()
{
const ScopedLock sl (contextLock);
if (! makeCurrentContextActive())
return false;
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
if (context->needToUpdateViewport)
if (needToUpdateViewport)
{
context->needToUpdateViewport = false;
glViewport (0, 0, getWidth(), getHeight());
needToUpdateViewport = false;
juce_glViewport (getWidth(), getHeight());
}
renderOpenGL();
context->swapBuffers();
swapBuffers();
return true;
}
@@ -295,8 +281,8 @@ void OpenGLComponent::internalRepaint (int x, int y, int w, int h)
{
Component::internalRepaint (x, y, w, h);
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
context->repaint();
if (context != 0)
context->repaint();
}


+ 186
- 30
src/juce_appframework/gui/components/special/juce_OpenGLComponent.h View File

@@ -37,6 +37,119 @@
// this is used to disable OpenGL, and is defined in juce_Config.h
#if JUCE_OPENGL || DOXYGEN
class OpenGLComponentWatcher;
//==============================================================================
/**
Represents the various properties of an OpenGL bitmap format.
@see OpenGLComponent::setPixelFormat
*/
struct OpenGLPixelFormat
{
//==============================================================================
/** Creates an OpenGLPixelFormat.
The default constructor just initialises the object as a simple 8-bit
RGBA format.
*/
OpenGLPixelFormat (const int bitsPerRGBComponent = 8,
const int alphaBits = 8,
const int depthBufferBits = 16,
const int stencilBufferBits = 0) throw();
//==============================================================================
int redBits; /**< The number of bits per pixel to use for the red channel. */
int greenBits; /**< The number of bits per pixel to use for the green channel. */
int blueBits; /**< The number of bits per pixel to use for the blue channel. */
int alphaBits; /**< The number of bits per pixel to use for the alpha channel. */
int depthBufferBits; /**< The number of bits per pixel to use for a depth buffer. */
int stencilBufferBits; /**< The number of bits per pixel to use for a stencil buffer. */
int accumulationBufferRedBits; /**< The number of bits per pixel to use for an accumulation buffer's red channel. */
int accumulationBufferGreenBits; /**< The number of bits per pixel to use for an accumulation buffer's green channel. */
int accumulationBufferBlueBits; /**< The number of bits per pixel to use for an accumulation buffer's blue channel. */
int accumulationBufferAlphaBits; /**< The number of bits per pixel to use for an accumulation buffer's alpha channel. */
uint8 fullSceneAntiAliasingNumSamples; /**< The number of samples to use in full-scene anti-aliasing (if available). */
//==============================================================================
/** Returns a list of all the pixel formats that can be used in this system.
*/
static void getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results);
//==============================================================================
bool operator== (const OpenGLPixelFormat&) const throw();
juce_UseDebuggingNewOperator
};
//==============================================================================
/**
A base class for types of OpenGL context.
An OpenGLComponent will supply its own context for drawing in its window.
*/
class OpenGLContext
{
public:
//==============================================================================
/** Destructor. */
virtual ~OpenGLContext() {}
//==============================================================================
/** Makes this context the currently active one. */
virtual bool makeActive() throw() = 0;
/** If this context is currently active, it is disactivated. */
virtual bool makeInactive() throw() = 0;
/** Returns true if this context is currently active. */
virtual bool isActive() const throw() = 0;
/** Swaps the buffers (if the context can do this). */
virtual void swapBuffers() = 0;
//==============================================================================
/** Returns the pixel format being used by this context. */
virtual const OpenGLPixelFormat getPixelFormat() const = 0;
/** For windowed contexts, this moves the context within the bounds of
its parent window.
*/
virtual void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) = 0;
/** For windowed contexts, this triggers a repaint of the window.
(Not relevent on all platforms).
*/
virtual void repaint() = 0;
/** Returns an OS-dependent handle to the raw GL context.
On win32, this will be a HGLRC; on the Mac, an AGLContext; on Linux,
a GLXContext.
*/
virtual void* getRawContext() const throw() = 0;
//==============================================================================
/** This tries to create a context that can be used for drawing into the
area occupied by the specified component.
Note that you probably shouldn't use this method directly unless you know what
you're doing - the OpenGLComponent calls this and manages the context for you.
*/
static OpenGLContext* createContextForWindow (Component* componentToDrawTo,
const OpenGLPixelFormat& pixelFormat,
const OpenGLContext* const contextToShareWith);
//==============================================================================
juce_UseDebuggingNewOperator
protected:
OpenGLContext() throw() {};
};
//==============================================================================
/**
@@ -51,42 +164,28 @@ class JUCE_API OpenGLComponent : public Component
public:
//==============================================================================
/** Creates an OpenGLComponent.
@param componentToShareContextWith if this is another OpenGLComponent, then
the two contexts will have their OpenGL contexts
shared
*/
OpenGLComponent (OpenGLComponent* componentToShareContextWith = 0);
OpenGLComponent();
/** Destructor. */
~OpenGLComponent();
//==============================================================================
/** Makes this component the current openGL context.
/** Changes the pixel format used by this component.
You might want to use this in things like your resize() method, before calling
GL commands.
If this returns false, then the context isn't active, so you should avoid
making any calls.
@see OpenGLPixelFormat::getAvailablePixelFormats()
*/
bool makeCurrentContextActive();
bool setPixelFormat (const OpenGLPixelFormat& formatToUse);
/** Stops the current component being the active OpenGL context.
/** Returns the pixel format that this component is currently using. */
const OpenGLPixelFormat getPixelFormat() const;
This is the opposite of makeCurrentContextActive()
*/
void makeCurrentContextInactive();
/** Specifies another component whose OpenGL context should be shared with
this one.
/** Returns true if this component is the active openGL context for the
current thread.
This is an OpenGL feature that lets two contexts share their texture data.
*/
bool isActiveContext() const throw();
/** Returns the OpenGLComponent that is currently the active context for
the current thread.
*/
static OpenGLComponent* getCurrentlyActiveContextComponent() throw();
void shareWith (OpenGLComponent* const componentToShareListsWith);
//==============================================================================
/** Flips the openGL buffers over. */
@@ -115,16 +214,63 @@ public:
virtual void newOpenGLContextCreated() = 0;
//==============================================================================
/** Returns the context that will draw into this component.
This may return 0 if it failed to initialise properly, or if the component
is currently invisible. The context object may be deleted and a new one created
during the life of this component - see newOpenGLContextCreated().
*/
OpenGLContext* getCurrentContext() const throw();
/** Makes this component the current openGL context.
You might want to use this in things like your resize() method, before calling
GL commands.
If this returns false, then the context isn't active, so you should avoid
making any calls.
@see OpenGLContext::makeActive
*/
bool makeCurrentContextActive();
/** Stops the current component being the active OpenGL context.
This is the opposite of makeCurrentContextActive()
@see OpenGLContext::makeInactive
*/
void makeCurrentContextInactive();
/** Returns true if this component is the active openGL context for the
current thread.
@see OpenGLContext::isActive
*/
bool isActiveContext() const throw();
//==============================================================================
/** Calls the rendering callback, and swaps the buffers afterwards.
Called by paint(), this can be overridden if you need to decouple the rendering
from the paint callback and render with a different thread.
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();
/** This returns a critical section that can be used to lock the current context.
Because the context that is used by this component can change, e.g. when the
component is shown or hidden, then if you're rendering to it on a background
thread, this allows you to lock the context for the duration of your rendering
routine.
*/
CriticalSection& getContextLock() throw() { return contextLock; }
//==============================================================================
/** @internal */
@@ -133,13 +279,23 @@ public:
juce_UseDebuggingNewOperator
private:
friend class InternalGLContextHolder;
void* internalData;
friend class OpenGLComponentWatcher;
OpenGLComponentWatcher* componentWatcher;
OpenGLComponent (const OpenGLComponent&);
const OpenGLComponent& operator= (const OpenGLComponent&);
OpenGLContext* context;
OpenGLComponent* componentToShareListsWith;
CriticalSection contextLock;
OpenGLPixelFormat preferredPixelFormat;
bool needToUpdateViewport;
void createContext();
void deleteContext();
void updateContextPosition();
void internalRepaint (int x, int y, int w, int h);
OpenGLComponent (const OpenGLComponent&);
const OpenGLComponent& operator= (const OpenGLComponent&);
};


Loading…
Cancel
Save