]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/iphone/glcanvas.mm
No real changes, just make wxWindow::CanScroll() virtual.
[wxWidgets.git] / src / osx / iphone / glcanvas.mm
... / ...
CommitLineData
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
168WXGLContext 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
178void WXGLDestroyContext( WXGLContext context )
179{
180 if ( context )
181 {
182 [context release];
183 }
184}
185
186WXGLContext WXGLGetCurrentContext()
187{
188 return [EAGLContext currentContext];
189}
190
191bool WXGLSetCurrentContext(WXGLContext context)
192{
193 [EAGLContext setCurrentContext:context];
194 return true;
195}
196
197void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
198{
199/*
200 if ( pixelFormat )
201 {
202 [pixelFormat release];
203 }
204*/
205}
206
207
208WXGLPixelFormat 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
355bool 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
367bool 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
404wxGLCanvas::~wxGLCanvas()
405{
406 if ( m_glFormat )
407 WXGLDestroyPixelFormat(m_glFormat);
408}
409
410bool 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