2 * MACDRV Cocoa OpenGL code
4 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <OpenGL/gl.h>
22 #import "cocoa_opengl.h"
24 #include "macdrv_cocoa.h"
25 #include "cocoa_event.h"
28 @interface WineOpenGLContext ()
29 @property (retain, nonatomic) NSView* latentView;
33 @implementation WineOpenGLContext
34 @synthesize latentView, needsUpdate, shouldClearToBlack;
42 /* On at least some versions of Mac OS X, -[NSOpenGLContext clearDrawable] has the
43 undesirable side effect of ordering the view's GL surface off-screen. This isn't
44 done when just changing the context's view to a different view (which I would
45 think would be analogous, since the old view and surface end up without a
46 context attached). So, we finesse things by first setting the context's view to
47 a different view (the content view of an off-screen window) and then letting the
48 original implementation proceed. */
49 - (void) clearDrawableLeavingSurfaceOnScreen
51 static NSWindow* dummyWindow;
52 static dispatch_once_t once;
54 dispatch_once(&once, ^{
56 dummyWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
57 styleMask:NSBorderlessWindowMask
58 backing:NSBackingStoreBuffered
63 [self setView:[dummyWindow contentView]];
67 - (void) clearToBlackIfNeeded
69 if (shouldClearToBlack)
71 NSOpenGLContext* origContext = [NSOpenGLContext currentContext];
73 [self makeCurrentContext];
75 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
76 glDrawBuffer(GL_FRONT_AND_BACK);
77 glDisable(GL_SCISSOR_TEST);
78 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
79 glClearColor(0, 0, 0, 1);
80 glClear(GL_COLOR_BUFFER_BIT);
85 [origContext makeCurrentContext];
87 [NSOpenGLContext clearCurrentContext];
89 shouldClearToBlack = FALSE;
93 - (void) removeFromViews:(BOOL)removeViews
97 macdrv_remove_view_opengl_context((macdrv_view)[self view], (macdrv_opengl_context)self);
99 [self clearDrawableLeavingSurfaceOnScreen];
101 if ([self latentView])
103 macdrv_remove_view_opengl_context((macdrv_view)[self latentView], (macdrv_opengl_context)self);
105 [self setLatentView:nil];
113 /***********************************************************************
114 * macdrv_create_opengl_context
116 * Returns a Cocoa OpenGL context created from a CoreGL context. The
117 * caller is responsible for calling macdrv_dispose_opengl_context()
118 * when done with the context object.
120 macdrv_opengl_context macdrv_create_opengl_context(void* cglctx)
122 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
123 WineOpenGLContext *context;
125 context = [[WineOpenGLContext alloc] initWithCGLContextObj:cglctx];
128 return (macdrv_opengl_context)context;
131 /***********************************************************************
132 * macdrv_dispose_opengl_context
134 * Destroys a Cocoa OpenGL context previously created by
135 * macdrv_create_opengl_context();
137 void macdrv_dispose_opengl_context(macdrv_opengl_context c)
139 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
140 WineOpenGLContext *context = (WineOpenGLContext*)c;
142 [context removeFromViews:YES];
148 /***********************************************************************
149 * macdrv_make_context_current
151 void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v)
153 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
154 WineOpenGLContext *context = (WineOpenGLContext*)c;
155 NSView* view = (NSView*)v;
159 [context removeFromViews:NO];
162 macdrv_add_view_opengl_context(v, c);
164 if (context.needsUpdate)
166 context.needsUpdate = FALSE;
167 [context setView:view];
168 [context setLatentView:nil];
171 [context setLatentView:view];
173 [context makeCurrentContext];
176 [context clearToBlackIfNeeded];
180 [WineOpenGLContext clearCurrentContext];
181 [context removeFromViews:YES];
186 WineOpenGLContext* currentContext = (WineOpenGLContext*)[WineOpenGLContext currentContext];
188 if ([currentContext isKindOfClass:[WineOpenGLContext class]])
190 [WineOpenGLContext clearCurrentContext];
191 [currentContext removeFromViews:YES];
198 /***********************************************************************
199 * macdrv_update_opengl_context
201 void macdrv_update_opengl_context(macdrv_opengl_context c)
203 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
204 WineOpenGLContext *context = (WineOpenGLContext*)c;
206 if (context.needsUpdate)
208 context.needsUpdate = FALSE;
209 if (context.latentView)
211 [context setView:context.latentView];
212 context.latentView = nil;
214 [context clearToBlackIfNeeded];
223 /***********************************************************************
224 * macdrv_flush_opengl_context
226 * Performs an implicit glFlush() and then swaps the back buffer to the
227 * front (if the context is double-buffered).
229 void macdrv_flush_opengl_context(macdrv_opengl_context c)
231 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
232 WineOpenGLContext *context = (WineOpenGLContext*)c;
234 macdrv_update_opengl_context(c);
235 [context flushBuffer];