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 #import "cocoa_opengl.h"
23 #include "macdrv_cocoa.h"
24 #include "cocoa_event.h"
27 @interface WineOpenGLContext ()
28 @property (retain, nonatomic) NSView* latentView;
32 @implementation WineOpenGLContext
33 @synthesize latentView, needsUpdate, shouldClearToBlack;
41 /* On at least some versions of Mac OS X, -[NSOpenGLContext clearDrawable] has the
42 undesirable side effect of ordering the view's GL surface off-screen. This isn't
43 done when just changing the context's view to a different view (which I would
44 think would be analogous, since the old view and surface end up without a
45 context attached). So, we finesse things by first setting the context's view to
46 a different view (the content view of an off-screen window) and then letting the
47 original implementation proceed. */
48 - (void) clearDrawableLeavingSurfaceOnScreen
50 static NSWindow* dummyWindow;
51 static dispatch_once_t once;
53 dispatch_once(&once, ^{
55 dummyWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
56 styleMask:NSBorderlessWindowMask
57 backing:NSBackingStoreBuffered
62 [self setView:[dummyWindow contentView]];
66 - (void) clearToBlackIfNeeded
68 if (shouldClearToBlack)
70 NSOpenGLContext* origContext = [NSOpenGLContext currentContext];
72 [self makeCurrentContext];
74 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
75 glDrawBuffer(GL_FRONT_AND_BACK);
76 glDisable(GL_SCISSOR_TEST);
77 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
78 glClearColor(0, 0, 0, 1);
79 glClear(GL_COLOR_BUFFER_BIT);
84 [origContext makeCurrentContext];
86 [NSOpenGLContext clearCurrentContext];
88 shouldClearToBlack = FALSE;
95 /***********************************************************************
96 * macdrv_create_opengl_context
98 * Returns a Cocoa OpenGL context created from a CoreGL context. The
99 * caller is responsible for calling macdrv_dispose_opengl_context()
100 * when done with the context object.
102 macdrv_opengl_context macdrv_create_opengl_context(void* cglctx)
104 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
105 WineOpenGLContext *context;
107 context = [[WineOpenGLContext alloc] initWithCGLContextObj:cglctx];
110 return (macdrv_opengl_context)context;
113 /***********************************************************************
114 * macdrv_dispose_opengl_context
116 * Destroys a Cocoa OpenGL context previously created by
117 * macdrv_create_opengl_context();
119 void macdrv_dispose_opengl_context(macdrv_opengl_context c)
121 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
122 WineOpenGLContext *context = (WineOpenGLContext*)c;
125 macdrv_remove_view_opengl_context((macdrv_view)[context view], c);
126 if ([context latentView])
127 macdrv_remove_view_opengl_context((macdrv_view)[context latentView], c);
128 [context clearDrawableLeavingSurfaceOnScreen];
134 /***********************************************************************
135 * macdrv_make_context_current
137 void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v)
139 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
140 WineOpenGLContext *context = (WineOpenGLContext*)c;
141 NSView* view = (NSView*)v;
146 macdrv_remove_view_opengl_context((macdrv_view)[context view], c);
147 if ([context latentView])
148 macdrv_remove_view_opengl_context((macdrv_view)[context latentView], c);
149 context.needsUpdate = FALSE;
152 macdrv_add_view_opengl_context(v, c);
154 if (context.needsUpdate)
156 context.needsUpdate = FALSE;
157 [context setView:view];
158 [context setLatentView:nil];
161 [context setLatentView:view];
163 [context makeCurrentContext];
166 [context clearToBlackIfNeeded];
170 [WineOpenGLContext clearCurrentContext];
171 [context clearDrawableLeavingSurfaceOnScreen];
175 [WineOpenGLContext clearCurrentContext];
180 /***********************************************************************
181 * macdrv_update_opengl_context
183 void macdrv_update_opengl_context(macdrv_opengl_context c)
185 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
186 WineOpenGLContext *context = (WineOpenGLContext*)c;
188 if (context.needsUpdate)
190 context.needsUpdate = FALSE;
191 if (context.latentView)
193 [context setView:context.latentView];
194 context.latentView = nil;
196 [context clearToBlackIfNeeded];
205 /***********************************************************************
206 * macdrv_flush_opengl_context
208 * Performs an implicit glFlush() and then swaps the back buffer to the
209 * front (if the context is double-buffered).
211 void macdrv_flush_opengl_context(macdrv_opengl_context c)
213 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
214 WineOpenGLContext *context = (WineOpenGLContext*)c;
216 macdrv_update_opengl_context(c);
217 [context flushBuffer];