1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
This commit is contained in:
jules 2007-09-04 09:05:08 +00:00
parent adeafc5c71
commit 73257b4f4f
9 changed files with 1096 additions and 482 deletions

View file

@ -2795,49 +2795,60 @@ Image* juce_createIconForFile (const File& file)
//============================================================================== //==============================================================================
#if JUCE_OPENGL #if JUCE_OPENGL
struct OpenGLContextInfo
//==============================================================================
class WindowedGLContext : public OpenGLContext
{ {
Window embeddedWindow; public:
GLXContext renderContext; WindowedGLContext (Component* const component,
}; const OpenGLPixelFormat& pixelFormat_,
GLXContext sharedContext)
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext) : renderContext (0),
{ embeddedWindow (0),
XSync (display, False); pixelFormat (pixelFormat_)
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, jassert (component != 0);
GLX_DOUBLEBUFFER, LinuxComponentPeer* const peer = dynamic_cast <LinuxComponentPeer*> (component->getTopLevelComponent()->getPeer());
GLX_RED_SIZE, 8, if (peer == 0)
GLX_GREEN_SIZE, 8, return;
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 8,
None
};
XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribList); XSync (display, False);
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) if (bestVisual == 0)
return 0; return;
OpenGLContextInfo* const oc = new OpenGLContextInfo(); renderContext = glXCreateContext (display, bestVisual, sharedContext, GL_TRUE);
oc->renderContext = glXCreateContext (display, bestVisual,
(sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext
: 0,
GL_TRUE);
Window windowH = (Window) peer->getNativeHandle(); Window windowH = (Window) peer->getNativeHandle();
@ -2847,7 +2858,7 @@ void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
swa.border_pixel = 0; swa.border_pixel = 0;
swa.event_mask = ExposureMask | StructureNotifyMask; swa.event_mask = ExposureMask | StructureNotifyMask;
oc->embeddedWindow = XCreateWindow (display, windowH, embeddedWindow = XCreateWindow (display, windowH,
0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
bestVisual->depth, bestVisual->depth,
InputOutput, InputOutput,
@ -2855,73 +2866,104 @@ void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
CWBorderPixel | CWColormap | CWEventMask, CWBorderPixel | CWColormap | CWEventMask,
&swa); &swa);
XSaveContext (display, (XID) oc->embeddedWindow, improbableNumber, (XPointer) peer); XSaveContext (display, (XID) embeddedWindow, improbableNumber, (XPointer) peer);
XMapWindow (display, oc->embeddedWindow); XMapWindow (display, embeddedWindow);
XFreeColormap (display, colourMap); XFreeColormap (display, colourMap);
XFree (bestVisual); XFree (bestVisual);
XSync (display, False); XSync (display, False);
return oc;
}
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()));
}
void juce_deleteOpenGLContext (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
if (oc != 0)
{
glXDestroyContext (display, oc->renderContext);
XUnmapWindow (display, oc->embeddedWindow);
XDestroyWindow (display, oc->embeddedWindow);
delete oc;
} }
}
bool juce_makeOpenGLContextCurrent (void* context) ~WindowedGLContext()
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; makeInactive();
if (oc != 0) glXDestroyContext (display, renderContext);
return glXMakeCurrent (display, oc->embeddedWindow, oc->renderContext)
XUnmapWindow (display, embeddedWindow);
XDestroyWindow (display, embeddedWindow);
}
bool makeActive() throw()
{
jassert (renderContext != 0);
return glXMakeCurrent (display, embeddedWindow, renderContext)
&& XSync (display, False); && XSync (display, False);
else }
return glXMakeCurrent (display, None, 0);
bool makeInactive() throw()
{
return (! isActive()) || glXMakeCurrent (display, None, 0);
}
bool isActive() const throw()
{
return glXGetCurrentContext() == renderContext;
}
const OpenGLPixelFormat getPixelFormat() const
{
return pixelFormat;
}
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)
{
WindowedGLContext* c = new WindowedGLContext (component, pixelFormat,
contextToShareWith != 0 ? (GLXContext) contextToShareWith->getRawContext() : 0);
if (c->renderContext == 0)
deleteAndZero (c);
return c;
} }
bool juce_isActiveOpenGLContext (void* context) throw() void juce_glViewport (const int w, const int h)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; glViewport (0, 0, w, h);
jassert (oc != 0);
return glXGetCurrentContext() == oc->renderContext;
} }
void juce_swapOpenGLBuffers (void* context) void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
if (oc != 0)
glXSwapBuffers (display, oc->embeddedWindow);
}
void juce_repaintOpenGLWindow (void* context)
{ {
results.add (new OpenGLPixelFormat()); // xxx
} }
#endif #endif

