]> git.saurik.com Git - wxWidgets.git/blame - src/osx/iphone/glcanvas.mm
Applied Blit system options optimization to StretchBlit
[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
a9a4f229 7// RCS-ID: $Id$
e5684ea0
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{
d5f46cdd 49 CGRect oldRect;
e5684ea0
SC
50 EAGLContext* context;
51
52 /* The pixel dimensions of the backbuffer */
53 GLint backingWidth;
54 GLint backingHeight;
55
56 /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
57 GLuint viewRenderbuffer, viewFramebuffer;
58
59 /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
60 GLuint depthRenderbuffer;
61}
62
63- (BOOL) createFramebuffer;
64- (void) destroyFramebuffer;
d5f46cdd 65- (id) initWithFrame:(CGRect) rect;
e5684ea0
SC
66
67@end
68
69@implementation wxUICustomOpenGLView
70
71+ (Class)layerClass {
72 return [CAEAGLLayer class];
73}
74
75+ (void)initialize
76{
77 static BOOL initialized = NO;
78 if (!initialized)
79 {
80 initialized = YES;
81 wxOSXIPhoneClassAddWXMethods( self );
82 }
83}
84
d5f46cdd
SC
85- (id) initWithFrame:(CGRect)rect
86{
87 if ( !(self=[super initWithFrame:rect]) )
88 return nil;
89
90 oldRect = rect;
91 return self;
92}
93
e5684ea0
SC
94- (BOOL)isOpaque
95{
96 return YES;
97}
98
99- (BOOL)createFramebuffer {
100
101 glGenFramebuffersOES(1, &viewFramebuffer);
102 glGenRenderbuffersOES(1, &viewRenderbuffer);
42327c33 103 glEnable(GL_CULL_FACE);
e5684ea0
SC
104
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);
109
110 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
111 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
112
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);
118 }
119
120 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
121 NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
122 return NO;
123 }
124
125 return YES;
126}
127
128
129- (void)destroyFramebuffer {
130
131 glDeleteFramebuffersOES(1, &viewFramebuffer);
132 viewFramebuffer = 0;
133 glDeleteRenderbuffersOES(1, &viewRenderbuffer);
134 viewRenderbuffer = 0;
135
136 if(depthRenderbuffer) {
137 glDeleteRenderbuffersOES(1, &depthRenderbuffer);
138 depthRenderbuffer = 0;
139 }
140}
141
142- (void) setContext:(EAGLContext*) ctx {
143 context = ctx;
144 [EAGLContext setCurrentContext:ctx];
d5f46cdd
SC
145#if 0
146 CGRect newRect = [self frame];
147 if ( /* (CGRectEqualToRect(newRect, oldRect) == NO && ![self isHidden] && newRect.size.width > 0 && newRect.size.height > 0 )
148 || */ viewFramebuffer == 0 )
149 {
150 [self destroyFramebuffer];
151 [self createFramebuffer];
152 }
153#endif
e5684ea0
SC
154 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
155}
156
157- (void) swapBuffers {
158 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
159 [context presentRenderbuffer:GL_RENDERBUFFER_OES];
160}
161
d5f46cdd
SC
162- (void)layoutSubviews {
163 [EAGLContext setCurrentContext:context];
164 [self destroyFramebuffer];
165 [self createFramebuffer];
166}
167
e5684ea0
SC
168@end
169
170
171WXGLContext WXGLCreateContext( WXGLPixelFormat pixelFormat, WXGLContext shareContext )
172{
173 WXGLContext context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
174
175 // [[EAGLContext alloc] initWithFormat:pixelFormat shareContext: shareContext];
176 if ( !context )
177 wxFAIL_MSG("NSOpenGLContext creation failed");
178 return context ;
179}
180
181void WXGLDestroyContext( WXGLContext context )
182{
183 if ( context )
184 {
185 [context release];
186 }
187}
188
189WXGLContext WXGLGetCurrentContext()
190{
191 return [EAGLContext currentContext];
192}
193
194bool WXGLSetCurrentContext(WXGLContext context)
195{
196 [EAGLContext setCurrentContext:context];
197 return true;
198}
199
200void WXGLDestroyPixelFormat( WXGLPixelFormat pixelFormat )
201{
202/*
203 if ( pixelFormat )
204 {
205 [pixelFormat release];
206 }
207*/
208}
209
210
211WXGLPixelFormat WXGLChoosePixelFormat(const int *attribList)
212{
213#if 0
214 NSOpenGLPixelFormatAttribute data[512];
215 const NSOpenGLPixelFormatAttribute defaultAttribs[] =
216 {
217 NSOpenGLPFADoubleBuffer,
218 NSOpenGLPFAMinimumPolicy,
219 NSOpenGLPFAColorSize,(NSOpenGLPixelFormatAttribute)8,
220 NSOpenGLPFAAlphaSize,(NSOpenGLPixelFormatAttribute)0,
221 NSOpenGLPFADepthSize,(NSOpenGLPixelFormatAttribute)8,
222 (NSOpenGLPixelFormatAttribute)nil
223 };
224
225 const NSOpenGLPixelFormatAttribute *attribs;
226 if ( !attribList )
227 {
228 attribs = defaultAttribs;
229 }
230 else
231 {
232 unsigned p = 0;
233 data[p++] = NSOpenGLPFAMinimumPolicy; // make _SIZE tags behave more like GLX
234
235 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
236 {
237 switch ( attribList[arg++] )
238 {
239 case WX_GL_RGBA:
240 //data[p++] = AGL_RGBA;
241 break;
242
243 case WX_GL_BUFFER_SIZE:
244 //data[p++] = AGL_BUFFER_SIZE;
245 //data[p++] = attribList[arg++];
246 break;
247
248 case WX_GL_LEVEL:
249 //data[p++]=AGL_LEVEL;
250 //data[p++]=attribList[arg++];
251 break;
252
253 case WX_GL_DOUBLEBUFFER:
254 data[p++] = NSOpenGLPFADoubleBuffer;
255 break;
256
257 case WX_GL_STEREO:
258 data[p++] = NSOpenGLPFAStereo;
259 break;
260
261 case WX_GL_AUX_BUFFERS:
262 data[p++] = NSOpenGLPFAAuxBuffers;
263 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
264 break;
265
266 case WX_GL_MIN_RED:
267 data[p++] = NSOpenGLPFAColorSize;
268 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
269 break;
270
271 case WX_GL_MIN_GREEN:
272 //data[p++] = AGL_GREEN_SIZE;
273 //data[p++] = attribList[arg++];
274 break;
275
276 case WX_GL_MIN_BLUE:
277 //data[p++] = AGL_BLUE_SIZE;
278 //data[p++] = attribList[arg++];
279 break;
280
281 case WX_GL_MIN_ALPHA:
282 data[p++] = NSOpenGLPFAAlphaSize;
283 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
284 break;
285
286 case WX_GL_DEPTH_SIZE:
287 data[p++] = NSOpenGLPFADepthSize;
288 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
289 break;
290
291 case WX_GL_STENCIL_SIZE:
292 data[p++] = NSOpenGLPFAStencilSize;
293 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
294 break;
295
296 case WX_GL_MIN_ACCUM_RED:
297 data[p++] = NSOpenGLPFAAccumSize;
298 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
299 break;
300
301 case WX_GL_MIN_ACCUM_GREEN:
302 //data[p++] = AGL_ACCUM_GREEN_SIZE;
303 //data[p++] = attribList[arg++];
304 break;
305
306 case WX_GL_MIN_ACCUM_BLUE:
307 //data[p++] = AGL_ACCUM_BLUE_SIZE;
308 //data[p++] = attribList[arg++];
309 break;
310
311 case WX_GL_MIN_ACCUM_ALPHA:
312 //data[p++] = AGL_ACCUM_ALPHA_SIZE;
313 //data[p++] = attribList[arg++];
314 break;
315
316 case WX_GL_SAMPLE_BUFFERS:
317 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
318 {
319 if ( !attribList[arg++] )
320 break;
321
322 return false;
323 }
324
325 data[p++] = NSOpenGLPFASampleBuffers;
326 if ( (data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++]) == true )
327 {
328 // don't use software fallback
329 data[p++] = NSOpenGLPFANoRecovery;
330 }
331 break;
332
333 case WX_GL_SAMPLES:
334 if ( !wxGLCanvas::IsAGLMultiSampleAvailable() )
335 {
336 if ( !attribList[arg++] )
337 break;
338
339 return false;
340 }
341
342 data[p++] = NSOpenGLPFASamples;
343 data[p++] = (NSOpenGLPixelFormatAttribute) attribList[arg++];
344 break;
345 }
346 }
347
348 data[p] = (NSOpenGLPixelFormatAttribute)nil;
349
350 attribs = data;
351 }
352
353 return [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute*) attribs];
354#endif
355 return NULL;
356}
357
358bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
359{
360 if ( !m_glContext )
361 return false;
362
363 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) win.GetPeer()->GetWXWidget();
364 [v setContext:m_glContext];
365 return true;
366}
367
368#define USE_SEPARATE_VIEW 1
369
370bool wxGLCanvas::Create(wxWindow *parent,
371 wxWindowID id,
372 const wxPoint& pos,
373 const wxSize& size,
374 long style,
375 const wxString& name,
376 const int *attribList,
377 const wxPalette& WXUNUSED(palette))
378{
379/*
380 m_glFormat = WXGLChoosePixelFormat(attribList);
381 if ( !m_glFormat )
382 return false;
383*/
384#if USE_SEPARATE_VIEW
d15694e8 385 DontCreatePeer();
e5684ea0
SC
386#endif
387
388 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
389 return false;
390
391#if USE_SEPARATE_VIEW
392 CGRect r = wxOSXGetFrameForControl( this, pos , size ) ;
393 wxUICustomOpenGLView* v = [[wxUICustomOpenGLView alloc] initWithFrame:r];
394 CAEAGLLayer* eaglLayer = (CAEAGLLayer*) v.layer;
395 eaglLayer.opaque = YES;
396 eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
397 [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
398 kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
399
8606ee50 400 SetPeer(new wxWidgetIPhoneImpl( this, v ));
e5684ea0
SC
401
402 MacPostControlCreate(pos, size) ;
403#endif
404 return true;
405}
406
407wxGLCanvas::~wxGLCanvas()
408{
409 if ( m_glFormat )
410 WXGLDestroyPixelFormat(m_glFormat);
411}
412
413bool wxGLCanvas::SwapBuffers()
414{
415 WXGLContext context = WXGLGetCurrentContext();
416 wxCHECK_MSG(context, false, wxT("should have current context"));
417
8606ee50 418 wxUICustomOpenGLView* v = (wxUICustomOpenGLView*) GetPeer()->GetWXWidget();
e5684ea0
SC
419 [v swapBuffers];
420 return true;
421}
422
423
424#endif // wxUSE_GLCANVAS