zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_cocoaopengl.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 /* NSOpenGL implementation of SDL OpenGL support */
24 
25 #if SDL_VIDEO_OPENGL_CGL
26 #include "SDL_cocoavideo.h"
27 #include "SDL_cocoaopengl.h"
28 
29 #include <OpenGL/CGLTypes.h>
30 #include <OpenGL/OpenGL.h>
31 #include <OpenGL/CGLRenderers.h>
32 
33 #include "SDL_loadso.h"
34 #include "SDL_opengl.h"
35 
36 #define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
37 
38 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
39 /* New methods for converting to and from backing store pixels, taken from
40  * AppKite/NSView.h in 10.8 SDK. */
41 @interface NSView (Backing)
42 - (NSPoint)convertPointToBacking:(NSPoint)aPoint;
43 - (NSPoint)convertPointFromBacking:(NSPoint)aPoint;
44 - (NSSize)convertSizeToBacking:(NSSize)aSize;
45 - (NSSize)convertSizeFromBacking:(NSSize)aSize;
46 - (NSRect)convertRectToBacking:(NSRect)aRect;
47 - (NSRect)convertRectFromBacking:(NSRect)aRect;
48 @end
49 #endif
50 
51 #ifndef kCGLPFAOpenGLProfile
52 #define kCGLPFAOpenGLProfile 99
53 #endif
54 #ifndef kCGLOGLPVersion_Legacy
55 #define kCGLOGLPVersion_Legacy 0x1000
56 #endif
57 #ifndef kCGLOGLPVersion_3_2_Core
58 #define kCGLOGLPVersion_3_2_Core 0x3200
59 #endif
60 
61 @implementation SDLOpenGLContext : NSOpenGLContext
62 
63 - (id)initWithFormat:(NSOpenGLPixelFormat *)format
64  shareContext:(NSOpenGLContext *)share
65 {
66  self = [super initWithFormat:format shareContext:share];
67  if (self) {
68  SDL_AtomicSet(&self->dirty, 0);
69  self->window = NULL;
70  }
71  return self;
72 }
73 
74 - (void)scheduleUpdate
75 {
76  SDL_AtomicAdd(&self->dirty, 1);
77 }
78 
79 /* This should only be called on the thread on which a user is using the context. */
80 - (void)updateIfNeeded
81 {
82  int value = SDL_AtomicSet(&self->dirty, 0);
83  if (value > 0) {
84  /* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */
85  [super update];
86  }
87 }
88 
89 /* This should only be called on the thread on which a user is using the context. */
90 - (void)update
91 {
92  /* This ensures that regular 'update' calls clear the atomic dirty flag. */
93  [self scheduleUpdate];
94  [self updateIfNeeded];
95 }
96 
97 /* Updates the drawable for the contexts and manages related state. */
98 - (void)setWindow:(SDL_Window *)newWindow
99 {
100  if (self->window) {
101  SDL_WindowData *oldwindowdata = (SDL_WindowData *)self->window->driverdata;
102 
103  /* Make sure to remove us from the old window's context list, or we'll get scheduled updates from it too. */
104  NSMutableArray *contexts = oldwindowdata->nscontexts;
105  @synchronized (contexts) {
106  [contexts removeObject:self];
107  }
108  }
109 
110  self->window = newWindow;
111 
112  if (newWindow) {
113  SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata;
114 
115  /* Now sign up for scheduled updates for the new window. */
116  NSMutableArray *contexts = windowdata->nscontexts;
117  @synchronized (contexts) {
118  [contexts addObject:self];
119  }
120 
121  if ([self view] != [windowdata->nswindow contentView]) {
122  [self setView:[windowdata->nswindow contentView]];
123  [self scheduleUpdate];
124  }
125  } else {
126  [self clearDrawable];
127  [self scheduleUpdate];
128  }
129 }
130 
131 @end
132 
133 
134 int
135 Cocoa_GL_LoadLibrary(_THIS, const char *path)
136 {
137  /* Load the OpenGL library */
138  if (path == NULL) {
139  path = SDL_getenv("SDL_OPENGL_LIBRARY");
140  }
141  if (path == NULL) {
142  path = DEFAULT_OPENGL;
143  }
145  if (!_this->gl_config.dll_handle) {
146  return -1;
147  }
150  return 0;
151 }
152 
153 void *
154 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
155 {
157 }
158 
159 void
160 Cocoa_GL_UnloadLibrary(_THIS)
161 {
164 }
165 
167 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
168 {
169  const int wantver = (_this->gl_config.major_version << 8) |
172  NSAutoreleasePool *pool;
174  SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
175  NSOpenGLPixelFormatAttribute attr[32];
176  NSOpenGLPixelFormat *fmt;
177  SDLOpenGLContext *context;
178  NSOpenGLContext *share_context = nil;
179  int i = 0;
180 
182  SDL_SetError ("OpenGL ES not supported on this platform");
183  return NULL;
184  }
185 
186  /* Sadly, we'll have to update this as life progresses, since we need to
187  set an enum for context profiles, not a context version number */
188  if (wantver > 0x0302) {
189  SDL_SetError ("OpenGL > 3.2 is not supported on this platform");
190  return NULL;
191  }
192 
193  pool = [[NSAutoreleasePool alloc] init];
194 
195  /* specify a profile if we're on Lion (10.7) or later. */
196  if (data->osversion >= 0x1070) {
197  NSOpenGLPixelFormatAttribute profile = kCGLOGLPVersion_Legacy;
199  if (wantver == 0x0302) {
200  profile = kCGLOGLPVersion_3_2_Core;
201  }
202  }
203  attr[i++] = kCGLPFAOpenGLProfile;
204  attr[i++] = profile;
205  }
206 
207  attr[i++] = NSOpenGLPFAColorSize;
208  attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
209 
210  attr[i++] = NSOpenGLPFADepthSize;
211  attr[i++] = _this->gl_config.depth_size;
212 
214  attr[i++] = NSOpenGLPFADoubleBuffer;
215  }
216 
217  if (_this->gl_config.stereo) {
218  attr[i++] = NSOpenGLPFAStereo;
219  }
220 
222  attr[i++] = NSOpenGLPFAStencilSize;
223  attr[i++] = _this->gl_config.stencil_size;
224  }
225 
230  attr[i++] = NSOpenGLPFAAccumSize;
231  attr[i++] = _this->gl_config.accum_red_size + _this->gl_config.accum_green_size + _this->gl_config.accum_blue_size + _this->gl_config.accum_alpha_size;
232  }
233 
235  attr[i++] = NSOpenGLPFASampleBuffers;
236  attr[i++] = _this->gl_config.multisamplebuffers;
237  }
238 
240  attr[i++] = NSOpenGLPFASamples;
241  attr[i++] = _this->gl_config.multisamplesamples;
242  attr[i++] = NSOpenGLPFANoRecovery;
243  }
244 
245  if (_this->gl_config.accelerated >= 0) {
246  if (_this->gl_config.accelerated) {
247  attr[i++] = NSOpenGLPFAAccelerated;
248  } else {
249  attr[i++] = NSOpenGLPFARendererID;
250  attr[i++] = kCGLRendererGenericFloatID;
251  }
252  }
253 
254  attr[i++] = NSOpenGLPFAScreenMask;
255  attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
256  attr[i] = 0;
257 
258  fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
259  if (fmt == nil) {
260  SDL_SetError ("Failed creating OpenGL pixel format");
261  [pool release];
262  return NULL;
263  }
264 
266  share_context = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
267  }
268 
269  context = [[SDLOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
270 
271  [fmt release];
272 
273  if (context == nil) {
274  SDL_SetError ("Failed creating OpenGL context");
275  [pool release];
276  return NULL;
277  }
278 
279  [pool release];
280 
281  if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
282  Cocoa_GL_DeleteContext(_this, context);
283  return NULL;
284  }
285 
286  return context;
287 }
288 
289 int
290 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
291 {
292  NSAutoreleasePool *pool;
293 
294  pool = [[NSAutoreleasePool alloc] init];
295 
296  if (context) {
297  SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
298  [nscontext setWindow:window];
299  [nscontext updateIfNeeded];
300  [nscontext makeCurrentContext];
301  } else {
302  [NSOpenGLContext clearCurrentContext];
303  }
304 
305  [pool release];
306  return 0;
307 }
308 
309 void
310 Cocoa_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
311 {
312  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
313  NSView *contentView = [windata->nswindow contentView];
314  NSRect viewport = [contentView bounds];
315 
316  /* This gives us the correct viewport for a Retina-enabled view, only
317  * supported on 10.7+. */
318  if ([contentView respondsToSelector:@selector(convertRectToBacking:)]) {
319  viewport = [contentView convertRectToBacking:viewport];
320  }
321 
322  if (w) {
323  *w = viewport.size.width;
324  }
325 
326  if (h) {
327  *h = viewport.size.height;
328  }
329 }
330 
331 int
332 Cocoa_GL_SetSwapInterval(_THIS, int interval)
333 {
334  NSAutoreleasePool *pool;
335  NSOpenGLContext *nscontext;
336  GLint value;
337  int status;
338 
339  if (interval < 0) { /* no extension for this on Mac OS X at the moment. */
340  return SDL_SetError("Late swap tearing currently unsupported");
341  }
342 
343  pool = [[NSAutoreleasePool alloc] init];
344 
345  nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
346  if (nscontext != nil) {
347  value = interval;
348  [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
349  status = 0;
350  } else {
351  status = SDL_SetError("No current OpenGL context");
352  }
353 
354  [pool release];
355  return status;
356 }
357 
358 int
359 Cocoa_GL_GetSwapInterval(_THIS)
360 {
361  NSAutoreleasePool *pool;
362  NSOpenGLContext *nscontext;
363  GLint value;
364  int status = 0;
365 
366  pool = [[NSAutoreleasePool alloc] init];
367 
368  nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
369  if (nscontext != nil) {
370  [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
371  status = (int)value;
372  }
373 
374  [pool release];
375  return status;
376 }
377 
378 void
379 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
380 {
381  NSAutoreleasePool *pool;
382 
383  pool = [[NSAutoreleasePool alloc] init];
384 
385  SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
386  [nscontext flushBuffer];
387  [nscontext updateIfNeeded];
388 
389  [pool release];
390 }
391 
392 void
393 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
394 {
395  NSAutoreleasePool *pool;
396  SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
397 
398  pool = [[NSAutoreleasePool alloc] init];
399 
400  [nscontext setWindow:NULL];
401  [nscontext release];
402 
403  [pool release];
404 }
405 
406 #endif /* SDL_VIDEO_OPENGL_CGL */
407 
408 /* vi: set ts=4 sw=4 expandtab: */
png_charp profile
Definition: pngrutil.c:1240
NSMutableArray * nscontexts
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
#define NULL
Definition: ftobjs.h:61
SDL_FORCE_INLINE int SDL_AtomicAdd(SDL_atomic_t *a, int v)
Add to an atomic variable.
Definition: SDL_atomic.h:283
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:161
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:123
SDL_Window * window
char * display
Definition: visualinfo.c:85
CGDirectDisplayID display
if(!yyg->yy_init)
GLuint id
Definition: gl2ext.h:1142
GLsizei const GLchar *const * path
Definition: glew.h:5828
static SDL_VideoDevice * _this
Definition: SDL_video.c:92
int
Definition: SDL_systhread.c:37
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define _THIS
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen)
Definition: SDL_string.c:448
char driver_path[256]
Definition: SDL_sysvideo.h:298
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
NSWindow * nswindow
int share_with_current_context
Definition: SDL_sysvideo.h:295
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
int GLint
Definition: gl2.h:28
EGLSurface EGLint void ** value
Definition: eglext.h:301
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:996
SDL_FORCE_INLINE int SDL_AtomicSet(SDL_atomic_t *a, int v)
Set an atomic variable to a value.
Definition: SDL_atomic.h:253
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
DECLSPEC char *SDLCALL SDL_getenv(const char *name)
Definition: SDL_getenv.c:179
void * driverdata
Definition: SDL_sysvideo.h:99
TParseContext * context
int i
Definition: pngrutil.c:1377
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)
struct SDL_VideoDevice::@87 gl_config
DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void)
Get the currently active OpenGL context.
Definition: SDL_video.c:2822