]> git.saurik.com Git - wxWidgets.git/blame - src/osx/iphone/glcanvas.mm
OpenGL for iPhone
[wxWidgets.git] / src / osx / iphone / glcanvas.mm
CommitLineData
e5684ea0
SC
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
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);
97
98 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
99 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
100
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);
106 }
107
108 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
109 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
110 return NO;
111 }
112
113 return YES;
114}
115
116
117- (void)destroyFramebuffer {
118
119 glDeleteFramebuffersOES(1, &viewFramebuffer);
120 viewFramebuffer = 0;
121 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
122 viewRenderbuffer = 0;
123
124 if(depthRenderbuffer) {
125 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
126 depthRenderbuffer = 0;
127 }
128}
129
130- (void) setContext:(EAGLContext*) ctx {
131 context = ctx;
132 [EAGLContext setCurrentContext:ctx];
133 [self destroyFramebuffer];
134 [self createFramebuffer];
135 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
136}
137
138- (void) swapBuffers {
139 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
140 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
141}
142
143@end
144
145
146WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
147{
148 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
149
150 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
151 if ( !context )
152 wxFAIL_MSG("NSOpenGLContext creation failed");
153 return context ;
154}
155
156void WXGLDestroyContext( WXGLContext context )
157{
158 if ( context )
159 {
160 [context release];
161 }
162}
163
164WXGLContext WXGLGetCurrentContext()
165{
166 return [EAGLContext currentContext];
167}
168
169bool WXGLSetCurrentContext(WXGLContext context)
170{
171 [EAGLContext setCurrentContext:context];
172 return true;
173}
174
175void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
176{
177/*
178 if ( pixelFormat )
179 {
180 [pixelFormat release];
181 }
182*/
183}
184
185
186WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
187{
188#if 0
189 NSOpenGLPixelFormatAttribute data[512];
190 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
191 {
192 NSOpenGLPFADoubleBuffer,
193 NSOpenGLPFAMinimumPolicy,
194 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
195 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
196 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
197 (NSOpenGLPixelFormatAttribute)nil
198 };
199
200 const NSOpenGLPixelFormatAttribute *attribs;
201 if ( !attribList )
202 {
203 attribs = defaultAttribs;
204 }
205 else
206 {
207 unsigned p = 0;
208 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
209
210 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
211 {
212 switch ( attribList[arg++] )
213 {
214 case WX_GL_RGBA:
215 //data[p++] = AGL_RGBA;
216 break;
217
218 case WX_GL_BUFFER_SIZE:
219 //data[p++] = AGL_BUFFER_SIZE;
220 //data[p++] = attribList[arg++];
221 break;
222
223 case WX_GL_LEVEL:
224 //data[p++]=AGL_LEVEL;
225 //data[p++]=attribList[arg++];
226 break;
227
228 case WX_GL_DOUBLEBUFFER:
229 data[p++] = NSOpenGLPFADoubleBuffer;
230 break;
231
232 case WX_GL_STEREO:
233 data[p++] = NSOpenGLPFAStereo;
234 break;
235
236 case WX_GL_AUX_BUFFERS:
237 data[p++] = NSOpenGLPFAAuxBuffers;
238 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
239 break;
240
241 case WX_GL_MIN_RED:
242 data[p++] = NSOpenGLPFAColorSize;
243 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
244 break;
245
246 case WX_GL_MIN_GREEN:
247 //data[p++] = AGL_GREEN_SIZE;
248 //data[p++] = attribList[arg++];
249 break;
250
251 case WX_GL_MIN_BLUE:
252 //data[p++] = AGL_BLUE_SIZE;
253 //data[p++] = attribList[arg++];
254 break;
255
256 case WX_GL_MIN_ALPHA:
257 data[p++] = NSOpenGLPFAAlphaSize;
258 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
259 break;
260
261 case WX_GL_DEPTH_SIZE:
262 data[p++] = NSOpenGLPFADepthSize;
263 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
264 break;
265
266 case WX_GL_STENCIL_SIZE:
267 data[p++] = NSOpenGLPFAStencilSize;
268 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
269 break;
270
271 case WX_GL_MIN_ACCUM_RED:
272 data[p++] = NSOpenGLPFAAccumSize;
273 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
274 break;
275
276 case WX_GL_MIN_ACCUM_GREEN:
277 //data[p++] = AGL_ACCUM_GREEN_SIZE;
278 //data[p++] = attribList[arg++];
279 break;
280
281 case WX_GL_MIN_ACCUM_BLUE:
282 //data[p++] = AGL_ACCUM_BLUE_SIZE;
283 //data[p++] = attribList[arg++];
284 break;
285
286 case WX_GL_MIN_ACCUM_ALPHA:
287 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
288 //data[p++] = attribList[arg++];
289 break;
290
291 case WX_GL_SAMPLE_BUFFERS:
292 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
293 {
294 if ( !attribList[arg++] )
295 break;
296
297 return false;
298 }
299
300 data[p++] = NSOpenGLPFASampleBuffers;
301 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
302 {
303 // don't use software fallback
304 data[p++] = NSOpenGLPFANoRecovery;
305 }
306 break;
307
308 case WX_GL_SAMPLES:
309 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
310 {
311 if ( !attribList[arg++] )
312 break;
313
314 return false;
315 }
316
317 data[p++] = NSOpenGLPFASamples;
318 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
319 break;
320 }
321 }
322
323 data[p] = (NSOpenGLPixelFormatAttribute)nil;
324
325 attribs = data;
326 }
327
328 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
329#endif
330 return NULL;
331}
332
333bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
334{
335 if ( !m_glContext )
336 return false;
337
338 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
339 [v setContext:m_glContext];
340 return true;
341}
342
343#define USE_SEPARATE_VIEW 1
344
345bool wxGLCanvas::Create(wxWindow *parent,
346 wxWindowID id,
347 const wxPoint& pos,
348 const wxSize& size,
349 long style,
350 const wxString& name,
351 const int *attribList,
352 const wxPalette& WXUNUSED(palette))
353{
354/*
355 m_glFormat = WXGLChoosePixelFormat(attribList);
356 if ( !m_glFormat )
357 return false;
358*/
359#if USE_SEPARATE_VIEW
360 m_macIsUserPane = false ;
361#endif
362
363 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
364 return false;
365
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];
374
375 m_peer = new wxWidgetIPhoneImpl( this, v );
376
377 MacPostControlCreate(pos, size) ;
378#endif
379 return true;
380}
381
382wxGLCanvas::~wxGLCanvas()
383{
384 if ( m_glFormat )
385 WXGLDestroyPixelFormat(m_glFormat);
386}
387
388bool wxGLCanvas::SwapBuffers()
389{
390 WXGLContext context = WXGLGetCurrentContext();
391 wxCHECK_MSG(context, false, wxT("should have current context"));
392
393 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) m_peer->GetWXWidget();
394 [v swapBuffers];
395 return true;
396}
397
398
399#endif // wxUSE_GLCANVAS