]> git.saurik.com Git - wxWidgets.git/blob - src/osx/iphone/glcanvas.mm
Allow unsetting wxMenuItem as start of radio group too.
[wxWidgets.git] / src / osx / iphone / glcanvas.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/iphone/glcanvas.mm
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under iPhone
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #if defined(__BORLANDC__)
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_GLCANVAS
27
28 #include "wx/glcanvas.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/frame.h"
32 #include "wx/log.h"
33 #include "wx/settings.h"
34 #endif
35
36 #include "wx/osx/private.h"
37
38 #import <OpenGLES/EAGL.h>
39 #import <OpenGLES/EAGLDrawable.h>
40 #import <QuartzCore/QuartzCore.h>
41
42 // a lot of the code is from the OpenGL ES Template
43
44 // can be turned on for ES 2.0 only
45 #define USE_DEPTH_BUFFER 0
46
47 @interface wxUICustomOpenGLView : UIView
48 {
49 CGRect oldRect;
50 EAGLContext* context;
51
52 /* The pixel dimensions of the backbuffer */
53 GLint backingWidth;
54 GLint backingHeight;
55
56 /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
57 GLuint viewRenderbuffer, viewFramebuffer;
58
59 /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
60 GLuint depthRenderbuffer;
61 }
62
63 - (BOOL) createFramebuffer;
64 - (void) destroyFramebuffer;
65 - (id) initWithFrame:(CGRect) rect;
66
67 @end
68
69 @implementation wxUICustomOpenGLView
70
71 + (Class)layerClass {
72 return [CAEAGLLayer class];
73 }
74
75 + (void)initialize
76 {
77 static BOOL initialized = NO;
78 if (!initialized)
79 {
80 initialized = YES;
81 wxOSXIPhoneClassAddWXMethods( self );
82 }
83 }
84
85 - (id) initWithFrame:(CGRect)rect
86 {
87 if ( !(self=[super initWithFrame:rect]) )
88 return nil;
89
90 oldRect = rect;
91 return self;
92 }
93
94 - (BOOL)isOpaque
95 {
96 return YES;
97 }
98
99 - (BOOL)createFramebuffer {
100
101 glGenFramebuffersOES(1, &viewFramebuffer);
102 glGenRenderbuffersOES(1, &viewRenderbuffer);
103 glEnable(GL_CULL_FACE);
104
105 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
106 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
107 [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
108 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
109
110 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
111 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
112
113 if (USE_DEPTH_BUFFER) {
114 glGenRenderbuffersOES(1, &depthRenderbuffer);
115 glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
116 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
117 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
118 }
119
120 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
121 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
122 return NO;
123 }
124
125 return YES;
126 }
127
128
129 - (void)destroyFramebuffer {
130
131 glDeleteFramebuffersOES(1, &viewFramebuffer);
132 viewFramebuffer = 0;
133 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
134 viewRenderbuffer = 0;
135
136 if(depthRenderbuffer) {
137 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
138 depthRenderbuffer = 0;
139 }
140 }
141
142 - (void) setContext:(EAGLContext*) ctx {
143 context = ctx;
144 [EAGLContext setCurrentContext:ctx];
145
146 if ( viewFramebuffer == 0 )
147 {
148 [self destroyFramebuffer];
149 [self createFramebuffer];
150 }
151
152 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
153 }
154
155 - (void) swapBuffers {
156 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
157 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
158 }
159
160 - (void)layoutSubviews {
161 [EAGLContext setCurrentContext:context];
162 [self destroyFramebuffer];
163 [self createFramebuffer];
164 }
165
166 @end
167
168
169 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
170 {
171 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
172
173 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
174 if ( !context )
175 wxFAIL_MSG("NSOpenGLContext creation failed");
176 return context ;
177 }
178
179 void WXGLDestroyContext( WXGLContext context )
180 {
181 if ( context )
182 {
183 [context release];
184 }
185 }
186
187 WXGLContext WXGLGetCurrentContext()
188 {
189 return [EAGLContext currentContext];
190 }
191
192 bool WXGLSetCurrentContext(WXGLContext context)
193 {
194 [EAGLContext setCurrentContext:context];
195 return true;
196 }
197
198 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
199 {
200 /*
201 if ( pixelFormat )
202 {
203 [pixelFormat release];
204 }
205 */
206 }
207
208
209 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
210 {
211 #if 0
212 NSOpenGLPixelFormatAttribute data[512];
213 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
214 {
215 NSOpenGLPFADoubleBuffer,
216 NSOpenGLPFAMinimumPolicy,
217 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
218 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
219 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
220 (NSOpenGLPixelFormatAttribute)nil
221 };
222
223 const NSOpenGLPixelFormatAttribute *attribs;
224 if ( !attribList )
225 {
226 attribs = defaultAttribs;
227 }
228 else
229 {
230 unsigned p = 0;
231 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
232
233 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
234 {
235 switch ( attribList[arg++] )
236 {
237 case WX_GL_RGBA:
238 //data[p++] = AGL_RGBA;
239 break;
240
241 case WX_GL_BUFFER_SIZE:
242 //data[p++] = AGL_BUFFER_SIZE;
243 //data[p++] = attribList[arg++];
244 break;
245
246 case WX_GL_LEVEL:
247 //data[p++]=AGL_LEVEL;
248 //data[p++]=attribList[arg++];
249 break;
250
251 case WX_GL_DOUBLEBUFFER:
252 data[p++] = NSOpenGLPFADoubleBuffer;
253 break;
254
255 case WX_GL_STEREO:
256 data[p++] = NSOpenGLPFAStereo;
257 break;
258
259 case WX_GL_AUX_BUFFERS:
260 data[p++] = NSOpenGLPFAAuxBuffers;
261 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
262 break;
263
264 case WX_GL_MIN_RED:
265 data[p++] = NSOpenGLPFAColorSize;
266 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
267 break;
268
269 case WX_GL_MIN_GREEN:
270 //data[p++] = AGL_GREEN_SIZE;
271 //data[p++] = attribList[arg++];
272 break;
273
274 case WX_GL_MIN_BLUE:
275 //data[p++] = AGL_BLUE_SIZE;
276 //data[p++] = attribList[arg++];
277 break;
278
279 case WX_GL_MIN_ALPHA:
280 data[p++] = NSOpenGLPFAAlphaSize;
281 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
282 break;
283
284 case WX_GL_DEPTH_SIZE:
285 data[p++] = NSOpenGLPFADepthSize;
286 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
287 break;
288
289 case WX_GL_STENCIL_SIZE:
290 data[p++] = NSOpenGLPFAStencilSize;
291 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
292 break;
293
294 case WX_GL_MIN_ACCUM_RED:
295 data[p++] = NSOpenGLPFAAccumSize;
296 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
297 break;
298
299 case WX_GL_MIN_ACCUM_GREEN:
300 //data[p++] = AGL_ACCUM_GREEN_SIZE;
301 //data[p++] = attribList[arg++];
302 break;
303
304 case WX_GL_MIN_ACCUM_BLUE:
305 //data[p++] = AGL_ACCUM_BLUE_SIZE;
306 //data[p++] = attribList[arg++];
307 break;
308
309 case WX_GL_MIN_ACCUM_ALPHA:
310 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
311 //data[p++] = attribList[arg++];
312 break;
313
314 case WX_GL_SAMPLE_BUFFERS:
315 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
316 {
317 if ( !attribList[arg++] )
318 break;
319
320 return false;
321 }
322
323 data[p++] = NSOpenGLPFASampleBuffers;
324 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
325 {
326 // don't use software fallback
327 data[p++] = NSOpenGLPFANoRecovery;
328 }
329 break;
330
331 case WX_GL_SAMPLES:
332 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
333 {
334 if ( !attribList[arg++] )
335 break;
336
337 return false;
338 }
339
340 data[p++] = NSOpenGLPFASamples;
341 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
342 break;
343 }
344 }
345
346 data[p] = (NSOpenGLPixelFormatAttribute)nil;
347
348 attribs = data;
349 }
350
351 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
352 #endif
353 return NULL;
354 }
355
356 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
357 {
358 if ( !m_glContext )
359 return false;
360
361 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
362 [v setContext:m_glContext];
363 return true;
364 }
365
366 #define USE_SEPARATE_VIEW 1
367
368 bool wxGLCanvas::Create(wxWindow *parent,
369 wxWindowID id,
370 const wxPoint& pos,
371 const wxSize& size,
372 long style,
373 const wxString& name,
374 const int *attribList,
375 const wxPalette& WXUNUSED(palette))
376 {
377 /*
378 m_glFormat = WXGLChoosePixelFormat(attribList);
379 if ( !m_glFormat )
380 return false;
381 */
382 #if USE_SEPARATE_VIEW
383 DontCreatePeer();
384 #endif
385
386 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
387 return false;
388
389 #if USE_SEPARATE_VIEW
390 CGRect r = wxOSXGetFrameForControl( this, pos , size ) ;
391 wxUICustomOpenGLView* v = [[wxUICustomOpenGLView alloc] initWithFrame:r];
392 CAEAGLLayer* eaglLayer = (CAEAGLLayer*) v.layer;
393 eaglLayer.opaque = YES;
394 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
395 [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
396 kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
397
398 SetPeer(new wxWidgetIPhoneImpl( this, v ));
399
400 MacPostControlCreate(pos, size) ;
401 #endif
402 return true;
403 }
404
405 wxGLCanvas::~wxGLCanvas()
406 {
407 if ( m_glFormat )
408 WXGLDestroyPixelFormat(m_glFormat);
409 }
410
411 bool wxGLCanvas::SwapBuffers()
412 {
413 WXGLContext context = WXGLGetCurrentContext();
414 wxCHECK_MSG(context, false, wxT("should have current context"));
415
416 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) GetPeer()->GetWXWidget();
417 [v swapBuffers];
418 return true;
419 }
420
421
422 #endif // wxUSE_GLCANVAS