]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/glcanvas.cpp
use correct scale when drawing
[wxWidgets.git] / src / osx / carbon / glcanvas.cpp
index 7d265bc1d602b69ae8d97e96d9672b5b1b8288e3..8268a38ae6856a9c850a75cdc33e4de6ad60d65a 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/glcanvas.cpp
+// Name:        src/osx/carbon/glcanvas.cpp
 // Purpose:     wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
 // Author:      Stefan Csomor
 // Modified by:
     #include "wx/settings.h"
 #endif
 
-#include "wx/mac/uma.h"
+#include "wx/osx/uma.h"
 
-#include "wx/mac/private.h"
+#include "wx/osx/private.h"
+#include <AGL/agl.h>
 
 // ----------------------------------------------------------------------------
 // helper functions
@@ -54,146 +55,53 @@ static void wxLogAGLError(const char *func)
 // ============================================================================
 
 // ----------------------------------------------------------------------------
-// wxGLContext
+// low level implementation routines
 // ----------------------------------------------------------------------------
 
-wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext *other)
+WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
 {
-    m_aglContext = aglCreateContext(win->GetAGLPixelFormat(),
-                                    other ? other->m_aglContext : NULL);
-    if ( !m_aglContext )
+    WXGLContext context = aglCreateContext(pixelFormat, shareContext);
+    if ( !context )
         wxLogAGLError("aglCreateContext");
+    return context ;
 }
 
-wxGLContext::~wxGLContext()
+void WXGLDestroyContext( WXGLContext context )
 {
-    if ( m_aglContext )
+    if ( context )
     {
-        // it's ok to pass the current context to this function
-        if ( !aglDestroyContext(m_aglContext) )
+        if ( !aglDestroyContext(context) )
+        {
             wxLogAGLError("aglDestroyContext");
+        }
     }
 }
 
-bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+WXGLContext WXGLGetCurrentContext()
 {
-    if ( !m_aglContext )
-        return false;
-
-    AGLDrawable drawable = (AGLDrawable)GetWindowPort(
-                                MAC_WXHWND(win.MacGetTopLevelWindowRef()));
-    if ( !aglSetDrawable(m_aglContext, drawable) )
-    {
-        wxLogAGLError("aglSetDrawable");
-        return false;
-    }
+    return aglGetCurrentContext();
+}
 
-    if ( !aglSetCurrentContext(m_aglContext) )
+bool WXGLSetCurrentContext(WXGLContext context)
+{
+    if ( !aglSetCurrentContext(context) )
     {
         wxLogAGLError("aglSetCurrentContext");
         return false;
     }
 
-    wx_const_cast(wxGLCanvas&, win).SetViewport();
     return true;
 }
 
-// ----------------------------------------------------------------------------
-// wxGLCanvas
-// ----------------------------------------------------------------------------
-
-IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
-
-BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
-    EVT_SIZE(wxGLCanvas::OnSize)
-END_EVENT_TABLE()
-
-wxGLCanvas::wxGLCanvas(wxWindow *parent,
-                       wxWindowID id,
-                       const int *attribList,
-                       const wxPoint& pos,
-                       const wxSize& size,
-                       long style,
-                       const wxString& name,
-                       const wxPalette& palette)
-{
-    Create(parent, id, pos, size, style, name, attribList, palette);
-}
-
-#if WXWIN_COMPATIBILITY_2_8
-
-wxGLCanvas::wxGLCanvas(wxWindow *parent,
-                       wxWindowID id,
-                       const wxPoint& pos,
-                       const wxSize& size,
-                       long style,
-                       const wxString& name,
-                       const int *attribList,
-                       const wxPalette& palette)
-{
-    if ( Create(parent, id, pos, size, style, name, attribList, palette) )
-        m_glContext = new wxGLContext(this);
-}
-
-wxGLCanvas::wxGLCanvas(wxWindow *parent,
-                       const wxGLContext *shared,
-                       wxWindowID id,
-                       const wxPoint& pos,
-                       const wxSize& size,
-                       long style,
-                       const wxString& name,
-                       const int *attribList,
-                       const wxPalette& palette)
-{
-    if ( Create(parent, id, pos, size, style, name, attribList, palette) )
-        m_glContext = new wxGLContext(this, shared);
-}
-
-wxGLCanvas::wxGLCanvas(wxWindow *parent,
-                       const wxGLCanvas *shared,
-                       wxWindowID id,
-                       const wxPoint& pos,
-                       const wxSize& size,
-                       long style,
-                       const wxString& name,
-                       const int *attribList,
-                       const wxPalette& palette)
-{
-    if ( Create(parent, id, pos, size, style, name, attribList, palette) )
-        m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
-}
-
-#endif // WXWIN_COMPATIBILITY_2_8
-
-/* static */
-bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
-{
-    // we need a valid context to query for extensions.
-    const GLint defaultAttribs[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NONE };
-    AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, defaultAttribs);
-    AGLContext ctx = aglCreateContext(fmt, NULL);
-    if ( !ctx )
-        return false;
-
-    wxString extensions = wxString::FromAscii(glGetString(GL_EXTENSIONS));
-
-    aglDestroyPixelFormat(fmt);
-    aglDestroyContext(ctx);
-
-    return IsExtensionInList(extensions, extension);
-}
-
-/* static */
-bool wxGLCanvas::IsAGLMultiSampleAvailable()
+void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
 {
-    static int s_isMultiSampleAvailable = -1;
-    if ( s_isMultiSampleAvailable == -1 )
-        s_isMultiSampleAvailable = IsExtensionSupported("GL_ARB_multisample");
-
-    return s_isMultiSampleAvailable != 0;
+    if ( pixelFormat )
+    {
+        aglDestroyPixelFormat(pixelFormat);
+    }
 }
 
