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