View file

@ -3292,92 +3292,190 @@ void AppleRemoteDevice::handleCallbackInternal()
//============================================================================== //==============================================================================
#if JUCE_OPENGL #if JUCE_OPENGL
struct OpenGLContextInfo //==============================================================================
{ class WindowedGLContext : public OpenGLContext
AGLContext renderContext;
};
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext)
{ {
public:
WindowedGLContext (Component* const component,
const OpenGLPixelFormat& pixelFormat_,
AGLContext sharedContext)
: renderContext (0),
pixelFormat (pixelFormat_)
{
jassert (component != 0); jassert (component != 0);
HIViewComponentPeer* const peer = dynamic_cast <HIViewComponentPeer*> (component->getTopLevelComponent()->getPeer()); HIViewComponentPeer* const peer = dynamic_cast <HIViewComponentPeer*> (component->getTopLevelComponent()->getPeer());
if (peer == 0) if (peer == 0)
return 0; return;
OpenGLContextInfo* const oc = new OpenGLContextInfo(); 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;
GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER, // xxx not sure how to do fullSceneAntiAliasingNumSamples..
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 };
oc->renderContext = aglCreateContext (aglChoosePixelFormat (0, 0, attrib), attribs[n++] = AGL_SAMPLE_BUFFERS_ARB;
(sharedContext != 0) ? ((OpenGLContextInfo*) sharedContext)->renderContext attribs[n++] = 1;
: 0); attribs[n++] = AGL_SAMPLES_ARB;
attribs[n++] = 4;
attribs[n++] = AGL_CLOSEST_POLICY;
attribs[n++] = AGL_NO_RECOVERY;
attribs[n++] = AGL_NONE;
aglSetDrawable (oc->renderContext, renderContext = aglCreateContext (aglChoosePixelFormat (0, 0, attribs),
GetWindowPort (peer->windowRef)); sharedContext);
return oc; aglSetDrawable (renderContext, GetWindowPort (peer->windowRef));
} }
void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp) ~WindowedGLContext()
{ {
jassert (context != 0); makeInactive();
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; aglSetDrawable (renderContext, 0);
aglDestroyContext (renderContext);
}
bool makeActive() throw()
{
jassert (renderContext != 0);
return aglSetCurrentContext (renderContext);
}
bool makeInactive() throw()
{
return (! isActive()) || aglSetCurrentContext (0);
}
bool isActive() const throw()
{
return aglGetCurrentContext() == renderContext;
}
const OpenGLPixelFormat getPixelFormat() const
{
return pixelFormat;
}
void* getRawContext() const throw()
{
return renderContext;
}
void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight)
{
GLint bufferRect[4]; GLint bufferRect[4];
bufferRect[0] = x;
bufferRect[1] = outerWindowHeight - (y + h);
bufferRect[2] = w;
bufferRect[3] = h;
bufferRect[0] = owner->getScreenX() - topComp->getScreenX(); aglSetInteger (renderContext, AGL_BUFFER_RECT, bufferRect);
bufferRect[1] = topComp->getHeight() - (owner->getHeight() + owner->getScreenY() - topComp->getScreenY()); aglEnable (renderContext, AGL_BUFFER_RECT);
bufferRect[2] = owner->getWidth(); }
bufferRect[3] = owner->getHeight();
aglSetInteger (oc->renderContext, AGL_BUFFER_RECT, bufferRect); void swapBuffers()
aglEnable (oc->renderContext, AGL_BUFFER_RECT); {
} aglSwapBuffers (renderContext);
}
void juce_deleteOpenGLContext (void* context) void repaint()
{
}
//==============================================================================
juce_UseDebuggingNewOperator
AGLContext renderContext;
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);
aglDestroyContext (oc->renderContext); if (c->renderContext == 0)
deleteAndZero (c);
delete oc; return c;
} }
bool juce_makeOpenGLContextCurrent (void* context) void juce_glViewport (const int w, const int h)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; glViewport (0, 0, w, h);
return aglSetCurrentContext ((oc != 0) ? oc->renderContext : 0);
} }
bool juce_isActiveOpenGLContext (void* context) throw() static int getAGLAttribute (AGLPixelFormat p, const GLint attrib)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; GLint result = 0;
aglDescribePixelFormat (p, attrib, &result);
jassert (oc != 0); return result;
return aglGetCurrentContext() == oc->renderContext;
} }
void juce_swapOpenGLBuffers (void* context) void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; 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;
if (oc != 0) AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs);
aglSwapBuffers (oc->renderContext);
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);
}
} }
void juce_repaintOpenGLWindow (void* context)
{
}
#endif #endif

