Fix crash when auto-sizing a wxDataViewCtrl column.
[wxWidgets.git] / src / osx / cocoa / glcanvas.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/glcanvas.mm
3 // Purpose:     wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     1998-01-01
7 // Copyright:   (c) Stefan Csomor
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #if defined(__BORLANDC__)
22     #pragma hdrstop
23 #endif
24
25 #if wxUSE_GLCANVAS
26
27 #include "wx/glcanvas.h"
28
29 #ifndef WX_PRECOMP
30     #include "wx/frame.h"
31     #include "wx/log.h"
32     #include "wx/settings.h"
33 #endif
34
35 #include "wx/osx/private.h"
36
37 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
38 {
39     WXGLContext context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
40     if ( !context )
41     {
42         wxFAIL_MSG("NSOpenGLContext creation failed");
43     }
44     return context ;
45 }
46
47 void WXGLDestroyContext( WXGLContext context )
48 {
49     if ( context )
50     {
51         [context release];
52     }
53 }
54
55 void WXGLSwapBuffers( WXGLContext context )
56 {
57     [context flushBuffer];
58 }
59
60 WXGLContext WXGLGetCurrentContext()
61 {
62     return [NSOpenGLContext currentContext];
63 }
64
65 bool WXGLSetCurrentContext(WXGLContext context)
66 {
67     [context makeCurrentContext];
68
69     return true;
70 }
71
72 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
73 {
74     if ( pixelFormat )
75     {
76         [pixelFormat release];
77     }
78 }
79
80
81 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
82 {
83     NSOpenGLPixelFormatAttribute data[512];
84     const NSOpenGLPixelFormatAttribute defaultAttribs[] =
85     {
86         NSOpenGLPFADoubleBuffer,
87         NSOpenGLPFAMinimumPolicy,
88         NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
89         NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
90         NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
91         NSOpenGLPFAAccelerated, // use hardware accelerated context
92         (NSOpenGLPixelFormatAttribute)nil
93     };
94
95     const NSOpenGLPixelFormatAttribute *attribs;
96     if ( !attribList )
97     {
98         attribs = defaultAttribs;
99     }
100     else
101     {
102         unsigned p = 0;
103         data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
104         data[p++] = NSOpenGLPFAAccelerated; // use hardware accelerated context
105
106         for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
107         {
108             switch ( attribList[arg++] )
109             {
110                 case WX_GL_RGBA:
111                     //data[p++] = AGL_RGBA;
112                     break;
113
114                 case WX_GL_BUFFER_SIZE:
115                     //data[p++] = AGL_BUFFER_SIZE;
116                     //data[p++] = attribList[arg++];
117                     break;
118
119                 case WX_GL_LEVEL:
120                     //data[p++]=AGL_LEVEL;
121                     //data[p++]=attribList[arg++];
122                     break;
123
124                 case WX_GL_DOUBLEBUFFER:
125                     data[p++] = NSOpenGLPFADoubleBuffer;
126                     break;
127
128                 case WX_GL_STEREO:
129                     data[p++] = NSOpenGLPFAStereo;
130                     break;
131
132                 case WX_GL_AUX_BUFFERS:
133                     data[p++] = NSOpenGLPFAAuxBuffers;
134                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
135                     break;
136
137                 case WX_GL_MIN_RED:
138                     data[p++] = NSOpenGLPFAColorSize;
139                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
140                     break;
141
142                 case WX_GL_MIN_GREEN:
143                     //data[p++] = AGL_GREEN_SIZE;
144                     //data[p++] = attribList[arg++];
145                     break;
146
147                 case WX_GL_MIN_BLUE:
148                     //data[p++] = AGL_BLUE_SIZE;
149                     //data[p++] = attribList[arg++];
150                     break;
151
152                 case WX_GL_MIN_ALPHA:
153                     data[p++] = NSOpenGLPFAAlphaSize;
154                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
155                     break;
156
157                 case WX_GL_DEPTH_SIZE:
158                     data[p++] = NSOpenGLPFADepthSize;
159                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
160                     break;
161
162                 case WX_GL_STENCIL_SIZE:
163                     data[p++] = NSOpenGLPFAStencilSize;
164                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
165                     break;
166
167                 case WX_GL_MIN_ACCUM_RED:
168                     data[p++] = NSOpenGLPFAAccumSize;
169                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
170                     break;
171
172                 case WX_GL_MIN_ACCUM_GREEN:
173                     //data[p++] = AGL_ACCUM_GREEN_SIZE;
174                     //data[p++] = attribList[arg++];
175                     break;
176
177                 case WX_GL_MIN_ACCUM_BLUE:
178                     //data[p++] = AGL_ACCUM_BLUE_SIZE;
179                     //data[p++] = attribList[arg++];
180                     break;
181
182                 case WX_GL_MIN_ACCUM_ALPHA:
183                     //data[p++] = AGL_ACCUM_ALPHA_SIZE;
184                     //data[p++] = attribList[arg++];
185                     break;
186
187                 case WX_GL_SAMPLE_BUFFERS:
188                     if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
189                     {
190                         if ( !attribList[arg++] )
191                             break;
192
193                         return nil;
194                     }
195
196                     data[p++] = NSOpenGLPFASampleBuffers;
197                     if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
198                     {
199                         // don't use software fallback
200                         data[p++] = NSOpenGLPFANoRecovery;
201                     }
202                     break;
203
204                 case WX_GL_SAMPLES:
205                     if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
206                     {
207                         if ( !attribList[arg++] )
208                             break;
209
210                         return nil;
211                     }
212
213                     data[p++] = NSOpenGLPFASamples;
214                     data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
215                     break;
216             }
217         }
218
219         data[p] = (NSOpenGLPixelFormatAttribute)nil;
220
221         attribs = data;
222     }
223
224     return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
225 }
226
227 @interface wxNSCustomOpenGLView : NSView
228 {
229     NSOpenGLContext* context;
230 }
231
232 @end
233
234 @implementation wxNSCustomOpenGLView
235
236 + (void)initialize
237 {
238     static BOOL initialized = NO;
239     if (!initialized)
240     {
241         initialized = YES;
242         wxOSXCocoaClassAddWXMethods( self );
243     }
244 }
245
246 - (BOOL)isOpaque
247 {
248     return YES;
249 }
250
251 @end
252
253 bool wxGLCanvas::Create(wxWindow *parent,
254                         wxWindowID id,
255                         const wxPoint& pos,
256                         const wxSize& size,
257                         long style,
258                         const wxString& name,
259                         const int *attribList,
260                         const wxPalette& WXUNUSED(palette))
261 {
262     m_glFormat = WXGLChoosePixelFormat(attribList);
263     if ( !m_glFormat )
264         return false;
265
266     // DontCreatePeer();
267     
268     if ( !wxWindow::Create(parent, id, pos, size, style, name) )
269         return false;
270
271 /*
272     NSRect r = wxOSXGetFrameForControl( this, pos , size ) ;
273     wxNSCustomOpenGLView* v = [[wxNSCustomOpenGLView alloc] initWithFrame:r];
274     m_peer = new wxWidgetCocoaImpl( this, v );
275
276     MacPostControlCreate(pos, size) ;
277 */
278     return true;
279 }
280
281 wxGLCanvas::~wxGLCanvas()
282 {
283     if ( m_glFormat )
284         WXGLDestroyPixelFormat(m_glFormat);
285 }
286
287 bool wxGLCanvas::SwapBuffers()
288 {
289     WXGLContext context = WXGLGetCurrentContext();
290     wxCHECK_MSG(context, false, wxT("should have current context"));
291
292     [context flushBuffer];
293
294     return true;
295 }
296
297 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
298 {
299     if ( !m_glContext )
300         return false;  
301
302     [m_glContext setView: win.GetHandle() ];
303     [m_glContext update];
304     
305     [m_glContext makeCurrentContext];
306     
307     return true;
308 }
309
310 #endif // wxUSE_GLCANVAS