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);
92 glEnable(GL_CULL_FACE);
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);
99 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
100 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
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);
109 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
110 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
118 - (void)destroyFramebuffer {
120 glDeleteFramebuffersOES(1, &viewFramebuffer);
122 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
123 viewRenderbuffer = 0;
125 if(depthRenderbuffer) {
126 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
127 depthRenderbuffer = 0;
131 - (void) setContext:(EAGLContext*) ctx {
133 [EAGLContext setCurrentContext:ctx];
134 [self destroyFramebuffer];
135 [self createFramebuffer];
136 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
139 - (void) swapBuffers {
140 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
141 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
147 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
149 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
151 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
153 wxFAIL_MSG("NSOpenGLContext creation failed");
157 void WXGLDestroyContext( WXGLContext context )
165 WXGLContext WXGLGetCurrentContext()
167 return [EAGLContext currentContext];
170 bool WXGLSetCurrentContext(WXGLContext context)
172 [EAGLContext setCurrentContext:context];
176 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
181 [pixelFormat release];
187 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
190 NSOpenGLPixelFormatAttribute data[512];
191 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
193 NSOpenGLPFADoubleBuffer,
194 NSOpenGLPFAMinimumPolicy,
195 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
196 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
197 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
198 (NSOpenGLPixelFormatAttribute)nil
201 const NSOpenGLPixelFormatAttribute *attribs;
204 attribs = defaultAttribs;
209 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
211 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
213 switch ( attribList[arg++] )
216 //data[p++] = AGL_RGBA;
219 case WX_GL_BUFFER_SIZE:
220 //data[p++] = AGL_BUFFER_SIZE;
221 //data[p++] = attribList[arg++];
225 //data[p++]=AGL_LEVEL;
226 //data[p++]=attribList[arg++];
229 case WX_GL_DOUBLEBUFFER:
230 data[p++] = NSOpenGLPFADoubleBuffer;
234 data[p++] = NSOpenGLPFAStereo;
237 case WX_GL_AUX_BUFFERS:
238 data[p++] = NSOpenGLPFAAuxBuffers;
239 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
243 data[p++] = NSOpenGLPFAColorSize;
244 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
247 case WX_GL_MIN_GREEN:
248 //data[p++] = AGL_GREEN_SIZE;
249 //data[p++] = attribList[arg++];
253 //data[p++] = AGL_BLUE_SIZE;
254 //data[p++] = attribList[arg++];
257 case WX_GL_MIN_ALPHA:
258 data[p++] = NSOpenGLPFAAlphaSize;
259 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
262 case WX_GL_DEPTH_SIZE:
263 data[p++] = NSOpenGLPFADepthSize;
264 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
267 case WX_GL_STENCIL_SIZE:
268 data[p++] = NSOpenGLPFAStencilSize;
269 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
272 case WX_GL_MIN_ACCUM_RED:
273 data[p++] = NSOpenGLPFAAccumSize;
274 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
277 case WX_GL_MIN_ACCUM_GREEN:
278 //data[p++] = AGL_ACCUM_GREEN_SIZE;
279 //data[p++] = attribList[arg++];
282 case WX_GL_MIN_ACCUM_BLUE:
283 //data[p++] = AGL_ACCUM_BLUE_SIZE;
284 //data[p++] = attribList[arg++];
287 case WX_GL_MIN_ACCUM_ALPHA:
288 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
289 //data[p++] = attribList[arg++];
292 case WX_GL_SAMPLE_BUFFERS:
293 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
295 if ( !attribList[arg++] )
301 data[p++] = NSOpenGLPFASampleBuffers;
302 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
304 // don't use software fallback
305 data[p++] = NSOpenGLPFANoRecovery;
310 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
312 if ( !attribList[arg++] )
318 data[p++] = NSOpenGLPFASamples;
319 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
324 data[p] = (NSOpenGLPixelFormatAttribute)nil;
329 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
334 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
339 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
340 [v setContext:m_glContext];
344 #define USE_SEPARATE_VIEW 1
346 bool wxGLCanvas::Create(wxWindow *parent,
351 const wxString& name,
352 const int *attribList,
353 const wxPalette& WXUNUSED(palette))
356 m_glFormat = WXGLChoosePixelFormat(attribList);
360 #if USE_SEPARATE_VIEW
361 m_macIsUserPane = false ;
364 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
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];
376 m_peer = new wxWidgetIPhoneImpl( this, v );
378 MacPostControlCreate(pos, size) ;
383 wxGLCanvas::~wxGLCanvas()
386 WXGLDestroyPixelFormat(m_glFormat);
389 bool wxGLCanvas::SwapBuffers()
391 WXGLContext context = WXGLGetCurrentContext();
392 wxCHECK_MSG(context, false, wxT("should have current context"));
394 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) m_peer->GetWXWidget();
400 #endif // wxUSE_GLCANVAS