]> git.saurik.com Git - wxWidgets.git/blob - src/osx/iphone/glcanvas.mm
No real changes, just make wxWindow::CanScroll() virtual.
[wxWidgets.git] / src / osx / iphone / glcanvas.mm
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 // Copyright: (c) Stefan Csomor
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #if defined(__BORLANDC__)
22 #pragma hdrstop
23 #endif
24
25 #if wxUSE_GLCANVAS
26
27 #include "wx/glcanvas.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/frame.h"
31 #include "wx/log.h"
32 #include "wx/settings.h"
33 #endif
34
35 #include "wx/osx/private.h"
36
37 #import <OpenGLES/EAGL.h>
38 #import <OpenGLES/EAGLDrawable.h>
39 #import <QuartzCore/QuartzCore.h>
40
41 // a lot of the code is from the OpenGL ES Template
42
43 // can be turned on for ES 2.0 only
44 #define USE_DEPTH_BUFFER 0
45
46 @interface wxUICustomOpenGLView : UIView
47 {
48 CGRect oldRect;
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 - (id) initWithFrame:(CGRect) rect;
65
66 @end
67
68 @implementation wxUICustomOpenGLView
69
70 + (Class)layerClass {
71 return [CAEAGLLayer class];
72 }
73
74 + (void)initialize
75 {
76 static BOOL initialized = NO;
77 if (!initialized)
78 {
79 initialized = YES;
80 wxOSXIPhoneClassAddWXMethods( self );
81 }
82 }
83
84 - (id) initWithFrame:(CGRect)rect
85 {
86 if ( !(self=[super initWithFrame:rect]) )
87 return nil;
88
89 oldRect = rect;
90 return self;
91 }
92
93 - (BOOL)isOpaque
94 {
95 return YES;
96 }
97
98 - (BOOL)createFramebuffer {
99
100 glGenFramebuffersOES(1, &viewFramebuffer);
101 glGenRenderbuffersOES(1, &viewRenderbuffer);
102 glEnable(GL_CULL_FACE);
103
104 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
105 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
106 [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
107 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
108
109 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
110 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
111
112 if (USE_DEPTH_BUFFER) {
113 glGenRenderbuffersOES(1, &depthRenderbuffer);
114 glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
115 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
116 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
117 }
118
119 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
120 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
121 return NO;
122 }
123
124 return YES;
125 }
126
127
128 - (void)destroyFramebuffer {
129
130 glDeleteFramebuffersOES(1, &viewFramebuffer);
131 viewFramebuffer = 0;
132 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
133 viewRenderbuffer = 0;
134
135 if(depthRenderbuffer) {
136 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
137 depthRenderbuffer = 0;
138 }
139 }
140
141 - (void) setContext:(EAGLContext*) ctx {
142 context = ctx;
143 [EAGLContext setCurrentContext:ctx];
144
145 if ( viewFramebuffer == 0 )
146 {
147 [self destroyFramebuffer];
148 [self createFramebuffer];
149 }
150
151 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
152 }
153
154 - (void) swapBuffers {
155 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
156 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
157 }
158
159 - (void)layoutSubviews {
160 [EAGLContext setCurrentContext:context];
161 [self destroyFramebuffer];
162 [self createFramebuffer];
163 }
164
165 @end
166
167
168 WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
169 {
170 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
171
172 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
173 if ( !context )
174 wxFAIL_MSG("NSOpenGLContext creation failed");
175 return context ;
176 }
177
178 void WXGLDestroyContext( WXGLContext context )
179 {
180 if ( context )
181 {
182 [context release];
183 }
184 }
185
186 WXGLContext WXGLGetCurrentContext()
187 {
188 return [EAGLContext currentContext];
189 }
190
191 bool WXGLSetCurrentContext(WXGLContext context)
192 {
193 [EAGLContext setCurrentContext:context];
194 return true;
195 }
196
197 void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
198 {
199 /*
200 if ( pixelFormat )
201 {
202 [pixelFormat release];
203 }
204 */
205 }
206
207
208 WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
209 {
210 #if 0
211 NSOpenGLPixelFormatAttribute data[512];
212 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
213 {
214 NSOpenGLPFADoubleBuffer,
215 NSOpenGLPFAMinimumPolicy,
216 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
217 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
218 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
219 (NSOpenGLPixelFormatAttribute)nil
220 };
221
222 const NSOpenGLPixelFormatAttribute *attribs;
223 if ( !attribList )
224 {
225 attribs = defaultAttribs;
226 }
227 else
228 {
229 unsigned p = 0;
230 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
231
232 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
233 {
234 switch ( attribList[arg++] )
235 {
236 case WX_GL_RGBA:
237 //data[p++] = AGL_RGBA;
238 break;
239
240 case WX_GL_BUFFER_SIZE:
241 //data[p++] = AGL_BUFFER_SIZE;
242 //data[p++] = attribList[arg++];
243 break;
244
245 case WX_GL_LEVEL:
246 //data[p++]=AGL_LEVEL;
247 //data[p++]=attribList[arg++];
248 break;
249
250 case WX_GL_DOUBLEBUFFER:
251 data[p++] = NSOpenGLPFADoubleBuffer;
252 break;
253
254 case WX_GL_STEREO:
255 data[p++] = NSOpenGLPFAStereo;
256 break;
257
258 case WX_GL_AUX_BUFFERS:
259 data[p++] = NSOpenGLPFAAuxBuffers;
260 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
261 break;
262
263 case WX_GL_MIN_RED:
264 data[p++] = NSOpenGLPFAColorSize;
265 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
266 break;
267
268 case WX_GL_MIN_GREEN:
269 //data[p++] = AGL_GREEN_SIZE;
270 //data[p++] = attribList[arg++];
271 break;
272
273 case WX_GL_MIN_BLUE:
274 //data[p++] = AGL_BLUE_SIZE;
275 //data[p++] = attribList[arg++];
276 break;
277
278 case WX_GL_MIN_ALPHA:
279 data[p++] = NSOpenGLPFAAlphaSize;
280 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
281 break;
282
283 case WX_GL_DEPTH_SIZE:
284 data[p++] = NSOpenGLPFADepthSize;
285 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
286 break;
287
288 case WX_GL_STENCIL_SIZE:
289 data[p++] = NSOpenGLPFAStencilSize;
290 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
291 break;
292
293 case WX_GL_MIN_ACCUM_RED:
294 data[p++] = NSOpenGLPFAAccumSize;
295 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
296 break;
297
298 case WX_GL_MIN_ACCUM_GREEN:
299 //data[p++] = AGL_ACCUM_GREEN_SIZE;
300 //data[p++] = attribList[arg++];
301 break;
302
303 case WX_GL_MIN_ACCUM_BLUE:
304 //data[p++] = AGL_ACCUM_BLUE_SIZE;
305 //data[p++] = attribList[arg++];
306 break;
307
308 case WX_GL_MIN_ACCUM_ALPHA:
309 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
310 //data[p++] = attribList[arg++];
311 break;
312
313 case WX_GL_SAMPLE_BUFFERS:
314 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
315 {
316 if ( !attribList[arg++] )
317 break;
318
319 return false;
320 }
321
322 data[p++] = NSOpenGLPFASampleBuffers;
323 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
324 {
325 // don't use software fallback
326 data[p++] = NSOpenGLPFANoRecovery;
327 }
328 break;
329
330 case WX_GL_SAMPLES:
331 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
332 {
333 if ( !attribList[arg++] )
334 break;
335
336 return false;
337 }
338
339 data[p++] = NSOpenGLPFASamples;
340 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
341 break;
342 }
343 }
344
345 data[p] = (NSOpenGLPixelFormatAttribute)nil;
346
347 attribs = data;
348 }
349
350 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
351 #endif
352 return NULL;
353 }
354
355 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
356 {
357 if ( !m_glContext )
358 return false;
359
360 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
361 [v setContext:m_glContext];
362 return true;
363 }
364
365 #define USE_SEPARATE_VIEW 1
366
367 bool wxGLCanvas::Create(wxWindow *parent,
368 wxWindowID id,
369 const wxPoint& pos,
370 const wxSize& size,
371 long style,
372 const wxString& name,
373 const int *attribList,
374 const wxPalette& WXUNUSED(palette))
375 {
376 /*
377 m_glFormat = WXGLChoosePixelFormat(attribList);
378 if ( !m_glFormat )
379 return false;
380 */
381 #if USE_SEPARATE_VIEW
382 DontCreatePeer();
383 #endif
384
385 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
386 return false;
387
388 #if USE_SEPARATE_VIEW
389 CGRect r = wxOSXGetFrameForControl( this, pos , size ) ;
390 wxUICustomOpenGLView* v = [[wxUICustomOpenGLView alloc] initWithFrame:r];
391 CAEAGLLayer* eaglLayer = (CAEAGLLayer*) v.layer;
392 eaglLayer.opaque = YES;
393 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
394 [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
395 kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
396
397 SetPeer(new wxWidgetIPhoneImpl( this, v ));
398
399 MacPostControlCreate(pos, size) ;
400 #endif
401 return true;
402 }
403
404 wxGLCanvas::~wxGLCanvas()
405 {
406 if ( m_glFormat )
407 WXGLDestroyPixelFormat(m_glFormat);
408 }
409
410 bool wxGLCanvas::SwapBuffers()
411 {
412 WXGLContext context = WXGLGetCurrentContext();
413 wxCHECK_MSG(context, false, wxT("should have current context"));
414
415 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) GetPeer()->GetWXWidget();
416 [v swapBuffers];
417 return true;
418 }
419
420
421 #endif // wxUSE_GLCANVAS