]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/iphone/glcanvas.mm
Add wxTimer::StartOnce().
[wxWidgets.git] / src / osx / iphone / glcanvas.mm
... / ...
CommitLineData
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
169WXGLContext 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
179void WXGLDestroyContext( WXGLContext context )
180{
181 if ( context )
182 {
183 [context release];
184 }
185}
186
187WXGLContext WXGLGetCurrentContext()
188{
189 return [EAGLContext currentContext];
190}
191
192bool WXGLSetCurrentContext(WXGLContext context)
193{
194 [EAGLContext setCurrentContext:context];
195 return true;
196}
197
198void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
199{
200/*
201 if ( pixelFormat )
202 {
203 [pixelFormat release];
204 }
205*/
206}
207
208
209WXGLPixelFormat 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
356bool 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
368bool 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
405wxGLCanvas::~wxGLCanvas()
406{
407 if ( m_glFormat )
408 WXGLDestroyPixelFormat(m_glFormat);
409}
410
411bool 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