• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//========================================================================
2// GLFW 3.2 OS X - www.glfw.org
3//------------------------------------------------------------------------
4// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
5//
6// This software is provided 'as-is', without any express or implied
7// warranty. In no event will the authors be held liable for any damages
8// arising from the use of this software.
9//
10// Permission is granted to anyone to use this software for any purpose,
11// including commercial applications, and to alter it and redistribute it
12// freely, subject to the following restrictions:
13//
14// 1. The origin of this software must not be misrepresented; you must not
15//    claim that you wrote the original software. If you use this software
16//    in a product, an acknowledgment in the product documentation would
17//    be appreciated but is not required.
18//
19// 2. Altered source versions must be plainly marked as such, and must not
20//    be misrepresented as being the original software.
21//
22// 3. This notice may not be removed or altered from any source
23//    distribution.
24//
25//========================================================================
26
27#include "internal.h"
28
29
30static void makeContextCurrentNSGL(_GLFWwindow* window)
31{
32    if (window)
33        [window->context.nsgl.object makeCurrentContext];
34    else
35        [NSOpenGLContext clearCurrentContext];
36
37    _glfwPlatformSetCurrentContext(window);
38}
39
40static void swapBuffersNSGL(_GLFWwindow* window)
41{
42    // ARP appears to be unnecessary, but this is future-proof
43    [window->context.nsgl.object flushBuffer];
44}
45
46static void swapIntervalNSGL(int interval)
47{
48    _GLFWwindow* window = _glfwPlatformGetCurrentContext();
49
50    GLint sync = interval;
51    [window->context.nsgl.object setValues:&sync
52                              forParameter:NSOpenGLCPSwapInterval];
53}
54
55static int extensionSupportedNSGL(const char* extension)
56{
57    // There are no NSGL extensions
58    return GLFW_FALSE;
59}
60
61static GLFWglproc getProcAddressNSGL(const char* procname)
62{
63    CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
64                                                       procname,
65                                                       kCFStringEncodingASCII);
66
67    GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
68                                                          symbolName);
69
70    CFRelease(symbolName);
71
72    return symbol;
73}
74
75// Destroy the OpenGL context
76//
77static void destroyContextNSGL(_GLFWwindow* window)
78{
79    [window->context.nsgl.pixelFormat release];
80    window->context.nsgl.pixelFormat = nil;
81
82    [window->context.nsgl.object release];
83    window->context.nsgl.object = nil;
84}
85
86
87//////////////////////////////////////////////////////////////////////////
88//////                       GLFW internal API                      //////
89//////////////////////////////////////////////////////////////////////////
90
91// Initialize OpenGL support
92//
93GLFWbool _glfwInitNSGL(void)
94{
95    if (_glfw.nsgl.framework)
96        return GLFW_TRUE;
97
98    _glfw.nsgl.framework =
99        CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
100    if (_glfw.nsgl.framework == NULL)
101    {
102        _glfwInputError(GLFW_API_UNAVAILABLE,
103                        "NSGL: Failed to locate OpenGL framework");
104        return GLFW_FALSE;
105    }
106
107    return GLFW_TRUE;
108}
109
110// Terminate OpenGL support
111//
112void _glfwTerminateNSGL(void)
113{
114}
115
116// Create the OpenGL context
117//
118GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
119                                const _GLFWctxconfig* ctxconfig,
120                                const _GLFWfbconfig* fbconfig)
121{
122    unsigned int attributeCount = 0;
123
124    if (ctxconfig->client == GLFW_OPENGL_ES_API)
125    {
126        _glfwInputError(GLFW_API_UNAVAILABLE,
127                        "NSGL: OpenGL ES is not available on OS X");
128        return GLFW_FALSE;
129    }
130
131    if (ctxconfig->major == 3 && ctxconfig->minor < 2)
132    {
133        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
134                        "NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");
135        fprintf(stderr, "[Engine Log] NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1\n");
136        return GLFW_FALSE;
137    }
138
139    if (ctxconfig->major > 2)
140    {
141        if (!ctxconfig->forward)
142        {
143            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
144                            "NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");
145            return GLFW_FALSE;
146        }
147
148        if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
149        {
150            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
151                            "NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");
152            return GLFW_FALSE;
153        }
154    }
155
156    // Context robustness modes (GL_KHR_robustness) are not yet supported on
157    // OS X but are not a hard constraint, so ignore and continue
158
159    // Context release behaviors (GL_KHR_context_flush_control) are not yet
160    // supported on OS X but are not a hard constraint, so ignore and continue
161
162#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
163#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
164
165    // Arbitrary array size here
166    NSOpenGLPixelFormatAttribute attributes[40];
167
168    ADD_ATTR(NSOpenGLPFAAccelerated);
169    ADD_ATTR(NSOpenGLPFAClosestPolicy);
170
171#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
172    if (ctxconfig->major >= 4)
173    {
174        ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
175    }
176    else
177#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
178    if (ctxconfig->major >= 3)
179    {
180        ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
181    }
182
183    if (ctxconfig->major <= 2)
184    {
185        if (fbconfig->auxBuffers != GLFW_DONT_CARE)
186            ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
187
188        if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
189            fbconfig->accumGreenBits != GLFW_DONT_CARE &&
190            fbconfig->accumBlueBits != GLFW_DONT_CARE &&
191            fbconfig->accumAlphaBits != GLFW_DONT_CARE)
192        {
193            const int accumBits = fbconfig->accumRedBits +
194                                  fbconfig->accumGreenBits +
195                                  fbconfig->accumBlueBits +
196                                  fbconfig->accumAlphaBits;
197
198            ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
199        }
200    }
201
202    if (fbconfig->redBits != GLFW_DONT_CARE &&
203        fbconfig->greenBits != GLFW_DONT_CARE &&
204        fbconfig->blueBits != GLFW_DONT_CARE)
205    {
206        int colorBits = fbconfig->redBits +
207                        fbconfig->greenBits +
208                        fbconfig->blueBits;
209
210        // OS X needs non-zero color size, so set reasonable values
211        if (colorBits == 0)
212            colorBits = 24;
213        else if (colorBits < 15)
214            colorBits = 15;
215
216        ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
217    }
218
219    if (fbconfig->alphaBits != GLFW_DONT_CARE)
220        ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
221
222    if (fbconfig->depthBits != GLFW_DONT_CARE)
223        ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
224
225    if (fbconfig->stencilBits != GLFW_DONT_CARE)
226        ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
227
228    if (fbconfig->stereo)
229        ADD_ATTR(NSOpenGLPFAStereo);
230
231    if (fbconfig->doublebuffer)
232        ADD_ATTR(NSOpenGLPFADoubleBuffer);
233
234    if (fbconfig->samples != GLFW_DONT_CARE)
235    {
236        if (fbconfig->samples == 0)
237        {
238            ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
239        }
240        else
241        {
242            ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
243            ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
244        }
245    }
246
247    // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
248    //       framebuffer, so there's no need (and no way) to request it
249
250    ADD_ATTR(0);
251
252#undef ADD_ATTR
253#undef ADD_ATTR2
254
255    window->context.nsgl.pixelFormat =
256        [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
257    if (window->context.nsgl.pixelFormat == nil)
258    {
259        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
260                        "NSGL: Failed to find a suitable pixel format");
261        return GLFW_FALSE;
262    }
263
264    NSOpenGLContext* share = NULL;
265
266    if (ctxconfig->share)
267        share = ctxconfig->share->context.nsgl.object;
268
269    window->context.nsgl.object =
270        [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
271                                   shareContext:share];
272    if (window->context.nsgl.object == nil)
273    {
274        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
275                        "NSGL: Failed to create OpenGL context");
276        return GLFW_FALSE;
277    }
278
279    [window->context.nsgl.object setView:window->ns.view];
280
281    window->context.makeCurrent = makeContextCurrentNSGL;
282    window->context.swapBuffers = swapBuffersNSGL;
283    window->context.swapInterval = swapIntervalNSGL;
284    window->context.extensionSupported = extensionSupportedNSGL;
285    window->context.getProcAddress = getProcAddressNSGL;
286    window->context.destroy = destroyContextNSGL;
287
288    return GLFW_TRUE;
289}
290
291
292//////////////////////////////////////////////////////////////////////////
293//////                        GLFW native API                       //////
294//////////////////////////////////////////////////////////////////////////
295
296GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
297{
298    _GLFWwindow* window = (_GLFWwindow*) handle;
299    _GLFW_REQUIRE_INIT_OR_RETURN(nil);
300
301    if (window->context.client == GLFW_NO_API)
302    {
303        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
304        return NULL;
305    }
306
307    return window->context.nsgl.object;
308}
309
310