1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/iphone/glcanvas.mm
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under iPhone
4 // Author: Stefan Csomor
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
52 /* The pixel dimensions of the backbuffer */
56 /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
57 GLuint viewRenderbuffer, viewFramebuffer;
59 /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
60 GLuint depthRenderbuffer;
63 - (BOOL) createFramebuffer;
64 - (void) destroyFramebuffer;
65 - (id) initWithFrame:(CGRect) rect;
69 @implementation wxUICustomOpenGLView
72 return [CAEAGLLayer class];
77 static BOOL initialized = NO;
81 wxOSXIPhoneClassAddWXMethods( self );
85 - (id) initWithFrame:(CGRect)rect
87 if ( !(self=[super initWithFrame:rect]) )
99 - (BOOL)createFramebuffer {
101 glGenFramebuffersOES(1, &viewFramebuffer);
102 glGenRenderbuffersOES(1, &viewRenderbuffer);
103 glEnable(GL_CULL_FACE);
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);
110 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
111 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
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);
120 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
121 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
129 - (void)destroyFramebuffer {
131 glDeleteFramebuffersOES(1, &viewFramebuffer);
133 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
134 viewRenderbuffer = 0;
136 if(depthRenderbuffer) {
137 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
138 depthRenderbuffer = 0;
142 - (void) setContext:(EAGLContext*) ctx {
144 [EAGLContext setCurrentContext:ctx];
146 if ( viewFramebuffer == 0 )
148 [self destroyFramebuffer];
149 [self createFramebuffer];
152 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
155 - (void) swapBuffers {
156 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
157 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
160 - (void)layoutSubviews {
161 [EAGLContext setCurrentContext:context];
162 [self destroyFramebuffer];
163 [self createFramebuffer];
169 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
171 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
173 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
175 wxFAIL_MSG("NSOpenGLContext creation failed");
179 void WXGLDestroyContext( WXGLContext context )
187 WXGLContext WXGLGetCurrentContext()
189 return [EAGLContext currentContext];
192 bool WXGLSetCurrentContext(WXGLContext context)
194 [EAGLContext setCurrentContext:context];
198 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
203 [pixelFormat release];
209 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
212 NSOpenGLPixelFormatAttribute data[512];
213 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
215 NSOpenGLPFADoubleBuffer,
216 NSOpenGLPFAMinimumPolicy,
217 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
218 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
219 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
220 (NSOpenGLPixelFormatAttribute)nil
223 const NSOpenGLPixelFormatAttribute *attribs;
226 attribs = defaultAttribs;
231 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
233 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
235 switch ( attribList[arg++] )
238 //data[p++] = AGL_RGBA;
241 case WX_GL_BUFFER_SIZE:
242 //data[p++] = AGL_BUFFER_SIZE;
243 //data[p++] = attribList[arg++];
247 //data[p++]=AGL_LEVEL;
248 //data[p++]=attribList[arg++];
251 case WX_GL_DOUBLEBUFFER:
252 data[p++] = NSOpenGLPFADoubleBuffer;
256 data[p++] = NSOpenGLPFAStereo;
259 case WX_GL_AUX_BUFFERS:
260 data[p++] = NSOpenGLPFAAuxBuffers;
261 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
265 data[p++] = NSOpenGLPFAColorSize;
266 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
269 case WX_GL_MIN_GREEN:
270 //data[p++] = AGL_GREEN_SIZE;
271 //data[p++] = attribList[arg++];
275 //data[p++] = AGL_BLUE_SIZE;
276 //data[p++] = attribList[arg++];
279 case WX_GL_MIN_ALPHA:
280 data[p++] = NSOpenGLPFAAlphaSize;
281 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
284 case WX_GL_DEPTH_SIZE:
285 data[p++] = NSOpenGLPFADepthSize;
286 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
289 case WX_GL_STENCIL_SIZE:
290 data[p++] = NSOpenGLPFAStencilSize;
291 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
294 case WX_GL_MIN_ACCUM_RED:
295 data[p++] = NSOpenGLPFAAccumSize;
296 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
299 case WX_GL_MIN_ACCUM_GREEN:
300 //data[p++] = AGL_ACCUM_GREEN_SIZE;
301 //data[p++] = attribList[arg++];
304 case WX_GL_MIN_ACCUM_BLUE:
305 //data[p++] = AGL_ACCUM_BLUE_SIZE;
306 //data[p++] = attribList[arg++];
309 case WX_GL_MIN_ACCUM_ALPHA:
310 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
311 //data[p++] = attribList[arg++];
314 case WX_GL_SAMPLE_BUFFERS:
315 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
317 if ( !attribList[arg++] )
323 data[p++] = NSOpenGLPFASampleBuffers;
324 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
326 // don't use software fallback
327 data[p++] = NSOpenGLPFANoRecovery;
332 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
334 if ( !attribList[arg++] )
340 data[p++] = NSOpenGLPFASamples;
341 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
346 data[p] = (NSOpenGLPixelFormatAttribute)nil;
351 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
356 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
361 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
362 [v setContext:m_glContext];
366 #define USE_SEPARATE_VIEW 1
368 bool wxGLCanvas::Create(wxWindow *parent,
373 const wxString& name,
374 const int *attribList,
375 const wxPalette& WXUNUSED(palette))
378 m_glFormat = WXGLChoosePixelFormat(attribList);
382 #if USE_SEPARATE_VIEW
386 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
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];
398 SetPeer(new wxWidgetIPhoneImpl( this, v ));
400 MacPostControlCreate(pos, size) ;
405 wxGLCanvas::~wxGLCanvas()
408 WXGLDestroyPixelFormat(m_glFormat);
411 bool wxGLCanvas::SwapBuffers()
413 WXGLContext context = WXGLGetCurrentContext();
414 wxCHECK_MSG(context, false, wxT("should have current context"));
416 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) GetPeer()->GetWXWidget();
422 #endif // wxUSE_GLCANVAS