-static AGLPixelFormat ChoosePixelFormat(const int *attribList)
+WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
 {
     GLint data[512];
     const GLint defaultAttribs[] =
@@ -306,7 +214,7 @@ static AGLPixelFormat ChoosePixelFormat(const int *attribList)
                         if ( !attribList[arg++] )
                             break;
 
-                        return false;
+                        return NULL;
                     }
 
                     data[p++] = AGL_SAMPLE_BUFFERS_ARB;
@@ -323,7 +231,7 @@ static AGLPixelFormat ChoosePixelFormat(const int *attribList)
                         if ( !attribList[arg++] )
                             break;
 
-                        return false;
+                        return NULL;
                     }
 
                     data[p++] = AGL_SAMPLES_ARB;
@@ -340,6 +248,88 @@ static AGLPixelFormat ChoosePixelFormat(const int *attribList)
     return aglChoosePixelFormat(NULL, 0, attribs);
 }
 
+// ----------------------------------------------------------------------------
+// wxGLContext
+// ----------------------------------------------------------------------------
+
+bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+{
+    if ( !m_glContext )
+        return false;
+
+    GLint bufnummer = win.GetAglBufferName();
+    aglSetInteger(m_glContext, AGL_BUFFER_NAME, &bufnummer);
+    //win.SetLastContext(m_glContext);
+
+    const_cast<wxGLCanvas&>(win).SetViewport();
+
+    
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+    if ( UMAGetSystemVersion() >= 0x1050 )
+    {
+        aglSetWindowRef(m_glContext, win.MacGetTopLevelWindowRef());
+    }
+    else
+#endif
+    {
+        AGLDrawable drawable = (AGLDrawable)GetWindowPort(
+                                                      MAC_WXHWND(win.MacGetTopLevelWindowRef()));
+    
+        if ( !aglSetDrawable(m_glContext, drawable) )
+        {
+            wxLogAGLError("aglSetDrawable");
+            return false;
+        }
+    }
+
+    return WXGLSetCurrentContext(m_glContext);
+}
+
+// ----------------------------------------------------------------------------
+// wxGLCanvas
+// ----------------------------------------------------------------------------
+
+/*
+
+sharing contexts under AGL is not straightforward, to quote from
+
+http://lists.apple.com/archives/mac-opengl/2003/Jan/msg00402.html :
+
+In Carbon OpenGL (AGL) you would use call aglSetInteger to setup a
+buffer name and attached each context to that same name. From AGL
+you can do:
+
+GLint id = 1;
+
+ctx1 = aglCreateContext...
+aglSetInteger(ctx1, AGL_BUFFER_NAME, &id); // create name
+aglAttachDrawable (ctx1,...); // create surface with associated with
+name (first time)
+ctx2 = aglCreateContext...
+aglSetInteger(ctx2, AGL_BUFFER_NAME, &id); // uses previously created name
+aglAttachDrawable (ctx2, ...); // uses existing surface with existing name
+
+AGL Docs say:
+AGL_BUFFER_NAME
+params contains one value: a non-negative integer name of the surface to be
+associated to be with the current context. If this value is non-zero, and a
+surface of this name is not associated to this drawable, a new surface with
+this name is created and associated with the context when
+aglSetDrawable is called subsequently. If this is a previously allocated
+buffer name within the namespace of the current window (e.g., drawable),
+that previously allocated surface is associated with the context (e.g., no
+new surface is created) and the subsequent call to aglSetDrawable will
+attach that surface. This allows multiple contexts to be attached to a single
+surface. Using the default buffer name zero, returns to one surface per
+context behaviour.
+*/
+
+/*
+so what I'm doing is to have a dummy aglContext attached to a wxGLCanvas,
+assign it a buffer number
+*/
+
+
 bool wxGLCanvas::Create(wxWindow *parent,
                         wxWindowID id,
                         const wxPoint& pos,
@@ -352,13 +342,31 @@ bool wxGLCanvas::Create(wxWindow *parent,
     m_needsUpdate = false;
     m_macCanvasIsShown = false;
 
-    m_aglFormat = ChoosePixelFormat(attribList);
-    if ( !m_aglFormat )
+    m_glFormat = WXGLChoosePixelFormat(attribList);
+    if ( !m_glFormat )
         return false;
 
     if ( !wxWindow::Create(parent, id, pos, size, style, name) )
         return false;
 
+    m_dummyContext = WXGLCreateContext(m_glFormat, NULL);
+
+    static GLint gCurrentBufferName = 1;
+    m_bufferName = gCurrentBufferName++;
+    aglSetInteger (m_dummyContext, AGL_BUFFER_NAME, &m_bufferName);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+    if ( UMAGetSystemVersion() >= 0x1050 )
+    {
+        aglSetWindowRef(m_dummyContext, MacGetTopLevelWindowRef());
+    }
+    else
+#endif
+    {
+        AGLDrawable drawable = (AGLDrawable)GetWindowPort(MAC_WXHWND(MacGetTopLevelWindowRef()));
+        aglSetDrawable(m_dummyContext, drawable);
+    }
+
     m_macCanvasIsShown = true;
 
     return true;
@@ -366,27 +374,17 @@ bool wxGLCanvas::Create(wxWindow *parent,
 
 wxGLCanvas::~wxGLCanvas()
 {
-    if ( m_aglFormat )
-        aglDestroyPixelFormat(m_aglFormat);
-}
-
-/* static */
-bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
-{
-    AGLPixelFormat aglFormat = ChoosePixelFormat(attribList);
+    if ( m_glFormat )
+        WXGLDestroyPixelFormat(m_glFormat);
 
-    if ( !aglFormat )
-       return false;
-
-    aglDestroyPixelFormat(aglFormat);
-
-    return true;
+    if ( m_dummyContext )
+        WXGLDestroyContext(m_dummyContext);
 }
 
 bool wxGLCanvas::SwapBuffers()
 {
-    AGLContext context = aglGetCurrentContext();
-    wxCHECK_MSG(context, false, _T("should have current context"));
+    WXGLContext context = WXGLGetCurrentContext();
+    wxCHECK_MSG(context, false, wxT("should have current context"));
 
     aglSwapBuffers(context);
     return true;
@@ -399,9 +397,9 @@ void wxGLCanvas::SetViewport()
 
     m_needsUpdate = false;
 
-    AGLContext context = aglGetCurrentContext();
-    if ( !context )
-        return;
+//    AGLContext context = aglGetCurrentContext();
+//    if ( !context )
+//        return;
 
     // viewport is initially set to entire port, adjust it to just this window
     int x = 0,
@@ -414,36 +412,23 @@ void wxGLCanvas::SetViewport()
     Rect bounds;
     GetWindowPortBounds(MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds);
 
-#if 0
-    // TODO in case we adopt point vs pixel coordinates, this will make the conversion
-    HIRect hiRect = CGRectMake( x, y, width, height );
-    HIRectConvert( &hiRect, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
-    HIRect hiBounds = CGRectMake( 0, 0, bounds.right - bounds.left , bounds.bottom - bounds.top );
-    HIRectConvert( &hiBounds, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
-    GLint parms[4];
-    parms[0] = hiRect.origin.x;
-    parms[1] = hiBounds.size.height - (hiRect.origin.y + hiRect.size.height);
-    parms[2] = hiRect.size.width;
-    parms[3] = hiRect.size.height;
-#else
     GLint parms[4];
     parms[0] = x;
     parms[1] = bounds.bottom - bounds.top - ( y + height );
     parms[2] = width;
     parms[3] = height;
-#endif
 
     // move the buffer rect out of sight if we're hidden
     if ( !m_macCanvasIsShown )
         parms[0] += 20000;
 
-    if ( !aglSetInteger(context, AGL_BUFFER_RECT, parms) )
+    if ( !aglSetInteger(m_dummyContext, AGL_BUFFER_RECT, parms) )
         wxLogAGLError("aglSetInteger(AGL_BUFFER_RECT)");
 
-    if ( !aglEnable(context, AGL_BUFFER_RECT) )
+    if ( !aglEnable(m_dummyContext, AGL_BUFFER_RECT) )
         wxLogAGLError("aglEnable(AGL_BUFFER_RECT)");
 
-    if ( !aglUpdateContext(context) )
+    if ( !aglUpdateContext(m_dummyContext) )
         wxLogAGLError("aglUpdateContext");
 }
 
@@ -462,6 +447,7 @@ void wxGLCanvas::MacUpdateView()
 void wxGLCanvas::MacSuperChangedPosition()
 {
     MacUpdateView();
+    SetViewport();
     wxWindow::MacSuperChangedPosition();
 }
 
@@ -482,18 +468,4 @@ void wxGLCanvas::MacVisibilityChanged()
     wxWindowMac::MacVisibilityChanged();
 }
 
-// ----------------------------------------------------------------------------
-// wxGLApp
-// ----------------------------------------------------------------------------
-
-bool wxGLApp::InitGLVisual(const int *attribList)
-{
-    AGLPixelFormat fmt = ChoosePixelFormat(attribList);
-    if ( !fmt )
-        return false;
-
-    aglDestroyPixelFormat(fmt);
-    return true;
-}
-
 #endif // wxUSE_GLCANVAS