1
///////////////////////////////////////////////////////////////////////////////
2
// Name: src/osx/iphone/glcanvas.mm
3
// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under iPhone
4
// Author: Stefan Csomor
7
// Copyright: (c) Stefan Csomor
8
// Licence: wxWindows licence
9
///////////////////////////////////////////////////////////////////////////////
11
// ============================================================================
13
// ============================================================================
15
// ----------------------------------------------------------------------------
17
// ----------------------------------------------------------------------------
19
#include "wx/wxprec.h"
21
#if defined(__BORLANDC__)
27
#include "wx/glcanvas.h"
32
#include "wx/settings.h"
35
#include "wx/osx/private.h"
37
#import <OpenGLES/EAGL.h>
38
#import <OpenGLES/EAGLDrawable.h>
39
#import <QuartzCore/QuartzCore.h>
41
// a lot of the code is from the OpenGL ES Template
43
// can be turned on for ES 2.0 only
44
#define USE_DEPTH_BUFFER 0
46
@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;
64
- (id) initWithFrame:(CGRect) rect;
68
@implementation wxUICustomOpenGLView
71
return [CAEAGLLayer class];
76
static BOOL initialized = NO;
80
wxOSXIPhoneClassAddWXMethods( self );
84
- (id) initWithFrame:(CGRect)rect
86
if ( !(self=[super initWithFrame:rect]) )
98
- (BOOL)createFramebuffer {
100
glGenFramebuffersOES(1, &viewFramebuffer);
101
glGenRenderbuffersOES(1, &viewRenderbuffer);
102
glEnable(GL_CULL_FACE);
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);
109
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
110
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
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);
119
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
120
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
128
- (void)destroyFramebuffer {
130
glDeleteFramebuffersOES(1, &viewFramebuffer);
132
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
133
viewRenderbuffer = 0;
135
if(depthRenderbuffer) {
136
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
137
depthRenderbuffer = 0;
141
- (void) setContext:(EAGLContext*) ctx {
143
[EAGLContext setCurrentContext:ctx];
145
if ( viewFramebuffer == 0 )
147
[self destroyFramebuffer];
148
[self createFramebuffer];
151
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
154
- (void) swapBuffers {
155
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
156
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
159
- (void)layoutSubviews {
160
[EAGLContext setCurrentContext:context];
161
[self destroyFramebuffer];
162
[self createFramebuffer];
168
WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
170
WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
172
// [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
174
wxFAIL_MSG("NSOpenGLContext creation failed");
178
void WXGLDestroyContext( WXGLContext context )
186
WXGLContext WXGLGetCurrentContext()
188
return [EAGLContext currentContext];
191
bool WXGLSetCurrentContext(WXGLContext context)
193
[EAGLContext setCurrentContext:context];
197
void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
202
[pixelFormat release];
208
WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
211
NSOpenGLPixelFormatAttribute data[512];
212
const NSOpenGLPixelFormatAttribute defaultAttribs[] =
214
NSOpenGLPFADoubleBuffer,
215
NSOpenGLPFAMinimumPolicy,
216
NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
217
NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
218
NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
219
(NSOpenGLPixelFormatAttribute)nil
222
const NSOpenGLPixelFormatAttribute *attribs;
225
attribs = defaultAttribs;
230
data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
232
for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
234
switch ( attribList[arg++] )
237
//data[p++] = AGL_RGBA;
240
case WX_GL_BUFFER_SIZE:
241
//data[p++] = AGL_BUFFER_SIZE;
242
//data[p++] = attribList[arg++];
246
//data[p++]=AGL_LEVEL;
247
//data[p++]=attribList[arg++];
250
case WX_GL_DOUBLEBUFFER:
251
data[p++] = NSOpenGLPFADoubleBuffer;
255
data[p++] = NSOpenGLPFAStereo;
258
case WX_GL_AUX_BUFFERS:
259
data[p++] = NSOpenGLPFAAuxBuffers;
260
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
264
data[p++] = NSOpenGLPFAColorSize;
265
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
268
case WX_GL_MIN_GREEN:
269
//data[p++] = AGL_GREEN_SIZE;
270
//data[p++] = attribList[arg++];
274
//data[p++] = AGL_BLUE_SIZE;
275
//data[p++] = attribList[arg++];
278
case WX_GL_MIN_ALPHA:
279
data[p++] = NSOpenGLPFAAlphaSize;
280
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
283
case WX_GL_DEPTH_SIZE:
284
data[p++] = NSOpenGLPFADepthSize;
285
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
288
case WX_GL_STENCIL_SIZE:
289
data[p++] = NSOpenGLPFAStencilSize;
290
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
293
case WX_GL_MIN_ACCUM_RED:
294
data[p++] = NSOpenGLPFAAccumSize;
295
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
298
case WX_GL_MIN_ACCUM_GREEN:
299
//data[p++] = AGL_ACCUM_GREEN_SIZE;
300
//data[p++] = attribList[arg++];
303
case WX_GL_MIN_ACCUM_BLUE:
304
//data[p++] = AGL_ACCUM_BLUE_SIZE;
305
//data[p++] = attribList[arg++];
308
case WX_GL_MIN_ACCUM_ALPHA:
309
//data[p++] = AGL_ACCUM_ALPHA_SIZE;
310
//data[p++] = attribList[arg++];
313
case WX_GL_SAMPLE_BUFFERS:
314
if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
316
if ( !attribList[arg++] )
322
data[p++] = NSOpenGLPFASampleBuffers;
323
if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
325
// don't use software fallback
326
data[p++] = NSOpenGLPFANoRecovery;
331
if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
333
if ( !attribList[arg++] )
339
data[p++] = NSOpenGLPFASamples;
340
data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
345
data[p] = (NSOpenGLPixelFormatAttribute)nil;
350
return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
355
bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
360
wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
361
[v setContext:m_glContext];
365
#define USE_SEPARATE_VIEW 1
367
bool wxGLCanvas::Create(wxWindow *parent,
372
const wxString& name,
373
const int *attribList,
374
const wxPalette& WXUNUSED(palette))
377
m_glFormat = WXGLChoosePixelFormat(attribList);
381
#if USE_SEPARATE_VIEW
385
if ( !wxWindow::Create(parent, id, pos, size, style, name) )
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];
397
SetPeer(new wxWidgetIPhoneImpl( this, v ));
399
MacPostControlCreate(pos, size) ;
404
wxGLCanvas::~wxGLCanvas()
407
WXGLDestroyPixelFormat(m_glFormat);
410
bool wxGLCanvas::SwapBuffers()
412
WXGLContext context = WXGLGetCurrentContext();
413
wxCHECK_MSG(context, false, wxT("should have current context"));
415
wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) GetPeer()->GetWXWidget();
421
#endif // wxUSE_GLCANVAS