1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/iphone/glcanvas.mm
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under iPhone
4 // Author: Stefan Csomor
7 // RCS-ID: $Id: glcanvas.cpp 54129 2008-06-11 19:30:52Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
22 #if defined(__BORLANDC__)
28 #include "wx/glcanvas.h"
33 #include "wx/settings.h"
36 #include "wx/osx/private.h"
38 #import <OpenGLES/EAGL.h>
39 #import <OpenGLES/EAGLDrawable.h>
40 #import <QuartzCore/QuartzCore.h>
42 // a lot of the code is from the OpenGL ES Template
44 // can be turned on for ES 2.0 only
45 #define USE_DEPTH_BUFFER 0
47 @interface wxUICustomOpenGLView : UIView
51 /* The pixel dimensions of the backbuffer */
55 /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
56 GLuint viewRenderbuffer, viewFramebuffer;
58 /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
59 GLuint depthRenderbuffer;
62 - (BOOL) createFramebuffer;
63 - (void) destroyFramebuffer;
67 @implementation wxUICustomOpenGLView
70 return [CAEAGLLayer class];
75 static BOOL initialized = NO;
79 wxOSXIPhoneClassAddWXMethods( self );
88 - (BOOL)createFramebuffer {
90 glGenFramebuffersOES(1, &viewFramebuffer);
91 glGenRenderbuffersOES(1, &viewRenderbuffer);
93 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
94 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
95 [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
96 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
98 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
99 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
101 if (USE_DEPTH_BUFFER) {
102 glGenRenderbuffersOES(1, &depthRenderbuffer);
103 glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
104 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
105 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
108 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
109 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
117 - (void)destroyFramebuffer {
119 glDeleteFramebuffersOES(1, &viewFramebuffer);
121 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
122 viewRenderbuffer = 0;
124 if(depthRenderbuffer) {
125 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
126 depthRenderbuffer = 0;
130 - (void) setContext:(EAGLContext*) ctx {
132 [EAGLContext setCurrentContext:ctx];
133 [self destroyFramebuffer];
134 [self createFramebuffer];
135 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
138 - (void) swapBuffers {
139 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
140 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
146 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
148 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
150 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
152 wxFAIL_MSG("NSOpenGLContext creation failed");
156 void WXGLDestroyContext( WXGLContext context )
164 WXGLContext WXGLGetCurrentContext()
166 return [EAGLContext currentContext];
169 bool WXGLSetCurrentContext(WXGLContext context)
171 [EAGLContext setCurrentContext:context];
175 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
180 [pixelFormat release];
186 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
189 NSOpenGLPixelFormatAttribute data[512];
190 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
192 NSOpenGLPFADoubleBuffer,
193 NSOpenGLPFAMinimumPolicy,
194 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
195 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
196 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
197 (NSOpenGLPixelFormatAttribute)nil
200 const NSOpenGLPixelFormatAttribute *attribs;
203 attribs = defaultAttribs;
208 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
210 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
212 switch ( attribList[arg++] )
215 //data[p++] = AGL_RGBA;
218 case WX_GL_BUFFER_SIZE:
219 //data[p++] = AGL_BUFFER_SIZE;
220 //data[p++] = attribList[arg++];
224 //data[p++]=AGL_LEVEL;
225 //data[p++]=attribList[arg++];
228 case WX_GL_DOUBLEBUFFER:
229 data[p++] = NSOpenGLPFADoubleBuffer;
233 data[p++] = NSOpenGLPFAStereo;
236 case WX_GL_AUX_BUFFERS:
237 data[p++] = NSOpenGLPFAAuxBuffers;
238 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
242 data[p++] = NSOpenGLPFAColorSize;
243 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
246 case WX_GL_MIN_GREEN:
247 //data[p++] = AGL_GREEN_SIZE;
248 //data[p++] = attribList[arg++];
252 //data[p++] = AGL_BLUE_SIZE;
253 //data[p++] = attribList[arg++];
256 case WX_GL_MIN_ALPHA:
257 data[p++] = NSOpenGLPFAAlphaSize;
258 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
261 case WX_GL_DEPTH_SIZE:
262 data[p++] = NSOpenGLPFADepthSize;
263 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
266 case WX_GL_STENCIL_SIZE:
267 data[p++] = NSOpenGLPFAStencilSize;
268 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
271 case WX_GL_MIN_ACCUM_RED:
272 data[p++] = NSOpenGLPFAAccumSize;
273 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
276 case WX_GL_MIN_ACCUM_GREEN:
277 //data[p++] = AGL_ACCUM_GREEN_SIZE;
278 //data[p++] = attribList[arg++];
281 case WX_GL_MIN_ACCUM_BLUE:
282 //data[p++] = AGL_ACCUM_BLUE_SIZE;
283 //data[p++] = attribList[arg++];
286 case WX_GL_MIN_ACCUM_ALPHA:
287 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
288 //data[p++] = attribList[arg++];
291 case WX_GL_SAMPLE_BUFFERS:
292 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
294 if ( !attribList[arg++] )
300 data[p++] = NSOpenGLPFASampleBuffers;
301 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
303 // don't use software fallback
304 data[p++] = NSOpenGLPFANoRecovery;
309 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
311 if ( !attribList[arg++] )
317 data[p++] = NSOpenGLPFASamples;
318 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
323 data[p] = (NSOpenGLPixelFormatAttribute)nil;
328 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
333 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
338 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
339 [v setContext:m_glContext];
343 #define USE_SEPARATE_VIEW 1
345 bool wxGLCanvas::Create(wxWindow *parent,
350 const wxString& name,
351 const int *attribList,
352 const wxPalette& WXUNUSED(palette))
355 m_glFormat = WXGLChoosePixelFormat(attribList);
359 #if USE_SEPARATE_VIEW
360 m_macIsUserPane = false ;
363 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
366 #if USE_SEPARATE_VIEW
367 CGRect r = wxOSXGetFrameForControl( this, pos , size ) ;
368 wxUICustomOpenGLView* v = [[wxUICustomOpenGLView alloc] initWithFrame:r];
369 CAEAGLLayer* eaglLayer = (CAEAGLLayer*) v.layer;
370 eaglLayer.opaque = YES;
371 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
372 [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
373 kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
375 m_peer = new wxWidgetIPhoneImpl( this, v );
377 MacPostControlCreate(pos, size) ;
382 wxGLCanvas::~wxGLCanvas()
385 WXGLDestroyPixelFormat(m_glFormat);
388 bool wxGLCanvas::SwapBuffers()
390 WXGLContext context = WXGLGetCurrentContext();
391 wxCHECK_MSG(context, false, wxT("should have current context"));
393 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) m_peer->GetWXWidget();
399 #endif // wxUSE_GLCANVAS