View file

@ -2640,6 +2640,7 @@ void MouseCursor::showInAllWindows() const throw()
showInWindow (0); showInWindow (0);
} }
//==============================================================================
//============================================================================== //==============================================================================
class JuceDropSource : public IDropSource class JuceDropSource : public IDropSource
{ {
@ -2970,13 +2971,13 @@ static HDROP createHDrop (const StringArray& fileNames) throw()
return hDrop; 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(); JuceDropSource* const source = new JuceDropSource();
JuceDataObject* const data = new JuceDataObject (source, format, medium, 1); JuceDataObject* const data = new JuceDataObject (source, format, medium, 1);
DWORD effect; DWORD effect;
HRESULT res = DoDragDrop (data, source, whatToDo, &effect); const HRESULT res = DoDragDrop (data, source, whatToDo, &effect);
data->Release(); data->Release();
source->Release(); source->Release();
@ -3026,152 +3027,456 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
} }
//==============================================================================
//============================================================================== //==============================================================================
#if JUCE_OPENGL #if JUCE_OPENGL
struct OpenGLContextInfo #define WGL_EXT_FUNCTION_INIT(extType, extFunc) \
{ ((extFunc = (extType) wglGetProcAddress (#extFunc)) != 0)
Win32ComponentPeer* nativeWindow;
HDC dc; typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
HGLRC renderContext; 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);
void* juce_createOpenGLContext (OpenGLComponent* component, void* sharedContext) #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()
{ {
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
}
//==============================================================================
class WindowedGLContext : public OpenGLContext
{
public:
WindowedGLContext (Component* const component, HGLRC contextToShareWith)
: renderContext (0),
nativeWindow (0)
{
jassert (component != 0); jassert (component != 0);
Win32ComponentPeer* const peer = dynamic_cast <Win32ComponentPeer*> (component->getTopLevelComponent()->getPeer()); Win32ComponentPeer* const peer = dynamic_cast <Win32ComponentPeer*> (component->getTopLevelComponent()->getPeer());
if (peer == 0) nativeWindow = new Win32ComponentPeer (component, 0);
return 0; nativeWindow->dontRepaint = true;
nativeWindow->setVisible (true);
OpenGLContextInfo* const oc = new OpenGLContextInfo(); HWND hwnd = (HWND) nativeWindow->getNativeHandle();
oc->nativeWindow = new Win32ComponentPeer (component, 0);
oc->nativeWindow->dontRepaint = true;
oc->nativeWindow->setVisible (true);
HWND hwnd = (HWND) oc->nativeWindow->getNativeHandle();
if (peer != 0)
{
SetParent (hwnd, (HWND) peer->getNativeHandle()); SetParent (hwnd, (HWND) peer->getNativeHandle());
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true); juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true);
juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false); juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false);
}
oc->dc = GetDC (hwnd); dc = GetDC (hwnd);
// Use a default pixel format that should be supported everywhere
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
zerostruct (pfd); zerostruct (pfd);
pfd.nSize = sizeof (pfd); pfd.nSize = sizeof (pfd);
pfd.nVersion = 1; pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA; pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32; pfd.cColorBits = 16;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int format = ChoosePixelFormat (oc->dc, &pfd);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
{
// try some less ambitious formats if it fails..
pfd.cColorBits = 24;
format = ChoosePixelFormat (oc->dc, &pfd);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd))
{
pfd.cDepthBits = 16; pfd.cDepthBits = 16;
format = ChoosePixelFormat (oc->dc, &pfd);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd)) const int format = ChoosePixelFormat (dc, &pfd);
if (format != 0)
SetPixelFormat (dc, format, &pfd);
renderContext = wglCreateContext (dc);
if (contextToShareWith != 0 && renderContext != 0)
wglShareLists (renderContext, contextToShareWith);
}
~WindowedGLContext()
{ {
pfd.cColorBits = 32; makeInactive();
format = ChoosePixelFormat (oc->dc, &pfd);
if (format == 0 || ! SetPixelFormat (oc->dc, format, &pfd)) wglDeleteContext (renderContext);
ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc);
delete nativeWindow;
}
bool makeActive() throw()
{ {
jassertfalse // can't find a suitable pixel format that works for opengl jassert (renderContext != 0);
} return wglMakeCurrent (dc, renderContext) != 0;
}
}
} }
oc->renderContext = wglCreateContext (oc->dc); bool makeInactive() throw()
if (sharedContext != 0)
wglShareLists (((OpenGLContextInfo*) sharedContext)->renderContext, oc->renderContext);
return oc;
}
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);
}
void juce_deleteOpenGLContext (void* context)
{
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
if (oc != 0)
{ {
wglDeleteContext (oc->renderContext); return (! isActive()) || (wglMakeCurrent (0, 0) != 0);
ReleaseDC ((HWND) oc->nativeWindow->getNativeHandle(), oc->dc);
deleteAndZero (oc->nativeWindow);
delete oc;
} }
}
bool juce_makeOpenGLContextCurrent (void* context) bool isActive() const throw()
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; return wglGetCurrentContext() == renderContext;
}
if (oc != 0) const OpenGLPixelFormat getPixelFormat() const
return wglMakeCurrent (oc->dc, oc->renderContext) != 0; {
OpenGLPixelFormat pf;
StringArray availableExtensions;
getWglExtensions (dc, availableExtensions);
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))
{
int attributes[64];
int n = 0;
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)
{
attributes[n++] = WGL_STENCIL_BITS_ARB;
attributes[n++] = pixelFormat.stencilBufferBits;
}
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 else
return wglMakeCurrent (0, 0) != 0; {
} format = ChoosePixelFormat (dc, &pfd);
}
bool juce_isActiveOpenGLContext (void* context) throw() if (format != 0)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; makeInactive();
jassert (oc != 0); // Create the real context..
return wglGetCurrentContext() == oc->renderContext; if (SetPixelFormat (dc, format, &pfd))
} {
wglDeleteContext (renderContext);
renderContext = wglCreateContext (dc);
void juce_swapOpenGLBuffers (void* context) jassert (renderContext != 0);
{ return renderContext != 0;
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; }
}
if (oc != 0) return false;
SwapBuffers (oc->dc); }
}
void juce_repaintOpenGLWindow (void* context) void updateWindowPosition (int x, int y, int w, int h, int)
{ {
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context; SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0,
x, y, w, h,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
}
if (oc != 0) void repaint()
{ {
int x, y, w, h; int x, y, w, h;
oc->nativeWindow->getBounds (x, y, w, h); nativeWindow->getBounds (x, y, w, h);
oc->nativeWindow->repaint (0, 0, w, h); nativeWindow->repaint (0, 0, w, h);
}
void swapBuffers()
{
SwapBuffers (dc);
}
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));
}
}
}
//==============================================================================
juce_UseDebuggingNewOperator
HGLRC renderContext;
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)
{
WindowedGLContext* c = new WindowedGLContext (component,
contextToShareWith != 0 ? (HGLRC) contextToShareWith->getRawContext() : 0);
if (c->renderContext == 0 || ! c->setPixelFormat (pixelFormat))
deleteAndZero (c);
return c;
}
void juce_glViewport (const int w, const int h)
{
glViewport (0, 0, w, h);
}
void OpenGLPixelFormat::getAvailablePixelFormats (OwnedArray <OpenGLPixelFormat>& results)
{
Component tempComp;
{
WindowedGLContext wc (&tempComp, 0);
wc.makeActive();
wc.findAlternativeOpenGLPixelFormats (results);
} }
} }
#endif #endif
//==============================================================================
//============================================================================== //==============================================================================
class JuceIStorage : public IStorage class JuceIStorage : public IStorage
{ {

View file

@ -14,6 +14,7 @@ Changelist for version 1.45
- new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath. - new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath.
- added a critical section option to ReferenceCountedArray - 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 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 Changelist for version 1.44

View file

@ -13,7 +13,7 @@ ifeq ($(CONFIG),Debug)
CPPFLAGS := -MMD -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include" CPPFLAGS := -MMD -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include"
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -D_DEBUG -ggdb CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -D_DEBUG -ggdb
CXXFLAGS := $(CFLAGS) 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 := LDDEPS :=
RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include" RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include"
TARGET := jucedemo TARGET := jucedemo
@ -28,7 +28,7 @@ ifeq ($(CONFIG),Release)
CPPFLAGS := -MMD -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include" CPPFLAGS := -MMD -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include"
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O2 CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O2
CXXFLAGS := $(CFLAGS) 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 := LDDEPS :=
RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include" RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include"
TARGET := jucedemo TARGET := jucedemo

View file

@ -31,11 +31,11 @@ package.libpaths = {
} }
package.config["Debug"].links = { 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 = { 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" } package.linkflags = { "static-runtime" }

View file

@ -81,6 +81,32 @@ public:
delete im; delete im;
startTimer (20); 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() ~DemoOpenGLCanvas()

View file

@ -29,229 +29,216 @@
============================================================================== ==============================================================================
*/ */
#ifdef _MSC_VER #include "../../../../juce_core/basics/juce_StandardHeader.h"
#pragma warning (disable: 4514)
#pragma warning (push)
#endif
#include "../../../../../juce_Config.h"
#if JUCE_OPENGL #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 BEGIN_JUCE_NAMESPACE
#undef KeyPress
#include "juce_OpenGLComponent.h" #include "juce_OpenGLComponent.h"
#include "../../graphics/geometry/juce_RectangleList.h"
#include "../../../events/juce_Timer.h"
#include "../layout/juce_ComponentMovementWatcher.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);
//============================================================================== //==============================================================================
class InternalGLContextHolder : public ComponentMovementWatcher extern void juce_glViewport (const int w, const int h);
//==============================================================================
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;
}
//==============================================================================
class OpenGLComponentWatcher : public ComponentMovementWatcher
{
public: public:
bool needToUpdateViewport;
//============================================================================== //==============================================================================
InternalGLContextHolder (OpenGLComponent* const owner_, OpenGLComponentWatcher (OpenGLComponent* const owner_)
InternalGLContextHolder* const sharedContext_)
: ComponentMovementWatcher (owner_), : ComponentMovementWatcher (owner_),
owner (owner_), owner (owner_),
context (0), wasShowing (false)
sharedContext (sharedContext_),
wasShowing (false),
needToUpdateViewport (true)
{ {
} }
~InternalGLContextHolder() ~OpenGLComponentWatcher() {}
{
release();
}
//==============================================================================
void release()
{
if (context != 0)
{
juce_deleteOpenGLContext (context);
context = 0;
}
}
void initialise()
{
jassert (context == 0);
if (context == 0)
{
context = juce_createOpenGLContext (owner,
sharedContext != 0 ? sharedContext->context
: 0);
if (context != 0)
{
componentMovedOrResized (true, true);
if (makeCurrent())
owner->newOpenGLContextCreated();
}
}
}
//==============================================================================
bool makeCurrent() const
{
return context != 0 && juce_makeOpenGLContextCurrent (context);
}
bool isActive() const throw()
{
return context != 0 && juce_isActiveOpenGLContext (context);
}
void swapBuffers() const
{
if (context != 0)
juce_swapOpenGLBuffers (context);
}
void repaint() const
{
if (context != 0)
juce_repaintOpenGLWindow (context);
}
//============================================================================== //==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{ {
if (owner->getWidth() > 0 && owner->getHeight() > 0) owner->updateContextPosition();
{
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);
}
}
} }
void componentPeerChanged() void componentPeerChanged()
{ {
release(); const ScopedLock sl (owner->getContextLock());
owner->deleteContext();
if (owner->isShowing() && owner->getTopLevelComponent()->getPeer() != 0) owner->createContext();
initialise();
} }
void componentVisibilityChanged (Component&) void componentVisibilityChanged (Component&)
{ {
if (wasShowing != owner->isShowing()) const bool isShowingNow = owner->isShowing();
if (wasShowing != isShowingNow)
{ {
wasShowing = owner->isShowing(); wasShowing = isShowingNow;
componentMovedOrResized (true, true); owner->updateContextPosition();
} }
} }
//==============================================================================
juce_UseDebuggingNewOperator
private:
OpenGLComponent* const owner;
bool wasShowing;
}; };
//============================================================================== //==============================================================================
OpenGLComponent::OpenGLComponent (OpenGLComponent* share) OpenGLComponent::OpenGLComponent()
: context (0),
componentToShareListsWith (0),
needToUpdateViewport (true)
{ {
setOpaque (true); setOpaque (true);
internalData = new InternalGLContextHolder (this, (InternalGLContextHolder*) (share != 0 ? share->internalData : 0)); componentWatcher = new OpenGLComponentWatcher (this);
activeGLWindows.add (this);
} }
OpenGLComponent::~OpenGLComponent() OpenGLComponent::~OpenGLComponent()
{ {
activeGLWindows.removeValue ((void*) this); deleteContext();
delete componentWatcher;
}
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; void OpenGLComponent::createContext()
delete context; {
const ScopedLock sl (contextLock);
jassert (context == 0);
if (context == 0 && isShowing() && getTopLevelComponent()->getPeer() != 0)
{
context = OpenGLContext::createContextForWindow (this,
preferredPixelFormat,
componentToShareListsWith != 0
? componentToShareListsWith->context
: 0);
if (context != 0)
{
updateContextPosition();
if (makeCurrentContextActive())
newOpenGLContextCreated();
}
}
}
void OpenGLComponent::deleteContext()
{
const ScopedLock sl (contextLock);
deleteAndZero (context);
}
void OpenGLComponent::updateContextPosition()
{
needToUpdateViewport = true;
if (getWidth() > 0 && getHeight() > 0)
{
Component* const topComp = getTopLevelComponent();
if (topComp->getPeer() != 0)
{
const ScopedLock sl (contextLock);
if (context == 0)
createContext();
if (context != 0)
context->updateWindowPosition (getScreenX() - topComp->getScreenX(),
getScreenY() - topComp->getScreenY(),
getWidth(),
getHeight(),
topComp->getHeight());
}
}
}
const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const
{
OpenGLPixelFormat pf;
const ScopedLock sl (contextLock);
if (context != 0)
pf = context->getPixelFormat();
return pf;
}
bool OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse)
{
if (preferredPixelFormat == formatToUse)
return true;
const ScopedLock sl (contextLock);
deleteContext();
preferredPixelFormat = formatToUse;
createContext();
return context != 0;
}
void OpenGLComponent::shareWith (OpenGLComponent* const comp)
{
if (componentToShareListsWith != comp)
{
const ScopedLock sl (contextLock);
deleteContext();
componentToShareListsWith = comp;
createContext();
}
} }
bool OpenGLComponent::makeCurrentContextActive() bool OpenGLComponent::makeCurrentContextActive()
{ {
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; return context != 0 && context->makeActive();
return context->makeCurrent();
} }
void OpenGLComponent::makeCurrentContextInactive() void OpenGLComponent::makeCurrentContextInactive()
{ {
juce_makeOpenGLContextCurrent (0); if (context != 0)
context->makeInactive();
} }
bool OpenGLComponent::isActiveContext() const throw() bool OpenGLComponent::isActiveContext() const throw()
{ {
const InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
return context != 0 && context->isActive(); 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() void OpenGLComponent::swapBuffers()
{ {
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
if (context != 0) if (context != 0)
context->swapBuffers(); context->swapBuffers();
} }
@ -273,20 +260,19 @@ void OpenGLComponent::paint (Graphics&)
bool OpenGLComponent::renderAndSwapBuffers() bool OpenGLComponent::renderAndSwapBuffers()
{ {
const ScopedLock sl (contextLock);
if (! makeCurrentContextActive()) if (! makeCurrentContextActive())
return false; return false;
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; if (needToUpdateViewport)
if (context->needToUpdateViewport)
{ {
context->needToUpdateViewport = false; needToUpdateViewport = false;
glViewport (0, 0, getWidth(), getHeight()); juce_glViewport (getWidth(), getHeight());
} }
renderOpenGL(); renderOpenGL();
swapBuffers();
context->swapBuffers();
return true; return true;
} }
@ -295,7 +281,7 @@ void OpenGLComponent::internalRepaint (int x, int y, int w, int h)
{ {
Component::internalRepaint (x, y, w, h); Component::internalRepaint (x, y, w, h);
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData; if (context != 0)
context->repaint(); context->repaint();
} }

View file

@ -37,6 +37,119 @@
// this is used to disable OpenGL, and is defined in juce_Config.h // this is used to disable OpenGL, and is defined in juce_Config.h
#if JUCE_OPENGL || DOXYGEN #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: public:
//============================================================================== //==============================================================================
/** Creates an OpenGLComponent. /** 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. */ /** Destructor. */
~OpenGLComponent(); ~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 @see OpenGLPixelFormat::getAvailablePixelFormats()
GL commands.
If this returns false, then the context isn't active, so you should avoid
making any calls.
*/ */
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() /** Specifies another component whose OpenGL context should be shared with
this one.
This is an OpenGL feature that lets two contexts share their texture data.
*/ */
void makeCurrentContextInactive(); void shareWith (OpenGLComponent* const componentToShareListsWith);
/** Returns true if this component is the active openGL context for the
current thread.
*/
bool isActiveContext() const throw();
/** Returns the OpenGLComponent that is currently the active context for
the current thread.
*/
static OpenGLComponent* getCurrentlyActiveContextComponent() throw();
//============================================================================== //==============================================================================
/** Flips the openGL buffers over. */ /** Flips the openGL buffers over. */
@ -115,16 +214,63 @@ public:
virtual void newOpenGLContextCreated() = 0; 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. /** Calls the rendering callback, and swaps the buffers afterwards.
Called by paint(), this can be overridden if you need to decouple the rendering This is called automatically by paint() when the component needs to be rendered.
from the paint callback and render with a different thread.
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. Returns true if the operation succeeded.
*/ */
virtual bool renderAndSwapBuffers(); 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 */ /** @internal */
@ -133,13 +279,23 @@ public:
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
private: private:
friend class InternalGLContextHolder; friend class OpenGLComponentWatcher;
void* internalData; OpenGLComponentWatcher* componentWatcher;
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&); OpenGLComponent (const OpenGLComponent&);
const OpenGLComponent& operator= (const OpenGLComponent&); const OpenGLComponent& operator= (const OpenGLComponent&);
void internalRepaint (int x, int y, int w, int h);
}; };