| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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" } | |||
| @@ -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() | |||
| @@ -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(); | |||
| } | |||
| @@ -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&); | |||
| }; | |||