winemac: Use unixlib interface for dragdrop.c calls.
[wine.git] / dlls / winemac.drv / opengl.c
blobcf58588981ff0d51d345d35133bc771ec5154b90
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #include "macdrv.h"
26 #include "winuser.h"
27 #include "winternl.h"
28 #include "winnt.h"
29 #include "wine/debug.h"
30 #include "wine/wgl.h"
31 #include "wine/wgl_driver.h"
33 #define GL_SILENCE_DEPRECATION
34 #define __gl_h_
35 #define __gltypes_h_
36 #include <OpenGL/OpenGL.h>
37 #include <OpenGL/glu.h>
38 #include <OpenGL/CGLRenderers.h>
39 #include <dlfcn.h>
41 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
44 struct gl_info {
45 char *glExtensions;
47 char wglExtensions[4096];
49 GLint max_viewport_dims[2];
51 unsigned int max_major, max_minor;
54 static struct gl_info gl_info;
57 struct wgl_context
59 struct list entry;
60 int format;
61 GLint renderer_id;
62 macdrv_opengl_context context;
63 CGLContextObj cglcontext;
64 HWND draw_hwnd;
65 macdrv_view draw_view;
66 RECT draw_rect;
67 struct wgl_pbuffer *draw_pbuffer;
68 macdrv_view read_view;
69 RECT read_rect;
70 struct wgl_pbuffer *read_pbuffer;
71 BOOL has_been_current;
72 BOOL sharing;
73 LONG update_swap_interval;
74 LONG view_moved;
75 DWORD last_flush_time;
76 UINT major;
79 static struct list context_list = LIST_INIT(context_list);
80 static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER;
83 struct wgl_pbuffer
85 CGLPBufferObj pbuffer;
86 int format;
87 BOOL no_texture;
88 int max_level;
89 GLint level;
90 GLenum face;
93 static CFMutableDictionaryRef dc_pbuffers;
94 static pthread_mutex_t dc_pbuffers_mutex = PTHREAD_MUTEX_INITIALIZER;
97 static struct opengl_funcs opengl_funcs;
99 #define USE_GL_FUNC(name) #name,
100 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
101 #undef USE_GL_FUNC
104 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
105 GLsizei width);
106 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
107 static void (*pglFinish)(void);
108 static void (*pglFlush)(void);
109 static void (*pglFlushRenderAPPLE)(void);
110 static const GLubyte *(*pglGetString)(GLenum name);
111 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
112 GLenum format, GLenum type, void *pixels);
113 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
116 struct color_mode {
117 GLint mode;
118 int bits_per_pixel;
119 GLint color_bits; /* including alpha_bits */
120 int red_bits, red_shift;
121 int green_bits, green_shift;
122 int blue_bits, blue_shift;
123 GLint alpha_bits, alpha_shift;
124 BOOL is_float;
125 int color_ordering;
128 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
129 observations of the behavior of Windows systems, but also subjective judgments
130 about what color formats are more "normal" than others.
132 On at least some Windows systems, integer color formats are listed before
133 floating-point formats. Within the integer formats, higher color bits were
134 usually listed before lower color bits, while for floating-point formats it
135 was the reverse. However, that leads D3D to select 64-bit integer formats in
136 preference to 32-bit formats when the latter would be sufficient. It seems
137 that a 32-bit format is much more likely to be normally used in that case.
139 Also, there are certain odd color formats supported on the Mac which seem like
140 they would be less appropriate than more common ones. For instance, the color
141 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
142 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
143 components.
145 For two color formats which differ only in whether or not they have alpha bits,
146 we use the same ordering. pixel_format_comparator() gives alpha bits a
147 different weight than color formats.
149 static const struct color_mode color_modes[] = {
150 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
151 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
152 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
153 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
154 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
155 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
156 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
157 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
158 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
159 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
160 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
161 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
162 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
163 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
164 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
165 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
166 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
167 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
168 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
169 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
170 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
171 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
172 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
173 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
177 static const struct {
178 GLint mode;
179 int bits;
180 } depth_stencil_modes[] = {
181 { kCGL0Bit, 0 },
182 { kCGL1Bit, 1 },
183 { kCGL2Bit, 2 },
184 { kCGL3Bit, 3 },
185 { kCGL4Bit, 4 },
186 { kCGL5Bit, 5 },
187 { kCGL6Bit, 6 },
188 { kCGL8Bit, 8 },
189 { kCGL10Bit, 10 },
190 { kCGL12Bit, 12 },
191 { kCGL16Bit, 16 },
192 { kCGL24Bit, 24 },
193 { kCGL32Bit, 32 },
194 { kCGL48Bit, 48 },
195 { kCGL64Bit, 64 },
196 { kCGL96Bit, 96 },
197 { kCGL128Bit, 128 },
201 typedef struct {
202 GLint renderer_id;
203 GLint buffer_modes;
204 GLint color_modes;
205 GLint accum_modes;
206 GLint depth_modes;
207 GLint stencil_modes;
208 GLint max_aux_buffers;
209 GLint max_sample_buffers;
210 GLint max_samples;
211 BOOL offscreen;
212 BOOL accelerated;
213 BOOL backing_store;
214 BOOL window;
215 BOOL online;
216 } renderer_properties;
219 typedef struct {
220 unsigned int window:1;
221 unsigned int pbuffer:1;
222 unsigned int accelerated:1;
223 unsigned int color_mode:5; /* index into color_modes table */
224 unsigned int aux_buffers:3;
225 unsigned int depth_bits:8;
226 unsigned int stencil_bits:8;
227 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
228 unsigned int double_buffer:1;
229 unsigned int stereo:1;
230 unsigned int sample_buffers:1;
231 unsigned int samples:5;
232 unsigned int backing_store:1;
233 } pixel_format;
236 typedef union
238 pixel_format format;
239 UInt64 code;
240 } pixel_format_or_code;
241 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
244 static pixel_format *pixel_formats;
245 static int nb_formats, nb_displayable_formats;
248 static void *opengl_handle;
251 static const char* debugstr_attrib(int attrib, int value)
253 static const struct {
254 int attrib;
255 const char *name;
256 } attrib_names[] = {
257 #define ATTRIB(a) { a, #a }
258 ATTRIB(WGL_ACCELERATION_ARB),
259 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
260 ATTRIB(WGL_ACCUM_BITS_ARB),
261 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
262 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
263 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
264 ATTRIB(WGL_ALPHA_BITS_ARB),
265 ATTRIB(WGL_ALPHA_SHIFT_ARB),
266 ATTRIB(WGL_AUX_BUFFERS_ARB),
267 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
268 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
269 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
270 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
271 ATTRIB(WGL_BLUE_BITS_ARB),
272 ATTRIB(WGL_BLUE_SHIFT_ARB),
273 ATTRIB(WGL_COLOR_BITS_ARB),
274 ATTRIB(WGL_DEPTH_BITS_ARB),
275 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
276 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
277 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
278 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
279 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
280 ATTRIB(WGL_GREEN_BITS_ARB),
281 ATTRIB(WGL_GREEN_SHIFT_ARB),
282 ATTRIB(WGL_NEED_PALETTE_ARB),
283 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
284 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
285 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
286 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
287 ATTRIB(WGL_PIXEL_TYPE_ARB),
288 ATTRIB(WGL_RED_BITS_ARB),
289 ATTRIB(WGL_RED_SHIFT_ARB),
290 ATTRIB(WGL_RENDERER_ID_WINE),
291 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
292 ATTRIB(WGL_SAMPLES_ARB),
293 ATTRIB(WGL_SHARE_ACCUM_ARB),
294 ATTRIB(WGL_SHARE_DEPTH_ARB),
295 ATTRIB(WGL_SHARE_STENCIL_ARB),
296 ATTRIB(WGL_STENCIL_BITS_ARB),
297 ATTRIB(WGL_STEREO_ARB),
298 ATTRIB(WGL_SUPPORT_GDI_ARB),
299 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
300 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
301 ATTRIB(WGL_SWAP_METHOD_ARB),
302 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
303 ATTRIB(WGL_TRANSPARENT_ARB),
304 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
305 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
306 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
307 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
308 #undef ATTRIB
310 int i;
311 const char *attrib_name = NULL;
312 const char *value_name = NULL;
314 for (i = 0; i < ARRAY_SIZE(attrib_names); i++)
316 if (attrib_names[i].attrib == attrib)
318 attrib_name = attrib_names[i].name;
319 break;
323 if (!attrib_name)
324 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
326 switch (attrib)
328 case WGL_ACCELERATION_ARB:
329 switch (value)
331 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
332 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
333 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
335 break;
336 case WGL_PIXEL_TYPE_ARB:
337 switch (value)
339 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
340 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
341 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
342 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
344 break;
345 case WGL_SWAP_METHOD_ARB:
346 switch (value)
348 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
349 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
350 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
352 break;
355 if (!value_name)
356 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
358 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
362 /**********************************************************************
363 * active_displays_mask
365 static CGOpenGLDisplayMask active_displays_mask(void)
367 CGError err;
368 CGDirectDisplayID displays[32];
369 uint32_t count, i;
370 CGOpenGLDisplayMask mask;
372 err = CGGetActiveDisplayList(ARRAY_SIZE(displays), displays, &count);
373 if (err != kCGErrorSuccess)
375 displays[0] = CGMainDisplayID();
376 count = 1;
379 mask = 0;
380 for (i = 0; i < count; i++)
381 mask |= CGDisplayIDToOpenGLDisplayMask(displays[i]);
383 return mask;
387 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
388 CGLRendererProperty property, GLint *value)
390 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
391 if (err != kCGLNoError)
392 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
393 return (err == kCGLNoError);
397 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
399 GLint value;
401 memset(properties, 0, sizeof(*properties));
403 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
404 properties->renderer_id = value & kCGLRendererIDMatchingMask;
406 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
407 properties->buffer_modes = value;
409 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
410 properties->color_modes = value;
412 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
413 properties->accum_modes = value;
415 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
416 properties->depth_modes = value;
418 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
419 properties->stencil_modes = value;
421 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
422 properties->max_aux_buffers = value;
424 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
425 properties->max_sample_buffers = value;
427 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
428 properties->max_samples = value;
430 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
431 properties->offscreen = (value != 0);
433 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
434 properties->accelerated = (value != 0);
436 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
437 properties->backing_store = (value != 0);
439 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
440 properties->window = (value != 0);
442 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
443 properties->online = (value != 0);
447 static void dump_renderer(const renderer_properties* renderer)
449 int i;
451 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
452 TRACE("Buffer modes:\n");
453 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
454 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
455 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
456 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
458 TRACE("Color buffer modes:\n");
459 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
461 if (renderer->color_modes & color_modes[i].mode)
463 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
464 if (color_modes[i].is_float)
465 TRACE(", Float");
466 TRACE("\n");
470 TRACE("Accumulation buffer sizes: { ");
471 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
473 if (renderer->accum_modes & color_modes[i].mode)
474 TRACE("%d, ", color_modes[i].color_bits);
476 TRACE("}\n");
478 TRACE("Depth buffer sizes: { ");
479 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
481 if (renderer->depth_modes & depth_stencil_modes[i].mode)
482 TRACE("%d, ", depth_stencil_modes[i].bits);
484 TRACE("}\n");
486 TRACE("Stencil buffer sizes: { ");
487 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
489 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
490 TRACE("%d, ", depth_stencil_modes[i].bits);
492 TRACE("}\n");
494 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
495 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
496 TRACE("Max. Samples: %d\n", renderer->max_samples);
497 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
498 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
499 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
500 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
501 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
505 static inline UInt64 code_for_pixel_format(const pixel_format* format)
507 pixel_format_or_code pfc;
509 pfc.code = 0;
510 pfc.format = *format;
511 return pfc.code;
515 static inline pixel_format pixel_format_for_code(UInt64 code)
517 pixel_format_or_code pfc;
519 pfc.code = code;
520 return pfc.format;
524 static const char *debugstr_pf(const pixel_format *pf)
526 return wine_dbg_sprintf("w/p/a %u/%u/%u col %u%s/%u dp/stn/ac/ax/b/db/str %u/%u/%u/%u/%u/%u/%u samp %u/%u %017llx",
527 pf->window,
528 pf->pbuffer,
529 pf->accelerated,
530 color_modes[pf->color_mode].color_bits,
531 (color_modes[pf->color_mode].is_float ? "f" : ""),
532 color_modes[pf->color_mode].alpha_bits,
533 pf->depth_bits,
534 pf->stencil_bits,
535 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
536 pf->aux_buffers,
537 pf->backing_store,
538 pf->double_buffer,
539 pf->stereo,
540 pf->sample_buffers,
541 pf->samples,
542 code_for_pixel_format(pf));
546 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
548 int best = -1;
549 int i;
551 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
553 if ((modes & color_modes[i].mode) &&
554 color_modes[i].color_bits >= color_size &&
555 color_modes[i].alpha_bits >= alpha_size &&
556 !color_modes[i].is_float == !color_float)
558 if (best < 0) /* no existing best choice */
559 best = i;
560 else if (color_modes[i].color_bits == color_size &&
561 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
563 /* prefer it over a best which isn't exact or which has a higher bpp */
564 if (color_modes[best].color_bits != color_size ||
565 color_modes[best].alpha_bits != alpha_size ||
566 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
567 best = i;
569 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
570 (color_modes[i].color_bits == color_modes[best].color_bits &&
571 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
572 best = i;
576 if (best < 0)
578 /* Couldn't find a match. Return first one that renderer supports. */
579 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
581 if (modes & color_modes[i].mode)
582 return i;
586 return best;
590 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
592 int best = -1;
593 int i;
595 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
597 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
599 /* Prefer the fewest color bits, then prefer more alpha bits, then
600 prefer more bits per pixel. */
601 if (best < 0)
602 best = i;
603 else if (color_modes[i].color_bits < color_modes[best].color_bits)
604 best = i;
605 else if (color_modes[i].color_bits == color_modes[best].color_bits)
607 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
608 best = i;
609 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
610 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
611 best = i;
616 if (best < 0)
618 /* Couldn't find a match. Return last one that renderer supports. */
619 for (i = ARRAY_SIZE(color_modes) - 1; i >= 0; i--)
621 if (modes & color_modes[i].mode)
622 return i;
626 return best;
630 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
631 CFMutableSetRef pixel_format_set)
633 CGLPixelFormatAttribute attribs[64] = {
634 kCGLPFAMinimumPolicy,
635 kCGLPFAClosestPolicy,
636 kCGLPFARendererID, renderer.renderer_id,
637 kCGLPFASingleRenderer,
639 int n = 5, n_stack[16], n_stack_idx = -1;
640 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
641 new_pixel_formats = 0;
642 pixel_format request;
643 unsigned int double_buffer;
644 unsigned int accelerated = renderer.accelerated;
646 if (accelerated)
648 attribs[n++] = kCGLPFAAccelerated;
649 attribs[n++] = kCGLPFANoRecovery;
651 else if (!allow_software_rendering)
653 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
654 return;
657 n_stack[++n_stack_idx] = n;
658 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
660 unsigned int aux;
662 n = n_stack[n_stack_idx];
664 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
665 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
666 continue;
668 if (double_buffer)
669 attribs[n++] = kCGLPFADoubleBuffer;
670 memset(&request, 0, sizeof(request));
671 request.accelerated = accelerated;
672 request.double_buffer = double_buffer;
674 /* Don't bother with in-between aux buffers values: either 0 or max. */
675 n_stack[++n_stack_idx] = n;
676 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
678 unsigned int color_mode;
680 n = n_stack[n_stack_idx];
682 attribs[n++] = kCGLPFAAuxBuffers;
683 attribs[n++] = aux;
684 request.aux_buffers = aux;
686 n_stack[++n_stack_idx] = n;
687 for (color_mode = 0; color_mode < ARRAY_SIZE(color_modes); color_mode++)
689 unsigned int depth_mode;
691 n = n_stack[n_stack_idx];
693 if (!(renderer.color_modes & color_modes[color_mode].mode))
694 continue;
696 attribs[n++] = kCGLPFAColorSize;
697 attribs[n++] = color_modes[color_mode].color_bits;
698 attribs[n++] = kCGLPFAAlphaSize;
699 attribs[n++] = color_modes[color_mode].alpha_bits;
700 if (color_modes[color_mode].is_float)
701 attribs[n++] = kCGLPFAColorFloat;
702 request.color_mode = color_mode;
704 n_stack[++n_stack_idx] = n;
705 for (depth_mode = 0; depth_mode < ARRAY_SIZE(depth_stencil_modes); depth_mode++)
707 unsigned int stencil_mode;
709 n = n_stack[n_stack_idx];
711 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
712 continue;
714 attribs[n++] = kCGLPFADepthSize;
715 attribs[n++] = depth_stencil_modes[depth_mode].bits;
716 request.depth_bits = depth_stencil_modes[depth_mode].bits;
718 n_stack[++n_stack_idx] = n;
719 for (stencil_mode = 0; stencil_mode < ARRAY_SIZE(depth_stencil_modes); stencil_mode++)
721 unsigned int stereo;
723 n = n_stack[n_stack_idx];
725 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
726 continue;
727 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 &&
728 depth_stencil_modes[depth_mode].bits != 32 && stencil_mode > 0)
729 continue;
731 attribs[n++] = kCGLPFAStencilSize;
732 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
733 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
735 /* FIXME: Could trim search space a bit here depending on GPU.
736 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
737 n_stack[++n_stack_idx] = n;
738 for (stereo = 0; stereo <= 1; stereo++)
740 int accum_mode;
742 n = n_stack[n_stack_idx];
744 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
745 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
746 continue;
748 if (stereo)
749 attribs[n++] = kCGLPFAStereo;
750 request.stereo = stereo;
752 /* Starts at -1 for a 0 accum size */
753 n_stack[++n_stack_idx] = n;
754 for (accum_mode = -1; accum_mode < (int) ARRAY_SIZE(color_modes); accum_mode++)
756 unsigned int target_pass;
758 n = n_stack[n_stack_idx];
760 if (accum_mode >= 0)
762 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
763 continue;
765 attribs[n++] = kCGLPFAAccumSize;
766 attribs[n++] = color_modes[accum_mode].color_bits;
767 request.accum_mode = accum_mode + 1;
769 else
770 request.accum_mode = 0;
772 /* Targets to request are:
773 accelerated: window OR window + pbuffer
774 software: window + pbuffer */
775 n_stack[++n_stack_idx] = n;
776 for (target_pass = 0; target_pass <= accelerated; target_pass++)
778 unsigned int samples, max_samples;
780 n = n_stack[n_stack_idx];
782 attribs[n++] = kCGLPFAWindow;
783 request.window = 1;
785 if (!accelerated || target_pass > 0)
787 attribs[n++] = kCGLPFAPBuffer;
788 request.pbuffer = 1;
790 else
791 request.pbuffer = 0;
793 /* FIXME: Could trim search space a bit here depending on GPU.
794 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
795 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
796 n_stack[++n_stack_idx] = n;
797 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
798 for (samples = 1; samples <= max_samples; samples *= 2)
800 unsigned int backing_store, min_backing_store, max_backing_store;
802 n = n_stack[n_stack_idx];
804 if (samples > 1)
806 attribs[n++] = kCGLPFASampleBuffers;
807 attribs[n++] = renderer.max_sample_buffers;
808 attribs[n++] = kCGLPFASamples;
809 attribs[n++] = samples;
810 request.sample_buffers = renderer.max_sample_buffers;
811 request.samples = samples;
813 else
814 request.sample_buffers = request.samples = 0;
816 if (renderer.backing_store && double_buffer)
818 /* The software renderer seems to always preserve the backing store, whether
819 we ask for it or not. So don't bother not asking for it. */
820 min_backing_store = accelerated ? 0 : 1;
821 max_backing_store = 1;
823 else
824 min_backing_store = max_backing_store = 0;
825 n_stack[++n_stack_idx] = n;
826 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
828 CGLPixelFormatObj pix;
829 GLint virtualScreens;
830 CGLError err;
832 n = n_stack[n_stack_idx];
834 if (backing_store)
835 attribs[n++] = kCGLPFABackingStore;
836 request.backing_store = backing_store;
838 attribs[n] = 0;
840 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
841 if (err == kCGLNoError && pix)
843 pixel_format pf;
844 GLint value, color_size, alpha_size, color_float;
845 UInt64 pf_code;
846 CFNumberRef code_object;
847 BOOL dupe;
849 memset(&pf, 0, sizeof(pf));
851 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
852 pf.accelerated = value;
853 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
854 pf.aux_buffers = value;
855 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
856 pf.depth_bits = value;
857 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
858 pf.double_buffer = value;
859 if (pf.double_buffer &&
860 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
861 pf.backing_store = value;
862 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
863 pf.pbuffer = value;
864 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
865 pf.sample_buffers = value;
866 if (pf.sample_buffers &&
867 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
868 pf.samples = value;
869 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
870 pf.stencil_bits = value;
871 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
872 pf.stereo = value;
873 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
874 pf.window = value;
876 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
877 color_size = 0;
878 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
879 alpha_size = 0;
880 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
881 color_float = 0;
882 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
884 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
885 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
887 CGLReleasePixelFormat(pix);
889 pf_code = code_for_pixel_format(&pf);
891 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
892 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
893 dupe_pixel_formats++;
894 else
896 CFSetAddValue(pixel_format_set, code_object);
897 CFArrayAppendValue(pixel_format_array, code_object);
898 new_pixel_formats++;
900 CFRelease(code_object);
902 if (pf_code == code_for_pixel_format(&request))
903 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
904 else
906 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
907 dupe ? " (duplicate)" : "");
910 else
912 failed_pixel_formats++;
913 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
916 tried_pixel_formats++;
919 n_stack_idx--;
922 n_stack_idx--;
925 n_stack_idx--;
928 n_stack_idx--;
931 n_stack_idx--;
934 n_stack_idx--;
937 n_stack_idx--;
940 n_stack_idx--;
943 n_stack_idx--;
946 n_stack_idx--;
948 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
949 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
950 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
951 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
955 /* The docs for WGL_ARB_pixel_format say:
956 Indices are assigned to pixel formats in the following order:
957 1. Accelerated pixel formats that are displayable
958 2. Accelerated pixel formats that are displayable and which have
959 extended attributes
960 3. Generic pixel formats
961 4. Accelerated pixel formats that are non displayable
963 static int pixel_format_category(pixel_format pf)
965 /* non-displayable */
966 if (!pf.window)
967 return 4;
969 /* non-accelerated a.k.a. software a.k.a. generic */
970 if (!pf.accelerated)
971 return 3;
973 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
974 if (color_modes[pf.color_mode].is_float)
975 return 2;
977 /* accelerated, displayable, no extended attributes */
978 return 1;
982 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
984 CFNumberRef number1 = val1;
985 CFNumberRef number2 = val2;
986 UInt64 code1, code2;
987 pixel_format pf1, pf2;
988 int category1, category2;
990 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
991 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
992 pf1 = pixel_format_for_code(code1);
993 pf2 = pixel_format_for_code(code2);
994 category1 = pixel_format_category(pf1);
995 category2 = pixel_format_category(pf2);
997 if (category1 < category2)
998 return kCFCompareLessThan;
999 if (category1 > category2)
1000 return kCFCompareGreaterThan;
1002 /* Within a category, sort the "best" formats toward the front since that's
1003 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1004 matches at least one Windows 7 machine's behavior.
1006 /* Accelerated before unaccelerated. */
1007 if (pf1.accelerated && !pf2.accelerated)
1008 return kCFCompareLessThan;
1009 if (!pf1.accelerated && pf2.accelerated)
1010 return kCFCompareGreaterThan;
1012 /* Explicit color mode ordering. */
1013 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1014 return kCFCompareLessThan;
1015 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1016 return kCFCompareGreaterThan;
1018 /* Non-pbuffer-capable before pbuffer-capable. */
1019 if (!pf1.pbuffer && pf2.pbuffer)
1020 return kCFCompareLessThan;
1021 if (pf1.pbuffer && !pf2.pbuffer)
1022 return kCFCompareGreaterThan;
1024 /* Fewer samples before more samples. */
1025 if (pf1.samples < pf2.samples)
1026 return kCFCompareLessThan;
1027 if (pf1.samples > pf2.samples)
1028 return kCFCompareGreaterThan;
1030 /* Monoscopic before stereoscopic. (This is a guess.) */
1031 if (!pf1.stereo && pf2.stereo)
1032 return kCFCompareLessThan;
1033 if (pf1.stereo && !pf2.stereo)
1034 return kCFCompareGreaterThan;
1036 /* Single buffered before double buffered. */
1037 if (!pf1.double_buffer && pf2.double_buffer)
1038 return kCFCompareLessThan;
1039 if (pf1.double_buffer && !pf2.double_buffer)
1040 return kCFCompareGreaterThan;
1042 /* Possibly-optimized double buffering before backing-store-preserving
1043 double buffering. */
1044 if (!pf1.backing_store && pf2.backing_store)
1045 return kCFCompareLessThan;
1046 if (pf1.backing_store && !pf2.backing_store)
1047 return kCFCompareGreaterThan;
1049 /* Bigger depth buffer before smaller depth buffer. */
1050 if (pf1.depth_bits > pf2.depth_bits)
1051 return kCFCompareLessThan;
1052 if (pf1.depth_bits < pf2.depth_bits)
1053 return kCFCompareGreaterThan;
1055 /* Smaller stencil buffer before bigger stencil buffer. */
1056 if (pf1.stencil_bits < pf2.stencil_bits)
1057 return kCFCompareLessThan;
1058 if (pf1.stencil_bits > pf2.stencil_bits)
1059 return kCFCompareGreaterThan;
1061 /* Smaller alpha bits before larger alpha bits. */
1062 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1063 return kCFCompareLessThan;
1064 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1065 return kCFCompareGreaterThan;
1067 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1068 if (pf1.accum_mode)
1070 if (pf2.accum_mode)
1072 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1073 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1074 return kCFCompareLessThan;
1075 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1076 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1077 return kCFCompareGreaterThan;
1079 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1080 return kCFCompareLessThan;
1081 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1082 return kCFCompareGreaterThan;
1084 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1085 return kCFCompareLessThan;
1086 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1087 return kCFCompareGreaterThan;
1089 else
1090 return kCFCompareGreaterThan;
1092 else if (pf2.accum_mode)
1093 return kCFCompareLessThan;
1095 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1096 if (pf1.aux_buffers < pf2.aux_buffers)
1097 return kCFCompareLessThan;
1098 if (pf1.aux_buffers > pf2.aux_buffers)
1099 return kCFCompareGreaterThan;
1101 /* If we get here, arbitrarily sort based on code. */
1102 if (code1 < code2)
1103 return kCFCompareLessThan;
1104 if (code1 > code2)
1105 return kCFCompareGreaterThan;
1106 return kCFCompareEqualTo;
1110 static BOOL init_pixel_formats(void)
1112 BOOL ret = FALSE;
1113 CGLRendererInfoObj renderer_info;
1114 GLint rendererCount;
1115 CGLError err;
1116 CFMutableSetRef pixel_format_set;
1117 CFMutableArrayRef pixel_format_array;
1118 int i;
1119 CFRange range;
1121 TRACE("()\n");
1123 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1124 if (err)
1126 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1127 return FALSE;
1130 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1131 if (!pixel_format_set)
1133 WARN("CFSetCreateMutable failed\n");
1134 CGLDestroyRendererInfo(renderer_info);
1135 return FALSE;
1138 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1139 if (!pixel_format_array)
1141 WARN("CFArrayCreateMutable failed\n");
1142 CFRelease(pixel_format_set);
1143 CGLDestroyRendererInfo(renderer_info);
1144 return FALSE;
1147 for (i = 0; i < rendererCount; i++)
1149 renderer_properties renderer;
1151 get_renderer_properties(renderer_info, i, &renderer);
1152 if (TRACE_ON(wgl))
1154 TRACE("renderer_properties %d:\n", i);
1155 dump_renderer(&renderer);
1158 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1161 CFRelease(pixel_format_set);
1162 CGLDestroyRendererInfo(renderer_info);
1164 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1165 if (range.length)
1167 pixel_formats = malloc(range.length * sizeof(*pixel_formats));
1168 if (pixel_formats)
1170 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1171 for (i = 0; i < range.length; i++)
1173 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1174 UInt64 code;
1176 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1177 pixel_formats[i] = pixel_format_for_code(code);
1178 if (pixel_formats[i].window)
1179 nb_displayable_formats++;
1182 nb_formats = range.length;
1183 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1184 ret = TRUE;
1186 else
1187 WARN("failed to allocate pixel format list\n");
1189 else
1190 WARN("got no pixel formats\n");
1192 CFRelease(pixel_format_array);
1193 return ret;
1197 static inline BOOL is_valid_pixel_format(int format)
1199 return format > 0 && format <= nb_formats;
1203 static inline BOOL is_displayable_pixel_format(int format)
1205 return format > 0 && format <= nb_displayable_formats;
1209 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1211 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1212 * format in case of probing the number of pixel formats.
1214 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1216 TRACE("Returning format %d\n", format);
1217 return &pixel_formats[format - 1];
1219 return NULL;
1223 static BOOL init_gl_info(void)
1225 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1226 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1228 CGDirectDisplayID display = CGMainDisplayID();
1229 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1230 CGLPixelFormatAttribute attribs[] = {
1231 kCGLPFADisplayMask, displayMask,
1234 CGLPixelFormatAttribute core_attribs[] =
1236 kCGLPFADisplayMask, displayMask,
1237 kCGLPFAAccelerated,
1238 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1241 CGLPixelFormatObj pix;
1242 GLint virtualScreens;
1243 CGLError err;
1244 CGLContextObj context;
1245 CGLContextObj old_context = CGLGetCurrentContext();
1246 const char *str;
1247 size_t length;
1249 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1250 if (err != kCGLNoError || !pix)
1252 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1253 return FALSE;
1256 err = CGLCreateContext(pix, NULL, &context);
1257 CGLReleasePixelFormat(pix);
1258 if (err != kCGLNoError || !context)
1260 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1261 return FALSE;
1264 err = CGLSetCurrentContext(context);
1265 if (err != kCGLNoError)
1267 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1268 CGLReleaseContext(context);
1269 return FALSE;
1272 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1273 length = strlen(str) + sizeof(legacy_extensions);
1274 if (allow_vsync)
1275 length += strlen(legacy_ext_swap_control);
1276 gl_info.glExtensions = malloc(length);
1277 strcpy(gl_info.glExtensions, str);
1278 strcat(gl_info.glExtensions, legacy_extensions);
1279 if (allow_vsync)
1280 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1282 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1284 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1285 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1286 TRACE("GL version : %s\n", str);
1287 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1289 CGLSetCurrentContext(old_context);
1290 CGLReleaseContext(context);
1292 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1293 if (err != kCGLNoError || !pix)
1295 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1296 err, CGLErrorString(err));
1297 return TRUE;
1300 err = CGLCreateContext(pix, NULL, &context);
1301 CGLReleasePixelFormat(pix);
1302 if (err != kCGLNoError || !context)
1304 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1305 err, CGLErrorString(err));
1306 return TRUE;
1309 err = CGLSetCurrentContext(context);
1310 if (err != kCGLNoError)
1312 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1313 err, CGLErrorString(err));
1314 CGLReleaseContext(context);
1315 return TRUE;
1318 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1319 TRACE("Core context GL version: %s\n", str);
1320 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1321 CGLSetCurrentContext(old_context);
1322 CGLReleaseContext(context);
1324 return TRUE;
1328 static int get_dc_pixel_format(HDC hdc)
1330 int format;
1331 HWND hwnd;
1333 if ((hwnd = NtUserWindowFromDC(hdc)))
1335 struct macdrv_win_data *data;
1337 if (!(data = get_win_data(hwnd)))
1339 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1340 return 0;
1343 format = data->pixel_format;
1344 release_win_data(data);
1346 else
1348 struct wgl_pbuffer *pbuffer;
1350 pthread_mutex_lock(&dc_pbuffers_mutex);
1351 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1352 if (pbuffer)
1353 format = pbuffer->format;
1354 else
1356 WARN("no window or pbuffer for DC %p\n", hdc);
1357 format = 0;
1359 pthread_mutex_unlock(&dc_pbuffers_mutex);
1362 return format;
1366 /**********************************************************************
1367 * create_context
1369 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1371 const pixel_format *pf;
1372 CGLPixelFormatAttribute attribs[64];
1373 int n = 0;
1374 CGLPixelFormatObj pix;
1375 GLint virtualScreens;
1376 CGLError err;
1377 BOOL core = major >= 3;
1379 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1380 if (!pf)
1382 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1383 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1384 return FALSE;
1387 attribs[n++] = kCGLPFAMinimumPolicy;
1388 attribs[n++] = kCGLPFAClosestPolicy;
1390 if (context->renderer_id)
1392 attribs[n++] = kCGLPFARendererID;
1393 attribs[n++] = context->renderer_id;
1394 attribs[n++] = kCGLPFASingleRenderer;
1395 attribs[n++] = kCGLPFANoRecovery;
1398 if (pf->accelerated)
1400 attribs[n++] = kCGLPFAAccelerated;
1401 attribs[n++] = kCGLPFANoRecovery;
1403 else
1405 attribs[n++] = kCGLPFARendererID;
1406 attribs[n++] = kCGLRendererGenericFloatID;
1409 if (pf->double_buffer)
1410 attribs[n++] = kCGLPFADoubleBuffer;
1412 if (!core)
1414 attribs[n++] = kCGLPFAAuxBuffers;
1415 attribs[n++] = pf->aux_buffers;
1418 attribs[n++] = kCGLPFAColorSize;
1419 attribs[n++] = color_modes[pf->color_mode].color_bits;
1420 attribs[n++] = kCGLPFAAlphaSize;
1421 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1422 if (color_modes[pf->color_mode].is_float)
1423 attribs[n++] = kCGLPFAColorFloat;
1425 attribs[n++] = kCGLPFADepthSize;
1426 attribs[n++] = pf->depth_bits;
1428 attribs[n++] = kCGLPFAStencilSize;
1429 attribs[n++] = pf->stencil_bits;
1431 if (pf->stereo)
1432 attribs[n++] = kCGLPFAStereo;
1434 if (pf->accum_mode && !core)
1436 attribs[n++] = kCGLPFAAccumSize;
1437 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1440 if (pf->pbuffer && !core)
1441 attribs[n++] = kCGLPFAPBuffer;
1443 if (pf->sample_buffers && pf->samples)
1445 attribs[n++] = kCGLPFASampleBuffers;
1446 attribs[n++] = pf->sample_buffers;
1447 attribs[n++] = kCGLPFASamples;
1448 attribs[n++] = pf->samples;
1451 if (pf->backing_store)
1452 attribs[n++] = kCGLPFABackingStore;
1454 if (core)
1456 attribs[n++] = kCGLPFAOpenGLProfile;
1457 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1458 if (major == 3)
1459 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1460 else
1461 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1462 #else
1463 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1464 #endif
1467 attribs[n] = 0;
1469 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1470 if (err != kCGLNoError || !pix)
1472 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1473 SetLastError(ERROR_INVALID_OPERATION);
1474 return FALSE;
1477 err = CGLCreateContext(pix, share, &context->cglcontext);
1478 CGLReleasePixelFormat(pix);
1479 if (err != kCGLNoError || !context->cglcontext)
1481 context->cglcontext = NULL;
1482 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1483 SetLastError(ERROR_INVALID_OPERATION);
1484 return FALSE;
1487 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1489 GLint opacity = 0;
1490 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1491 if (err != kCGLNoError)
1492 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1494 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1496 GLint order = -1;
1497 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1498 if (err != kCGLNoError)
1499 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1502 context->context = macdrv_create_opengl_context(context->cglcontext);
1503 CGLReleaseContext(context->cglcontext);
1504 if (!context->context)
1506 WARN("macdrv_create_opengl_context() failed\n");
1507 SetLastError(ERROR_INVALID_OPERATION);
1508 return FALSE;
1510 context->major = major;
1512 InterlockedExchange(&context->update_swap_interval, TRUE);
1514 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1516 return TRUE;
1520 /**********************************************************************
1521 * set_pixel_format
1523 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1525 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1527 struct macdrv_win_data *data;
1528 const pixel_format *pf;
1529 HWND hwnd = NtUserWindowFromDC(hdc);
1530 BOOL ret = FALSE;
1532 TRACE("hdc %p format %d\n", hdc, fmt);
1534 if (!hwnd || hwnd == NtUserGetDesktopWindow())
1536 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1537 return FALSE;
1540 if (!(data = get_win_data(hwnd)))
1542 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1543 return FALSE;
1546 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1548 ret = (data->pixel_format == fmt);
1549 goto done;
1552 /* Check if fmt is in our list of supported formats to see if it is supported. */
1553 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1554 if (!pf)
1556 ERR("Invalid pixel format: %d\n", fmt);
1557 goto done;
1560 if (!pf->window)
1562 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1563 goto done;
1566 data->pixel_format = fmt;
1568 TRACE("pixel format:\n");
1569 TRACE(" window: %u\n", (unsigned int)pf->window);
1570 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1571 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1572 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1573 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1574 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1575 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1576 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1577 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1578 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1579 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1580 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1581 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1582 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1583 ret = TRUE;
1585 done:
1586 release_win_data(data);
1587 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) NtUserSetWindowPixelFormat(hwnd, fmt);
1588 return ret;
1592 /**********************************************************************
1593 * mark_contexts_for_moved_view
1595 static void mark_contexts_for_moved_view(macdrv_view view)
1597 struct wgl_context *context;
1599 pthread_mutex_lock(&context_mutex);
1600 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1602 if (context->draw_view == view)
1603 InterlockedExchange(&context->view_moved, TRUE);
1605 pthread_mutex_unlock(&context_mutex);
1609 /**********************************************************************
1610 * sync_context_rect
1612 static BOOL sync_context_rect(struct wgl_context *context)
1614 BOOL ret = FALSE;
1615 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1617 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1619 if (data && data->client_cocoa_view == context->draw_view)
1621 RECT rect = data->client_rect;
1622 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1623 if (!EqualRect(&context->draw_rect, &rect))
1625 context->draw_rect = rect;
1626 ret = TRUE;
1629 release_win_data(data);
1631 return ret;
1635 /**********************************************************************
1636 * make_context_current
1638 static void make_context_current(struct wgl_context *context, BOOL read)
1640 macdrv_view view;
1641 RECT view_rect;
1642 struct wgl_pbuffer *pbuffer;
1644 if (read)
1646 view = context->read_view;
1647 view_rect = context->read_rect;
1648 pbuffer = context->read_pbuffer;
1650 else
1652 sync_context_rect(context);
1654 view = context->draw_view;
1655 view_rect = context->draw_rect;
1656 pbuffer = context->draw_pbuffer;
1659 if (view || !pbuffer)
1660 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1661 else
1663 GLint enabled;
1665 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1666 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1667 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1668 pbuffer->level, 0);
1669 CGLSetCurrentContext(context->cglcontext);
1674 /**********************************************************************
1675 * sync_context
1677 static void sync_context(struct wgl_context *context)
1679 if (sync_context_rect(context))
1680 make_context_current(context, FALSE);
1684 /**********************************************************************
1685 * set_swap_interval
1687 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1689 CGLError err;
1691 /* In theory, for single-buffered contexts, there's no such thing as a swap
1692 so the swap interval shouldn't matter. But OS X will synchronize flushes
1693 of single-buffered contexts if the interval is set to non-zero. */
1694 if (interval && !pixel_formats[context->format - 1].double_buffer)
1695 interval = 0;
1697 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1698 if (err != kCGLNoError)
1699 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1701 return err == kCGLNoError;
1705 /**********************************************************************
1706 * sync_swap_interval
1708 static void sync_swap_interval(struct wgl_context *context)
1710 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1712 int interval;
1714 if (!allow_vsync)
1715 interval = 0;
1716 else if (context->draw_hwnd)
1718 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1719 if (data)
1721 interval = data->swap_interval;
1722 release_win_data(data);
1724 else /* window was destroyed? */
1725 interval = 1;
1727 else /* pbuffer */
1728 interval = 0;
1730 set_swap_interval(context, interval);
1735 /**********************************************************************
1736 * get_iokit_display_property
1738 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1740 GLint accelerated;
1741 GLint display_mask;
1742 int i;
1744 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1746 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1747 return FALSE;
1750 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1752 WARN("failed to get kCGLRPDisplayMask\n");
1753 return FALSE;
1756 for (i = 0; i < sizeof(GLint) * 8; i++)
1758 GLint this_display_mask = (GLint)(1U << i);
1759 if (this_display_mask & display_mask)
1761 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1762 io_service_t service;
1763 CFDataRef data;
1764 uint32_t prop_value;
1766 if (!display_id)
1767 continue;
1768 service = CGDisplayIOServicePort(display_id);
1769 if (!service)
1771 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1772 continue;
1775 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1776 kIORegistryIterateRecursively | kIORegistryIterateParents);
1777 if (!data)
1779 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1780 continue;
1782 if (CFGetTypeID(data) != CFDataGetTypeID())
1784 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1785 CFRelease(data);
1786 continue;
1788 if (CFDataGetLength(data) != sizeof(prop_value))
1790 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1791 (unsigned long long)CFDataGetLength(data));
1792 CFRelease(data);
1793 continue;
1796 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1797 CFRelease(data);
1798 *value = prop_value;
1799 return TRUE;
1803 return FALSE;
1807 /**********************************************************************
1808 * create_pixel_format_for_renderer
1810 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1811 * responsible for releasing the pixel format object.
1813 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1815 GLint renderer_id;
1816 CGLPixelFormatAttribute attrs[] = {
1817 kCGLPFARendererID, 0,
1818 kCGLPFASingleRenderer,
1819 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1822 CGError err;
1823 CGLPixelFormatObj pixel_format;
1824 GLint virtual_screens;
1826 if (core)
1828 attrs[3] = kCGLPFAOpenGLProfile;
1829 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1832 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1833 return NULL;
1835 attrs[1] = renderer_id;
1836 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1837 if (err != kCGLNoError)
1838 pixel_format = NULL;
1839 return pixel_format;
1843 /**********************************************************************
1844 * map_renderer_index
1846 * We can't create pixel formats for all renderers listed. For example,
1847 * in a dual-GPU system, the integrated GPU is typically unavailable
1848 * when the discrete GPU is active.
1850 * This function conceptually creates a list of "good" renderers from the
1851 * list of all renderers. It treats the input "renderer" parameter as an
1852 * index into that list of good renderers and returns the corresponding
1853 * index into the list of all renderers.
1855 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1857 GLint good_count, i;
1859 good_count = 0;
1860 for (i = 0; i < renderer_count; i++)
1862 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1863 if (pix)
1865 CGLReleasePixelFormat(pix);
1866 good_count++;
1867 if (good_count > renderer)
1868 break;
1870 else
1871 TRACE("skipping bad renderer %d\n", i);
1874 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1875 return i;
1879 /**********************************************************************
1880 * get_gl_string
1882 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1884 const char* ret = NULL;
1885 CGLContextObj context, old_context;
1886 CGLError err;
1888 err = CGLCreateContext(pixel_format, NULL, &context);
1889 if (err == kCGLNoError && context)
1891 old_context = CGLGetCurrentContext();
1892 err = CGLSetCurrentContext(context);
1893 if (err == kCGLNoError)
1895 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1896 CGLSetCurrentContext(old_context);
1898 else
1899 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1900 CGLReleaseContext(context);
1902 else
1903 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1905 return ret;
1909 /**********************************************************************
1910 * get_fallback_renderer_version
1912 static void get_fallback_renderer_version(GLuint *value)
1914 BOOL got_it = FALSE;
1915 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1916 kCFURLPOSIXPathStyle, TRUE);
1917 if (url)
1919 CFBundleRef bundle = CFBundleCreate(NULL, url);
1920 CFRelease(url);
1921 if (bundle)
1923 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1924 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1926 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1927 char* buf = malloc(len);
1928 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1930 unsigned int major, minor, bugfix;
1931 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1932 if (count >= 2)
1934 value[0] = major;
1935 value[1] = minor;
1936 if (count == 3)
1937 value[2] = bugfix;
1938 else
1939 value[2] = 0;
1940 got_it = TRUE;
1943 free(buf);
1945 CFRelease(bundle);
1949 if (!got_it)
1951 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1952 earliest version that the Mac driver supports. */
1953 value[0] = 1;
1954 value[1] = 6;
1955 value[2] = 14;
1960 /**********************************************************************
1961 * parse_renderer_version
1963 * Get the renderer version from the OpenGL version string. Assumes
1964 * the string is of the form
1965 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1966 * where major, minor, and bugfix are what we're interested in. This
1967 * form for the vendor specific information is not generally applicable,
1968 * but seems reliable on OS X.
1970 static BOOL parse_renderer_version(const char* version, GLuint *value)
1972 const char* p = strchr(version, ' ');
1973 int count;
1974 unsigned int major, minor, bugfix;
1976 if (p) p = strchr(p + 1, '-');
1977 if (!p) return FALSE;
1979 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
1980 if (count < 2)
1981 return FALSE;
1983 value[0] = major;
1984 value[1] = minor;
1985 if (count == 3)
1986 value[2] = bugfix;
1987 else
1988 value[2] = 0;
1990 return TRUE;
1994 /**********************************************************************
1995 * query_renderer_integer
1997 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
1999 BOOL ret = FALSE;
2000 CGLError err;
2002 if (TRACE_ON(wgl))
2004 GLint renderer_id;
2005 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2006 renderer_id = 0;
2007 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2010 switch (attribute)
2012 case WGL_RENDERER_ACCELERATED_WINE:
2013 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2014 break;
2015 *value = !!*value;
2016 ret = TRUE;
2017 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2018 break;
2020 case WGL_RENDERER_DEVICE_ID_WINE:
2021 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2022 if (!ret)
2024 *value = 0xffffffff;
2025 ret = TRUE;
2027 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2028 break;
2030 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2031 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2033 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2034 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2036 if (pixel_format)
2038 const char* version = get_gl_string(pixel_format, GL_VERSION);
2040 CGLReleasePixelFormat(pixel_format);
2041 if (version)
2043 unsigned int major, minor;
2045 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2047 value[0] = major;
2048 value[1] = minor;
2049 ret = TRUE;
2054 if (!ret)
2056 value[0] = value[1] = 0;
2057 ret = TRUE;
2059 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2060 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2061 break;
2064 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2066 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2068 if (pixel_format)
2070 CGLReleasePixelFormat(pixel_format);
2071 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2072 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2074 else
2076 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2077 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2079 ret = TRUE;
2080 break;
2083 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2084 /* FIXME: no API to query this */
2085 *value = 0;
2086 ret = TRUE;
2087 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2088 break;
2090 case WGL_RENDERER_VENDOR_ID_WINE:
2091 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2092 if (!ret)
2094 *value = 0xffffffff;
2095 ret = TRUE;
2097 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2098 break;
2100 case WGL_RENDERER_VERSION_WINE:
2102 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2104 if (!pixel_format)
2105 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2106 if (pixel_format)
2108 const char* version = get_gl_string(pixel_format, GL_VERSION);
2110 CGLReleasePixelFormat(pixel_format);
2111 if (version)
2112 ret = parse_renderer_version(version, value);
2115 if (!ret)
2117 get_fallback_renderer_version(value);
2118 ret = TRUE;
2120 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2121 break;
2124 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2125 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2126 if (err != kCGLNoError && err != kCGLBadProperty)
2127 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2128 if (err != kCGLNoError)
2130 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2131 *value /= 1024 * 1024;
2132 else
2133 *value = 0;
2135 ret = TRUE;
2136 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2137 break;
2139 default:
2140 FIXME("unrecognized attribute 0x%04x\n", attribute);
2141 break;
2144 return ret;
2148 /**********************************************************************
2149 * macdrv_glCopyColorTable
2151 * Hook into glCopyColorTable as part of the implementation of
2152 * wglMakeContextCurrentARB. If the context has a separate readable,
2153 * temporarily make that current, do glCopyColorTable, and then set it
2154 * back to the drawable. This is modeled after what Mesa GLX's Apple
2155 * implementation does.
2157 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2158 GLsizei width)
2160 struct wgl_context *context = NtCurrentTeb()->glContext;
2162 if (context->read_view || context->read_pbuffer)
2163 make_context_current(context, TRUE);
2165 pglCopyColorTable(target, internalformat, x, y, width);
2167 if (context->read_view || context->read_pbuffer)
2168 make_context_current(context, FALSE);
2172 /**********************************************************************
2173 * macdrv_glCopyPixels
2175 * Hook into glCopyPixels as part of the implementation of
2176 * wglMakeContextCurrentARB. If the context has a separate readable,
2177 * temporarily make that current, do glCopyPixels, and then set it back
2178 * to the drawable. This is modeled after what Mesa GLX's Apple
2179 * implementation does.
2181 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2183 struct wgl_context *context = NtCurrentTeb()->glContext;
2185 if (context->read_view || context->read_pbuffer)
2186 make_context_current(context, TRUE);
2188 pglCopyPixels(x, y, width, height, type);
2190 if (context->read_view || context->read_pbuffer)
2191 make_context_current(context, FALSE);
2195 /**********************************************************************
2196 * macdrv_glFinish
2198 static void macdrv_glFinish(void)
2200 struct wgl_context *context = NtCurrentTeb()->glContext;
2202 sync_swap_interval(context);
2203 sync_context(context);
2204 pglFinish();
2208 /**********************************************************************
2209 * macdrv_glFlush
2211 static void macdrv_glFlush(void)
2213 struct wgl_context *context = NtCurrentTeb()->glContext;
2215 sync_swap_interval(context);
2216 sync_context(context);
2218 if (skip_single_buffer_flushes)
2220 const pixel_format *pf = &pixel_formats[context->format - 1];
2221 DWORD now = NtGetTickCount();
2223 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2224 context->last_flush_time, now);
2225 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2227 TRACE("calling glFlushRenderAPPLE()\n");
2228 pglFlushRenderAPPLE();
2229 return;
2231 else
2233 TRACE("calling glFlush()\n");
2234 context->last_flush_time = now;
2238 pglFlush();
2242 /**********************************************************************
2243 * macdrv_glGetString
2245 * Hook into glGetString in order to return some legacy WGL extensions
2246 * that couldn't be advertised via the standard
2247 * WGL_ARB_extensions_string mechanism. Some programs, especially
2248 * older ones, expect to find certain older extensions, such as
2249 * WGL_EXT_extensions_string itself, in the standard GL extensions
2250 * string, and won't query any other WGL extensions unless they find
2251 * that particular extension there.
2253 static const GLubyte *macdrv_glGetString(GLenum name)
2255 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2256 return (const GLubyte *)gl_info.glExtensions;
2257 else
2258 return pglGetString(name);
2262 /**********************************************************************
2263 * macdrv_glReadPixels
2265 * Hook into glReadPixels as part of the implementation of
2266 * wglMakeContextCurrentARB. If the context has a separate readable,
2267 * temporarily make that current, do glReadPixels, and then set it back
2268 * to the drawable. This is modeled after what Mesa GLX's Apple
2269 * implementation does.
2271 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2272 GLenum format, GLenum type, void *pixels)
2274 struct wgl_context *context = NtCurrentTeb()->glContext;
2276 if (context->read_view || context->read_pbuffer)
2277 make_context_current(context, TRUE);
2279 pglReadPixels(x, y, width, height, format, type, pixels);
2281 if (context->read_view || context->read_pbuffer)
2282 make_context_current(context, FALSE);
2286 /**********************************************************************
2287 * macdrv_glViewport
2289 * Hook into glViewport as an opportunity to update the OpenGL context
2290 * if necessary. This is modeled after what Mesa GLX's Apple
2291 * implementation does.
2293 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2295 struct wgl_context *context = NtCurrentTeb()->glContext;
2297 sync_context(context);
2298 macdrv_update_opengl_context(context->context);
2299 pglViewport(x, y, width, height);
2303 /***********************************************************************
2304 * macdrv_wglBindTexImageARB
2306 * WGL_ARB_render_texture: wglBindTexImageARB
2308 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2310 struct wgl_context *context = NtCurrentTeb()->glContext;
2311 GLenum source;
2312 CGLError err;
2314 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2316 if (pbuffer->no_texture)
2318 SetLastError(ERROR_INVALID_OPERATION);
2319 return GL_FALSE;
2322 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2323 opengl_funcs.gl.p_glFlush();
2325 switch (iBuffer)
2327 case WGL_FRONT_LEFT_ARB:
2328 if (pixel_formats[pbuffer->format - 1].stereo)
2329 source = GL_FRONT_LEFT;
2330 else
2331 source = GL_FRONT;
2332 break;
2333 case WGL_FRONT_RIGHT_ARB:
2334 source = GL_FRONT_RIGHT;
2335 break;
2336 case WGL_BACK_LEFT_ARB:
2337 if (pixel_formats[pbuffer->format - 1].stereo)
2338 source = GL_BACK_LEFT;
2339 else
2340 source = GL_BACK;
2341 break;
2342 case WGL_BACK_RIGHT_ARB:
2343 source = GL_BACK_RIGHT;
2344 break;
2345 case WGL_AUX0_ARB: source = GL_AUX0; break;
2346 case WGL_AUX1_ARB: source = GL_AUX1; break;
2347 case WGL_AUX2_ARB: source = GL_AUX2; break;
2348 case WGL_AUX3_ARB: source = GL_AUX3; break;
2350 case WGL_AUX4_ARB:
2351 case WGL_AUX5_ARB:
2352 case WGL_AUX6_ARB:
2353 case WGL_AUX7_ARB:
2354 case WGL_AUX8_ARB:
2355 case WGL_AUX9_ARB:
2356 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2357 SetLastError(ERROR_INVALID_DATA);
2358 return GL_FALSE;
2360 default:
2361 WARN("unknown source buffer 0x%x\n", iBuffer);
2362 SetLastError(ERROR_INVALID_DATA);
2363 return GL_FALSE;
2366 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2367 if (err != kCGLNoError)
2369 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2370 SetLastError(ERROR_INVALID_OPERATION);
2371 return GL_FALSE;
2374 return GL_TRUE;
2378 /***********************************************************************
2379 * macdrv_wglChoosePixelFormatARB
2381 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2383 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2384 const FLOAT *pfAttribFList, UINT nMaxFormats,
2385 int *piFormats, UINT *nNumFormats)
2387 pixel_format pf, valid;
2388 const int *iptr;
2389 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2390 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2391 int float_color;
2392 BOOL srgb;
2393 int i, found = 0;
2395 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2396 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2397 if (pfAttribFList)
2398 FIXME("unused pfAttribFList\n");
2400 memset(&pf, 0, sizeof(pf));
2401 memset(&valid, 0, sizeof(valid));
2402 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2403 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2404 float_color = -1;
2405 srgb = FALSE;
2407 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2409 int attr = iptr[0];
2410 int value = iptr[1];
2412 TRACE("%s\n", debugstr_attrib(attr, value));
2414 switch (attr)
2416 case WGL_DRAW_TO_WINDOW_ARB:
2417 if (valid.window && (!pf.window != !value)) goto cant_match;
2418 pf.window = (value != 0);
2419 valid.window = 1;
2420 break;
2422 case WGL_DRAW_TO_BITMAP_ARB:
2423 goto cant_match;
2425 case WGL_ACCELERATION_ARB:
2426 if (value == WGL_FULL_ACCELERATION_ARB)
2427 value = 1;
2428 else if (value == WGL_NO_ACCELERATION_ARB)
2429 value = 0;
2430 else
2431 goto cant_match;
2432 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2433 pf.accelerated = value;
2434 valid.accelerated = 1;
2435 break;
2437 case WGL_NEED_PALETTE_ARB:
2438 case WGL_NEED_SYSTEM_PALETTE_ARB:
2439 case WGL_SWAP_LAYER_BUFFERS_ARB:
2440 if (value) goto cant_match;
2441 break;
2443 case WGL_SWAP_METHOD_ARB:
2444 if (value == WGL_SWAP_COPY_ARB)
2445 value = 1;
2446 else if (value == WGL_SWAP_UNDEFINED_ARB)
2447 value = 0;
2448 else
2449 goto cant_match;
2450 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2451 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2452 pf.backing_store = value;
2453 valid.backing_store = 1;
2454 break;
2456 case WGL_NUMBER_OVERLAYS_ARB:
2457 case WGL_NUMBER_UNDERLAYS_ARB:
2458 if (value) goto cant_match;
2459 break;
2461 case WGL_SHARE_DEPTH_ARB:
2462 case WGL_SHARE_STENCIL_ARB:
2463 case WGL_SHARE_ACCUM_ARB:
2464 /* no effect */
2465 break;
2467 case WGL_SUPPORT_GDI_ARB:
2468 if (value) goto cant_match;
2469 break;
2471 case WGL_SUPPORT_OPENGL_ARB:
2472 if (!value) goto cant_match;
2473 break;
2475 case WGL_DOUBLE_BUFFER_ARB:
2476 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2477 pf.double_buffer = (value != 0);
2478 valid.double_buffer = 1;
2479 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2480 break;
2482 case WGL_STEREO_ARB:
2483 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2484 pf.stereo = (value != 0);
2485 valid.stereo = 1;
2486 break;
2488 case WGL_PIXEL_TYPE_ARB:
2489 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2490 value = 1;
2491 else if (value == WGL_TYPE_RGBA_ARB)
2492 value = 0;
2493 else
2495 /* Mac contexts don't support rendering to unsigned floating
2496 point formats, even if GL_EXT_packed_float is supported.
2497 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2498 goto cant_match;
2500 if (float_color != -1 && float_color != value) goto cant_match;
2501 if (srgb && value) goto cant_match;
2502 float_color = value;
2503 break;
2505 case WGL_COLOR_BITS_ARB:
2506 if (color_bits < value) color_bits = value;
2507 break;
2509 case WGL_RED_BITS_ARB:
2510 if (srgb && value > 8) goto cant_match;
2511 if (red_bits < value) red_bits = value;
2512 break;
2514 case WGL_GREEN_BITS_ARB:
2515 if (srgb && value > 8) goto cant_match;
2516 if (green_bits < value) green_bits = value;
2517 break;
2519 case WGL_BLUE_BITS_ARB:
2520 if (srgb && value > 8) goto cant_match;
2521 if (blue_bits < value) blue_bits = value;
2522 break;
2524 case WGL_ALPHA_BITS_ARB:
2525 if (alpha_bits < value) alpha_bits = value;
2526 break;
2528 case WGL_ACCUM_BITS_ARB:
2529 if (accum_bits < value) accum_bits = value;
2530 break;
2532 case WGL_ACCUM_RED_BITS_ARB:
2533 if (accum_red_bits < value) accum_red_bits = value;
2534 break;
2536 case WGL_ACCUM_GREEN_BITS_ARB:
2537 if (accum_green_bits < value) accum_green_bits = value;
2538 break;
2540 case WGL_ACCUM_BLUE_BITS_ARB:
2541 if (accum_blue_bits < value) accum_blue_bits = value;
2542 break;
2544 case WGL_ACCUM_ALPHA_BITS_ARB:
2545 if (accum_alpha_bits < value) accum_alpha_bits = value;
2546 break;
2548 case WGL_DEPTH_BITS_ARB:
2549 if (value > 255) goto cant_match;
2550 if (pf.depth_bits < value) pf.depth_bits = value;
2551 break;
2553 case WGL_STENCIL_BITS_ARB:
2554 if (value > 255) goto cant_match;
2555 if (pf.stencil_bits < value) pf.stencil_bits = value;
2556 break;
2558 case WGL_AUX_BUFFERS_ARB:
2559 if (value > 7) goto cant_match;
2560 if (pf.aux_buffers < value) pf.aux_buffers = value;
2561 break;
2563 case WGL_SAMPLE_BUFFERS_ARB:
2564 if (value > 1) goto cant_match;
2565 if (pf.sample_buffers < value) pf.sample_buffers = value;
2566 break;
2568 case WGL_SAMPLES_ARB:
2569 if (value > 31) goto cant_match;
2570 if (pf.samples < value) pf.samples = value;
2571 break;
2573 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2574 /* sRGB is only supported for 8-bit integer color components */
2575 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2576 goto cant_match;
2577 srgb = TRUE;
2578 break;
2580 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2581 case WGL_RED_SHIFT_ARB:
2582 case WGL_GREEN_SHIFT_ARB:
2583 case WGL_BLUE_SHIFT_ARB:
2584 case WGL_ALPHA_SHIFT_ARB:
2585 case WGL_TRANSPARENT_ARB:
2586 case WGL_TRANSPARENT_RED_VALUE_ARB:
2587 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2588 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2589 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2590 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2591 /* ignored */
2592 break;
2594 case WGL_DRAW_TO_PBUFFER_ARB:
2595 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2596 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2597 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2598 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2599 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2600 pf.pbuffer = (value != 0);
2601 valid.pbuffer = 1;
2602 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2603 !alpha_bits)
2604 alpha_bits = 1;
2605 break;
2607 default:
2608 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2609 return GL_FALSE;
2613 TRACE("required: w/p/a %s/%s/%s col/r/g/b/a %d%s/%d/%d/%d/%d srgb %d ac %d/%d/%d/%d/%d dp/stn/ax/b/db/str %u/%u/%u/%s/%s/%s samp %u/%u\n",
2614 valid.window ? (pf.window ? "1" : "0") : "?",
2615 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2616 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2617 color_bits,
2618 float_color == -1 ? "?" : float_color ? "f" : "",
2619 red_bits,
2620 green_bits,
2621 blue_bits,
2622 alpha_bits,
2623 (int)srgb,
2624 accum_bits,
2625 accum_red_bits,
2626 accum_green_bits,
2627 accum_blue_bits,
2628 accum_alpha_bits,
2629 pf.depth_bits,
2630 pf.stencil_bits,
2631 pf.aux_buffers,
2632 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2633 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2634 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2635 pf.sample_buffers,
2636 pf.samples);
2638 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2640 const struct color_mode *mode;
2642 if (valid.window && pixel_formats[i].window != pf.window) continue;
2643 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2644 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2645 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2646 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2647 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2649 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2650 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2651 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2652 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2653 if (pixel_formats[i].samples < pf.samples) continue;
2655 mode = &color_modes[pixel_formats[i].color_mode];
2656 /* If the mode doesn't have alpha, check requested color bits against
2657 bits per pixel instead of the mode's color bits. On Windows, color
2658 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2659 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2660 expects that to match such a pixel format, we need to accommodate that. */
2661 if (mode->alpha_bits)
2663 if (mode->color_bits < color_bits)
2664 continue;
2666 else
2668 if (mode->bits_per_pixel < color_bits)
2669 continue;
2671 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2672 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2673 continue;
2674 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2675 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2676 continue;
2678 if (pixel_formats[i].accum_mode)
2680 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2681 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2682 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2683 mode->alpha_bits < accum_alpha_bits)
2684 continue;
2686 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2687 continue;
2689 piFormats[found++] = i + 1;
2690 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2693 cant_match:
2694 *nNumFormats = found;
2696 return TRUE;
2700 /***********************************************************************
2701 * macdrv_wglCreateContextAttribsARB
2703 * WGL_ARB_create_context: wglCreateContextAttribsARB
2705 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2706 struct wgl_context *share_context,
2707 const int *attrib_list)
2709 int format;
2710 struct wgl_context *context;
2711 const int *iptr;
2712 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2713 BOOL core = FALSE;
2714 GLint renderer_id = 0;
2716 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2718 format = get_dc_pixel_format(hdc);
2720 if (!is_valid_pixel_format(format))
2722 ERR("Invalid pixel format %d, expect problems!\n", format);
2723 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2724 return NULL;
2727 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2729 int attr = iptr[0];
2730 int value = iptr[1];
2732 TRACE("%s\n", debugstr_attrib(attr, value));
2734 switch (attr)
2736 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2737 major = value;
2738 break;
2740 case WGL_CONTEXT_MINOR_VERSION_ARB:
2741 minor = value;
2742 break;
2744 case WGL_CONTEXT_LAYER_PLANE_ARB:
2745 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2746 break;
2748 case WGL_CONTEXT_FLAGS_ARB:
2749 flags = value;
2750 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2751 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2752 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2753 break;
2755 case WGL_CONTEXT_PROFILE_MASK_ARB:
2756 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2757 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2759 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2760 SetLastError(ERROR_INVALID_PROFILE_ARB);
2761 return NULL;
2763 profile = value;
2764 break;
2766 case WGL_RENDERER_ID_WINE:
2768 CGLError err;
2769 CGLRendererInfoObj renderer_info;
2770 GLint renderer_count, temp;
2772 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2773 if (err != kCGLNoError)
2775 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2776 SetLastError(ERROR_GEN_FAILURE);
2777 return NULL;
2780 value = map_renderer_index(renderer_info, renderer_count, value);
2782 if (value >= renderer_count)
2784 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2785 CGLDestroyRendererInfo(renderer_info);
2786 SetLastError(ERROR_INVALID_PARAMETER);
2787 return NULL;
2790 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2792 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2793 CGLDestroyRendererInfo(renderer_info);
2794 SetLastError(ERROR_GEN_FAILURE);
2795 return NULL;
2798 CGLDestroyRendererInfo(renderer_info);
2800 if (renderer_id && temp != renderer_id)
2802 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2803 SetLastError(ERROR_INVALID_PARAMETER);
2804 return NULL;
2806 renderer_id = temp;
2807 break;
2810 default:
2811 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2812 SetLastError(ERROR_INVALID_PARAMETER);
2813 return NULL;
2817 if ((major == 3 && (minor == 2 || minor == 3)) ||
2818 (major == 4 && (minor == 0 || minor == 1)))
2820 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2822 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2823 SetLastError(ERROR_INVALID_VERSION_ARB);
2824 return NULL;
2826 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2828 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2829 SetLastError(ERROR_INVALID_PROFILE_ARB);
2830 return NULL;
2832 if (major > gl_info.max_major ||
2833 (major == gl_info.max_major && minor > gl_info.max_minor))
2835 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2836 major, minor);
2837 SetLastError(ERROR_INVALID_PROFILE_ARB);
2838 return NULL;
2840 core = TRUE;
2842 else if (major >= 3)
2844 WARN("Profile version %u.%u not supported\n", major, minor);
2845 SetLastError(ERROR_INVALID_VERSION_ARB);
2846 return NULL;
2848 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2849 (major == 2 && (minor < 0 || minor > 1)))
2851 WARN("Invalid GL version requested\n");
2852 SetLastError(ERROR_INVALID_VERSION_ARB);
2853 return NULL;
2855 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2857 WARN("Forward compatible context requested for GL version < 3\n");
2858 SetLastError(ERROR_INVALID_VERSION_ARB);
2859 return NULL;
2862 if (!(context = calloc(1, sizeof(*context)))) return NULL;
2864 context->format = format;
2865 context->renderer_id = renderer_id;
2866 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2868 free(context);
2869 return NULL;
2872 pthread_mutex_lock(&context_mutex);
2873 list_add_tail(&context_list, &context->entry);
2874 pthread_mutex_unlock(&context_mutex);
2876 return context;
2880 /**********************************************************************
2881 * macdrv_wglCreatePbufferARB
2883 * WGL_ARB_pbuffer: wglCreatePbufferARB
2885 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2886 const int *piAttribList)
2888 struct wgl_pbuffer* pbuffer;
2889 GLenum target = 0;
2890 GLenum internalFormat = 0;
2891 CGLError err;
2893 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2894 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2896 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2898 WARN("invalid pixel format %d\n", iPixelFormat);
2899 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2900 return NULL;
2903 pbuffer = calloc(1, sizeof(*pbuffer));
2904 pbuffer->format = iPixelFormat;
2906 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2908 int attr = piAttribList[0];
2909 int value = piAttribList[1];
2911 switch (attr)
2913 case WGL_PBUFFER_LARGEST_ARB:
2914 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2915 break;
2917 case WGL_TEXTURE_FORMAT_ARB:
2918 switch (value)
2920 case WGL_TEXTURE_RGBA_ARB:
2921 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2922 internalFormat = GL_RGBA;
2923 break;
2924 case WGL_TEXTURE_RGB_ARB:
2925 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2926 internalFormat = GL_RGB;
2927 break;
2928 case WGL_NO_TEXTURE_ARB:
2929 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2930 internalFormat = 0;
2931 break;
2932 default:
2933 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2934 SetLastError(ERROR_INVALID_DATA);
2935 goto done;
2937 break;
2939 case WGL_TEXTURE_TARGET_ARB:
2940 pbuffer->face = 0;
2941 switch (value)
2943 case WGL_NO_TEXTURE_ARB:
2944 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2945 target = 0;
2946 break;
2947 case WGL_TEXTURE_CUBE_MAP_ARB:
2948 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2949 target = GL_TEXTURE_CUBE_MAP;
2950 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2951 break;
2952 case WGL_TEXTURE_1D_ARB:
2953 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2954 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2955 goto done;
2956 case WGL_TEXTURE_2D_ARB:
2957 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2958 target = GL_TEXTURE_2D;
2959 break;
2960 case WGL_TEXTURE_RECTANGLE_NV:
2961 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2962 target = GL_TEXTURE_RECTANGLE;
2963 break;
2964 default:
2965 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2966 SetLastError(ERROR_INVALID_DATA);
2967 goto done;
2969 break;
2971 case WGL_MIPMAP_TEXTURE_ARB:
2972 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2973 pbuffer->max_level = 0;
2974 if (value)
2976 int size = min(iWidth, iHeight) / 2;
2977 while (size)
2979 pbuffer->max_level++;
2980 size /= 2;
2983 break;
2985 default:
2986 WARN("unknown attribute 0x%x\n", attr);
2987 SetLastError(ERROR_INVALID_DATA);
2988 goto done;
2992 if (!target || !internalFormat)
2994 pbuffer->no_texture = TRUE;
2995 /* no actual way to turn off ability to texture; use most permissive target */
2996 target = GL_TEXTURE_RECTANGLE;
2997 internalFormat = GL_RGB;
3000 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3001 if (err != kCGLNoError)
3003 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3004 pbuffer->pbuffer = NULL;
3005 if (err == kCGLBadAlloc)
3006 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3007 else
3008 SetLastError(ERROR_INVALID_DATA);
3011 done:
3012 if (!pbuffer->pbuffer)
3014 free(pbuffer);
3015 return NULL;
3018 TRACE(" -> %p\n", pbuffer);
3019 return pbuffer;
3023 /**********************************************************************
3024 * macdrv_wglDestroyPbufferARB
3026 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3028 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3030 TRACE("pbuffer %p\n", pbuffer);
3031 if (pbuffer && pbuffer->pbuffer)
3032 CGLReleasePBuffer(pbuffer->pbuffer);
3033 free(pbuffer);
3034 return GL_TRUE;
3038 /**********************************************************************
3039 * macdrv_wglGetExtensionsStringARB
3041 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3043 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3045 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3046 this can be specific to the CGL renderer like we're supposed to do. */
3047 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3048 return gl_info.wglExtensions;
3052 /**********************************************************************
3053 * macdrv_wglGetExtensionsStringEXT
3055 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3057 static const char *macdrv_wglGetExtensionsStringEXT(void)
3059 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3060 return gl_info.wglExtensions;
3064 /**********************************************************************
3065 * macdrv_wglGetPbufferDCARB
3067 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3069 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3071 HDC hdc;
3072 struct wgl_pbuffer *prev;
3074 hdc = NtGdiOpenDCW(NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL);
3075 if (!hdc) return 0;
3077 pthread_mutex_lock(&dc_pbuffers_mutex);
3078 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3079 if (prev)
3081 CGLReleasePBuffer(prev->pbuffer);
3082 free(prev);
3084 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3085 pthread_mutex_unlock(&dc_pbuffers_mutex);
3087 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3088 return hdc;
3092 /**********************************************************************
3093 * macdrv_wglGetPixelFormatAttribivARB
3095 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3097 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3098 UINT nAttributes, const int *piAttributes, int *piValues)
3100 const pixel_format *pf;
3101 UINT i;
3103 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3104 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3106 if (!nAttributes) return GL_TRUE;
3108 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3110 piValues[0] = nb_formats;
3111 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3112 return GL_TRUE;
3115 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3116 if (!pf)
3118 WARN("invalid pixel format %d\n", iPixelFormat);
3119 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3120 return GL_FALSE;
3123 for (i = 0; i < nAttributes; ++i)
3125 switch (piAttributes[i])
3127 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3128 piValues[i] = nb_formats;
3129 break;
3131 case WGL_DRAW_TO_WINDOW_ARB:
3132 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3133 break;
3135 case WGL_DRAW_TO_BITMAP_ARB:
3136 piValues[i] = GL_FALSE;
3137 break;
3139 case WGL_ACCELERATION_ARB:
3140 if (iLayerPlane) goto invalid_layer;
3141 if (pf->accelerated)
3142 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3143 else
3144 piValues[i] = WGL_NO_ACCELERATION_ARB;
3145 break;
3147 case WGL_NEED_PALETTE_ARB:
3148 case WGL_NEED_SYSTEM_PALETTE_ARB:
3149 case WGL_SWAP_LAYER_BUFFERS_ARB:
3150 piValues[i] = GL_FALSE;
3151 break;
3153 case WGL_SWAP_METHOD_ARB:
3154 if (pf->double_buffer && pf->backing_store)
3155 piValues[i] = WGL_SWAP_COPY_ARB;
3156 else
3157 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3158 break;
3160 case WGL_NUMBER_OVERLAYS_ARB:
3161 case WGL_NUMBER_UNDERLAYS_ARB:
3162 piValues[i] = 0;
3163 break;
3165 case WGL_TRANSPARENT_ARB:
3166 if (iLayerPlane) goto invalid_layer;
3167 piValues[i] = GL_FALSE;
3168 break;
3170 case WGL_TRANSPARENT_RED_VALUE_ARB:
3171 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3172 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3173 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3174 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3175 if (iLayerPlane) goto invalid_layer;
3176 piValues[i] = 0;
3177 break;
3179 case WGL_SHARE_DEPTH_ARB:
3180 case WGL_SHARE_STENCIL_ARB:
3181 case WGL_SHARE_ACCUM_ARB:
3182 if (iLayerPlane) goto invalid_layer;
3183 piValues[i] = GL_TRUE;
3184 break;
3186 case WGL_SUPPORT_GDI_ARB:
3187 if (iLayerPlane) goto invalid_layer;
3188 piValues[i] = GL_FALSE;
3189 break;
3191 case WGL_SUPPORT_OPENGL_ARB:
3192 if (iLayerPlane) goto invalid_layer;
3193 piValues[i] = GL_TRUE;
3194 break;
3196 case WGL_DOUBLE_BUFFER_ARB:
3197 if (iLayerPlane) goto invalid_layer;
3198 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3199 break;
3201 case WGL_STEREO_ARB:
3202 if (iLayerPlane) goto invalid_layer;
3203 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3204 break;
3206 case WGL_PIXEL_TYPE_ARB:
3207 if (iLayerPlane) goto invalid_layer;
3208 if (color_modes[pf->color_mode].is_float)
3209 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3210 else
3211 piValues[i] = WGL_TYPE_RGBA_ARB;
3212 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3213 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3214 However, Mac contexts don't support rendering to unsigned floating-point
3215 formats, even when GL_EXT_packed_float is supported. */
3216 break;
3218 case WGL_COLOR_BITS_ARB:
3219 if (iLayerPlane) goto invalid_layer;
3220 /* If the mode doesn't have alpha, return bits per pixel instead
3221 of color bits. On Windows, color bits sometimes exceeds r+g+b
3222 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3223 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3224 pixel format, we need to accommodate that. */
3225 if (color_modes[pf->color_mode].alpha_bits)
3226 piValues[i] = color_modes[pf->color_mode].color_bits;
3227 else
3228 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3229 break;
3231 case WGL_RED_BITS_ARB:
3232 if (iLayerPlane) goto invalid_layer;
3233 piValues[i] = color_modes[pf->color_mode].red_bits;
3234 break;
3236 case WGL_RED_SHIFT_ARB:
3237 if (iLayerPlane) goto invalid_layer;
3238 piValues[i] = color_modes[pf->color_mode].red_shift;
3239 break;
3241 case WGL_GREEN_BITS_ARB:
3242 if (iLayerPlane) goto invalid_layer;
3243 piValues[i] = color_modes[pf->color_mode].green_bits;
3244 break;
3246 case WGL_GREEN_SHIFT_ARB:
3247 if (iLayerPlane) goto invalid_layer;
3248 piValues[i] = color_modes[pf->color_mode].green_shift;
3249 break;
3251 case WGL_BLUE_BITS_ARB:
3252 if (iLayerPlane) goto invalid_layer;
3253 piValues[i] = color_modes[pf->color_mode].blue_bits;
3254 break;
3256 case WGL_BLUE_SHIFT_ARB:
3257 if (iLayerPlane) goto invalid_layer;
3258 piValues[i] = color_modes[pf->color_mode].blue_shift;
3259 break;
3261 case WGL_ALPHA_BITS_ARB:
3262 if (iLayerPlane) goto invalid_layer;
3263 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3264 break;
3266 case WGL_ALPHA_SHIFT_ARB:
3267 if (iLayerPlane) goto invalid_layer;
3268 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3269 break;
3271 case WGL_ACCUM_BITS_ARB:
3272 if (iLayerPlane) goto invalid_layer;
3273 if (pf->accum_mode)
3274 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3275 else
3276 piValues[i] = 0;
3277 break;
3279 case WGL_ACCUM_RED_BITS_ARB:
3280 if (iLayerPlane) goto invalid_layer;
3281 if (pf->accum_mode)
3282 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3283 else
3284 piValues[i] = 0;
3285 break;
3287 case WGL_ACCUM_GREEN_BITS_ARB:
3288 if (iLayerPlane) goto invalid_layer;
3289 if (pf->accum_mode)
3290 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3291 else
3292 piValues[i] = 0;
3293 break;
3295 case WGL_ACCUM_BLUE_BITS_ARB:
3296 if (iLayerPlane) goto invalid_layer;
3297 if (pf->accum_mode)
3298 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3299 else
3300 piValues[i] = 0;
3301 break;
3303 case WGL_ACCUM_ALPHA_BITS_ARB:
3304 if (iLayerPlane) goto invalid_layer;
3305 if (pf->accum_mode)
3306 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3307 else
3308 piValues[i] = 0;
3309 break;
3311 case WGL_DEPTH_BITS_ARB:
3312 if (iLayerPlane) goto invalid_layer;
3313 piValues[i] = pf->depth_bits;
3314 break;
3316 case WGL_STENCIL_BITS_ARB:
3317 if (iLayerPlane) goto invalid_layer;
3318 piValues[i] = pf->stencil_bits;
3319 break;
3321 case WGL_AUX_BUFFERS_ARB:
3322 if (iLayerPlane) goto invalid_layer;
3323 piValues[i] = pf->aux_buffers;
3324 break;
3326 case WGL_SAMPLE_BUFFERS_ARB:
3327 if (iLayerPlane) goto invalid_layer;
3328 piValues[i] = pf->sample_buffers;
3329 break;
3331 case WGL_SAMPLES_ARB:
3332 if (iLayerPlane) goto invalid_layer;
3333 piValues[i] = pf->samples;
3334 break;
3336 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3337 if (iLayerPlane) goto invalid_layer;
3338 /* sRGB is only supported for 8-bit integer color components */
3339 if (color_modes[pf->color_mode].red_bits == 8 &&
3340 color_modes[pf->color_mode].green_bits == 8 &&
3341 color_modes[pf->color_mode].blue_bits == 8 &&
3342 !color_modes[pf->color_mode].is_float)
3343 piValues[i] = GL_TRUE;
3344 else
3345 piValues[i] = GL_FALSE;
3346 break;
3348 case WGL_DRAW_TO_PBUFFER_ARB:
3349 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3350 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3351 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3352 break;
3354 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3355 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3356 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3357 break;
3359 case WGL_MAX_PBUFFER_WIDTH_ARB:
3360 piValues[i] = gl_info.max_viewport_dims[0];
3361 break;
3363 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3364 piValues[i] = gl_info.max_viewport_dims[1];
3365 break;
3367 case WGL_MAX_PBUFFER_PIXELS_ARB:
3368 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3369 break;
3371 default:
3372 WARN("invalid attribute %x\n", piAttributes[i]);
3373 return GL_FALSE;
3376 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3379 return GL_TRUE;
3381 invalid_layer:
3382 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3383 return GL_FALSE;
3387 /**********************************************************************
3388 * macdrv_wglGetPixelFormatAttribfvARB
3390 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3392 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3393 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3395 int *attr;
3396 int ret;
3398 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3399 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3401 /* Allocate a temporary array to store integer values */
3402 attr = malloc(nAttributes * sizeof(int));
3403 if (!attr)
3405 ERR("couldn't allocate %d array\n", nAttributes);
3406 return GL_FALSE;
3409 /* Piggy-back on wglGetPixelFormatAttribivARB */
3410 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3411 if (ret)
3413 UINT i;
3415 /* Convert integer values to float. Should also check for attributes
3416 that can give decimal values here */
3417 for (i = 0; i < nAttributes; i++)
3418 pfValues[i] = attr[i];
3421 free(attr);
3422 return ret;
3426 /**********************************************************************
3427 * macdrv_wglGetSwapIntervalEXT
3429 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3431 static int macdrv_wglGetSwapIntervalEXT(void)
3433 struct wgl_context *context = NtCurrentTeb()->glContext;
3434 struct macdrv_win_data *data;
3435 long value;
3436 CGLError err;
3438 TRACE("\n");
3440 if ((data = get_win_data(context->draw_hwnd)))
3442 value = data->swap_interval;
3443 release_win_data(data);
3445 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3446 set_swap_interval(context, allow_vsync ? value : 0);
3448 else
3450 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3451 if (err != kCGLNoError)
3453 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3454 err, CGLErrorString(err));
3455 value = 1;
3459 return value;
3463 /***********************************************************************
3464 * macdrv_wglMakeContextCurrentARB
3466 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3468 * This is not supported directly by OpenGL on the Mac. We emulate it
3469 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3470 * temporarily swap the drawable. This follows the technique used in
3471 * the implementation of Mesa GLX for Apple.
3473 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3475 struct macdrv_win_data *data;
3476 HWND hwnd;
3478 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3479 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3481 if (!context)
3483 macdrv_make_context_current(NULL, NULL, CGRectNull);
3484 NtCurrentTeb()->glContext = NULL;
3485 return TRUE;
3488 if ((hwnd = NtUserWindowFromDC(draw_hdc)))
3490 if (!(data = get_win_data(hwnd)))
3492 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3493 return FALSE;
3496 if (!data->pixel_format)
3498 WARN("no pixel format set\n");
3499 release_win_data(data);
3500 SetLastError(ERROR_INVALID_HANDLE);
3501 return FALSE;
3503 if (context->format != data->pixel_format)
3505 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3506 release_win_data(data);
3507 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3508 return FALSE;
3511 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd)
3512 set_swap_interval(context, allow_vsync ? data->swap_interval : 0);
3514 context->draw_hwnd = hwnd;
3515 context->draw_view = data->client_cocoa_view;
3516 context->draw_rect = data->client_rect;
3517 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3518 context->draw_pbuffer = NULL;
3519 release_win_data(data);
3521 else
3523 struct wgl_pbuffer *pbuffer;
3525 pthread_mutex_lock(&dc_pbuffers_mutex);
3526 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3527 if (pbuffer)
3529 if (context->format != pbuffer->format)
3531 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3532 pthread_mutex_unlock(&dc_pbuffers_mutex);
3533 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3534 return FALSE;
3537 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer)
3538 set_swap_interval(context, 0);
3540 else
3542 WARN("no window or pbuffer for DC\n");
3543 pthread_mutex_unlock(&dc_pbuffers_mutex);
3544 SetLastError(ERROR_INVALID_HANDLE);
3545 return FALSE;
3548 context->draw_hwnd = NULL;
3549 context->draw_view = NULL;
3550 context->draw_pbuffer = pbuffer;
3551 pthread_mutex_unlock(&dc_pbuffers_mutex);
3554 context->read_view = NULL;
3555 context->read_pbuffer = NULL;
3556 if (read_hdc && read_hdc != draw_hdc)
3558 if ((hwnd = NtUserWindowFromDC(read_hdc)))
3560 if ((data = get_win_data(hwnd)))
3562 if (data->client_cocoa_view != context->draw_view)
3564 context->read_view = data->client_cocoa_view;
3565 context->read_rect = data->client_rect;
3566 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3568 release_win_data(data);
3571 else
3573 pthread_mutex_lock(&dc_pbuffers_mutex);
3574 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3575 pthread_mutex_unlock(&dc_pbuffers_mutex);
3579 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3580 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3581 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3583 make_context_current(context, FALSE);
3584 context->has_been_current = TRUE;
3585 NtCurrentTeb()->glContext = context;
3587 return TRUE;
3591 /**********************************************************************
3592 * macdrv_wglQueryCurrentRendererIntegerWINE
3594 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3596 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3598 BOOL ret = FALSE;
3599 struct wgl_context *context = NtCurrentTeb()->glContext;
3600 CGLPixelFormatObj pixel_format;
3601 CGLError err;
3602 GLint virtual_screen;
3603 GLint display_mask;
3604 GLint pf_renderer_id;
3605 CGLRendererInfoObj renderer_info;
3606 GLint renderer_count;
3607 GLint renderer;
3609 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3610 (context ? context->cglcontext : NULL), attribute, value);
3612 if (attribute == WGL_RENDERER_VERSION_WINE)
3614 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3615 get_fallback_renderer_version(value);
3616 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3617 return TRUE;
3620 pixel_format = CGLGetPixelFormat(context->cglcontext);
3621 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3622 if (err != kCGLNoError)
3624 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3625 return FALSE;
3628 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3629 if (err != kCGLNoError)
3631 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3632 return FALSE;
3635 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3636 if (err != kCGLNoError)
3638 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3639 return FALSE;
3642 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3643 if (err != kCGLNoError)
3645 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3646 return FALSE;
3649 for (renderer = 0; renderer < renderer_count; renderer++)
3651 GLint renderer_id;
3653 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3654 continue;
3656 if (renderer_id == pf_renderer_id)
3658 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3659 break;
3663 if (renderer >= renderer_count)
3664 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3666 CGLDestroyRendererInfo(renderer_info);
3667 return ret;
3671 /**********************************************************************
3672 * macdrv_wglQueryCurrentRendererStringWINE
3674 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3676 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3678 const char* ret = NULL;
3679 struct wgl_context *context = NtCurrentTeb()->glContext;
3681 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3682 (context ? context->cglcontext : NULL), attribute);
3684 switch (attribute)
3686 case WGL_RENDERER_DEVICE_ID_WINE:
3688 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3689 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3690 break;
3693 case WGL_RENDERER_VENDOR_ID_WINE:
3695 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3696 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3697 break;
3700 default:
3701 FIXME("unrecognized attribute 0x%04x\n", attribute);
3702 break;
3705 return ret;
3709 /**********************************************************************
3710 * macdrv_wglQueryPbufferARB
3712 * WGL_ARB_pbuffer: wglQueryPbufferARB
3714 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3716 CGLError err;
3717 GLsizei width;
3718 GLsizei height;
3719 GLenum target;
3720 GLenum internalFormat;
3721 GLint mipmap;
3723 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3725 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3726 if (err != kCGLNoError)
3728 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3729 SetLastError(ERROR_INVALID_HANDLE);
3730 return GL_FALSE;
3733 switch (iAttribute)
3735 case WGL_PBUFFER_WIDTH_ARB:
3736 *piValue = width;
3737 break;
3738 case WGL_PBUFFER_HEIGHT_ARB:
3739 *piValue = height;
3740 break;
3741 case WGL_PBUFFER_LOST_ARB:
3742 /* Mac PBuffers can't be lost */
3743 *piValue = GL_FALSE;
3744 break;
3745 case WGL_TEXTURE_FORMAT_ARB:
3746 if (pbuffer->no_texture)
3747 *piValue = WGL_NO_TEXTURE_ARB;
3748 else switch (internalFormat)
3750 case GL_RGBA:
3751 *piValue = WGL_TEXTURE_RGBA_ARB;
3752 break;
3753 case GL_RGB:
3754 default:
3755 *piValue = WGL_TEXTURE_RGB_ARB;
3756 break;
3758 break;
3759 case WGL_TEXTURE_TARGET_ARB:
3760 if (pbuffer->no_texture)
3761 *piValue = WGL_NO_TEXTURE_ARB;
3762 else switch (target)
3764 case GL_TEXTURE_CUBE_MAP:
3765 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3766 break;
3767 case GL_TEXTURE_2D:
3768 *piValue = WGL_TEXTURE_2D_ARB;
3769 break;
3770 case GL_TEXTURE_RECTANGLE:
3771 default:
3772 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3773 break;
3775 break;
3776 case WGL_MIPMAP_TEXTURE_ARB:
3777 *piValue = (pbuffer->max_level > 0);
3778 break;
3779 case WGL_MIPMAP_LEVEL_ARB:
3780 *piValue = pbuffer->level;
3781 break;
3782 case WGL_CUBE_MAP_FACE_ARB:
3783 switch (pbuffer->face)
3785 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3786 default:
3787 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3788 break;
3789 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3790 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3791 break;
3792 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3793 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3794 break;
3795 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3796 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3797 break;
3798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3799 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3800 break;
3801 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3802 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3803 break;
3805 break;
3806 default:
3807 WARN("invalid attribute 0x%x\n", iAttribute);
3808 SetLastError(ERROR_INVALID_DATA);
3809 return GL_FALSE;
3812 return GL_TRUE;
3816 /**********************************************************************
3817 * macdrv_wglQueryRendererIntegerWINE
3819 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3821 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3823 BOOL ret = FALSE;
3824 CGLRendererInfoObj renderer_info;
3825 GLint renderer_count;
3826 CGLError err;
3828 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3830 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3831 if (err != kCGLNoError)
3833 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3834 return FALSE;
3837 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3839 if (renderer < renderer_count)
3840 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3841 else
3842 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3844 CGLDestroyRendererInfo(renderer_info);
3845 return ret;
3849 /**********************************************************************
3850 * macdrv_wglQueryRendererStringWINE
3852 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3854 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3856 const char* ret = NULL;
3857 CGLRendererInfoObj renderer_info;
3858 GLint renderer_count;
3859 CGLError err;
3861 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3863 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3864 if (err != kCGLNoError)
3866 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3867 return FALSE;
3870 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3872 if (renderer >= renderer_count)
3874 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3875 goto done;
3878 switch (attribute)
3880 case WGL_RENDERER_DEVICE_ID_WINE:
3881 case WGL_RENDERER_VENDOR_ID_WINE:
3883 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3884 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3886 if (!pixel_format)
3887 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3888 if (pixel_format)
3890 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3891 CGLReleasePixelFormat(pixel_format);
3894 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3895 break;
3898 default:
3899 FIXME("unrecognized attribute 0x%04x\n", attribute);
3900 break;
3903 done:
3904 CGLDestroyRendererInfo(renderer_info);
3905 return ret;
3909 /**********************************************************************
3910 * macdrv_wglReleasePbufferDCARB
3912 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3914 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3916 struct wgl_pbuffer *prev;
3918 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3920 pthread_mutex_lock(&dc_pbuffers_mutex);
3922 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3923 if (prev)
3925 if (prev != pbuffer)
3926 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3927 CGLReleasePBuffer(prev->pbuffer);
3928 free(prev);
3929 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3931 else hdc = 0;
3933 pthread_mutex_unlock(&dc_pbuffers_mutex);
3935 return hdc && NtGdiDeleteObjectApp(hdc);
3939 /**********************************************************************
3940 * macdrv_wglReleaseTexImageARB
3942 * WGL_ARB_render_texture: wglReleaseTexImageARB
3944 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3946 struct wgl_context *context = NtCurrentTeb()->glContext;
3947 CGLError err;
3949 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3951 if (pbuffer->no_texture)
3953 SetLastError(ERROR_INVALID_OPERATION);
3954 return GL_FALSE;
3957 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3958 if (err != kCGLNoError)
3960 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3961 SetLastError(ERROR_INVALID_OPERATION);
3962 return GL_FALSE;
3965 return GL_TRUE;
3969 /**********************************************************************
3970 * macdrv_wglSetPbufferAttribARB
3972 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3974 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3976 struct wgl_context *context = NtCurrentTeb()->glContext;
3978 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3980 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3982 int attr = piAttribList[0];
3983 int value = piAttribList[1];
3984 switch (attr)
3986 case WGL_MIPMAP_LEVEL_ARB:
3987 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3988 pbuffer->level = value;
3989 break;
3990 case WGL_CUBE_MAP_FACE_ARB:
3991 switch (value)
3993 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3994 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3995 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3996 break;
3997 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3998 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3999 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4000 break;
4001 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4002 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4003 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4004 break;
4005 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4006 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4007 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4008 break;
4009 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4010 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4011 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4012 break;
4013 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4014 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4015 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4016 break;
4017 default:
4018 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4019 SetLastError(ERROR_INVALID_DATA);
4020 return GL_FALSE;
4022 break;
4023 default:
4024 WARN("invalid attribute 0x%x\n", attr);
4025 SetLastError(ERROR_INVALID_DATA);
4026 return GL_FALSE;
4030 if (context && context->draw_pbuffer == pbuffer)
4031 make_context_current(context, FALSE);
4033 return GL_TRUE;
4037 /**********************************************************************
4038 * macdrv_wglSetPixelFormatWINE
4040 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4042 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4044 return set_pixel_format(hdc, fmt, TRUE);
4048 /**********************************************************************
4049 * macdrv_wglSwapIntervalEXT
4051 * WGL_EXT_swap_control: wglSwapIntervalEXT
4053 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4055 struct wgl_context *context = NtCurrentTeb()->glContext;
4056 BOOL changed = FALSE;
4058 TRACE("interval %d\n", interval);
4060 if (interval < 0)
4062 SetLastError(ERROR_INVALID_DATA);
4063 return FALSE;
4065 if (interval > 1)
4066 interval = 1;
4068 if (context->draw_hwnd)
4070 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4071 if (data)
4073 changed = data->swap_interval != interval;
4074 if (changed)
4075 data->swap_interval = interval;
4076 release_win_data(data);
4079 else /* pbuffer */
4080 interval = 0;
4082 if (!allow_vsync)
4083 interval = 0;
4085 InterlockedExchange(&context->update_swap_interval, FALSE);
4086 if (!set_swap_interval(context, interval))
4088 SetLastError(ERROR_GEN_FAILURE);
4089 return FALSE;
4092 if (changed)
4094 struct wgl_context *ctx;
4096 pthread_mutex_lock(&context_mutex);
4097 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4099 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4100 InterlockedExchange(&context->update_swap_interval, TRUE);
4102 pthread_mutex_unlock(&context_mutex);
4105 return TRUE;
4109 static void register_extension(const char *ext)
4111 if (gl_info.wglExtensions[0])
4112 strcat(gl_info.wglExtensions, " ");
4113 strcat(gl_info.wglExtensions, ext);
4115 TRACE("'%s'\n", ext);
4118 static void load_extensions(void)
4121 * ARB Extensions
4123 register_extension("WGL_ARB_extensions_string");
4124 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4126 register_extension("WGL_ARB_make_current_read");
4127 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4128 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4130 register_extension("WGL_ARB_pixel_format");
4131 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4132 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4133 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4135 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4137 register_extension("WGL_ARB_pixel_format_float");
4138 register_extension("WGL_ATI_pixel_format_float");
4141 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4142 register_extension("WGL_ARB_multisample");
4144 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4145 register_extension("WGL_ARB_framebuffer_sRGB");
4147 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4149 register_extension("WGL_ARB_pbuffer");
4150 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4151 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4152 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4153 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4154 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4156 register_extension("WGL_ARB_render_texture");
4157 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4158 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4159 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4161 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4162 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4163 register_extension("WGL_NV_render_texture_rectangle");
4166 register_extension("WGL_ARB_create_context");
4167 register_extension("WGL_ARB_create_context_profile");
4168 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4171 * EXT Extensions
4173 register_extension("WGL_EXT_extensions_string");
4174 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4176 if (allow_vsync)
4178 register_extension("WGL_EXT_swap_control");
4179 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4180 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4183 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4184 check for either, so register them separately. */
4185 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4186 register_extension("WGL_EXT_framebuffer_sRGB");
4188 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4189 register_extension("WGL_EXT_pixel_format_packed_float");
4192 * WINE-specific WGL Extensions
4195 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4196 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4198 register_extension("WGL_WINE_pixel_format_passthrough");
4199 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4201 register_extension("WGL_WINE_query_renderer");
4202 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4203 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4204 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4205 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4209 static void init_opengl(void)
4211 unsigned int i;
4213 TRACE("()\n");
4215 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4216 if (!dc_pbuffers)
4218 WARN("CFDictionaryCreateMutable failed\n");
4219 return;
4222 opengl_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD);
4223 if (!opengl_handle)
4225 ERR("Failed to load OpenGL: %s\n", dlerror());
4226 ERR("OpenGL support is disabled.\n");
4227 return;
4230 for (i = 0; i < ARRAY_SIZE(opengl_func_names); i++)
4232 if (!(((void **)&opengl_funcs.gl)[i] = dlsym(opengl_handle, opengl_func_names[i])))
4234 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4235 goto failed;
4239 if (!init_gl_info())
4240 goto failed;
4242 /* redirect some standard OpenGL functions */
4243 #define REDIRECT(func) \
4244 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4245 REDIRECT(glCopyPixels);
4246 REDIRECT(glGetString);
4247 REDIRECT(glReadPixels);
4248 REDIRECT(glViewport);
4249 if (skip_single_buffer_flushes || allow_vsync)
4250 REDIRECT(glFlush);
4251 if (allow_vsync)
4252 REDIRECT(glFinish);
4253 #undef REDIRECT
4255 /* redirect some OpenGL extension functions */
4256 #define REDIRECT(func) \
4257 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4258 REDIRECT(glCopyColorTable);
4259 #undef REDIRECT
4261 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4262 pglFlushRenderAPPLE = dlsym(opengl_handle, "glFlushRenderAPPLE");
4264 load_extensions();
4265 if (!init_pixel_formats())
4266 goto failed;
4268 return;
4270 failed:
4271 dlclose(opengl_handle);
4272 opengl_handle = NULL;
4276 /***********************************************************************
4277 * sync_gl_view
4279 * Synchronize the Mac GL view position with the Windows child window
4280 * position.
4282 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4284 if (data->client_cocoa_view && data->pixel_format)
4286 RECT old = *old_client_rect, new = data->client_rect;
4288 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4289 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4290 if (!EqualRect(&old, &new))
4292 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4293 mark_contexts_for_moved_view(data->client_cocoa_view);
4299 /**********************************************************************
4300 * macdrv_wglDescribePixelFormat
4302 static int WINAPI macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4304 const pixel_format *pf;
4305 const struct color_mode *mode;
4307 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4309 if (!descr) return nb_displayable_formats;
4310 if (size < sizeof(*descr)) return 0;
4312 if (!(pf = get_pixel_format(fmt, FALSE)))
4313 return 0;
4315 memset(descr, 0, sizeof(*descr));
4316 descr->nSize = sizeof(*descr);
4317 descr->nVersion = 1;
4319 descr->dwFlags = PFD_SUPPORT_OPENGL;
4320 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4321 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4322 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4323 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4324 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4326 descr->iPixelType = PFD_TYPE_RGBA;
4328 mode = &color_modes[pf->color_mode];
4329 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4330 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4331 R8G8B8A0 pixel format). If an app depends on that and expects that
4332 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4333 if (mode->alpha_bits)
4334 descr->cColorBits = mode->color_bits;
4335 else
4336 descr->cColorBits = mode->bits_per_pixel;
4337 descr->cRedBits = mode->red_bits;
4338 descr->cRedShift = mode->red_shift;
4339 descr->cGreenBits = mode->green_bits;
4340 descr->cGreenShift = mode->green_shift;
4341 descr->cBlueBits = mode->blue_bits;
4342 descr->cBlueShift = mode->blue_shift;
4343 descr->cAlphaBits = mode->alpha_bits;
4344 descr->cAlphaShift = mode->alpha_shift;
4346 if (pf->accum_mode)
4348 mode = &color_modes[pf->accum_mode - 1];
4349 descr->cAccumBits = mode->color_bits;
4350 descr->cAccumRedBits = mode->red_bits;
4351 descr->cAccumGreenBits = mode->green_bits;
4352 descr->cAccumBlueBits = mode->blue_bits;
4353 descr->cAccumAlphaBits = mode->alpha_bits;
4356 descr->cDepthBits = pf->depth_bits;
4357 descr->cStencilBits = pf->stencil_bits;
4358 descr->cAuxBuffers = pf->aux_buffers;
4359 descr->iLayerType = PFD_MAIN_PLANE;
4361 TRACE("%s\n", debugstr_pf(pf));
4362 return nb_displayable_formats;
4365 /***********************************************************************
4366 * macdrv_wglCopyContext
4368 static BOOL WINAPI macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4370 CGLError err;
4372 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4374 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4375 if (err != kCGLNoError)
4376 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4377 return (err == kCGLNoError);
4380 /***********************************************************************
4381 * macdrv_wglCreateContext
4383 static struct wgl_context * WINAPI macdrv_wglCreateContext(HDC hdc)
4385 struct wgl_context *context;
4387 TRACE("hdc %p\n", hdc);
4389 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4391 return context;
4394 /***********************************************************************
4395 * macdrv_wglDeleteContext
4397 static BOOL WINAPI macdrv_wglDeleteContext(struct wgl_context *context)
4399 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4401 pthread_mutex_lock(&context_mutex);
4402 list_remove(&context->entry);
4403 pthread_mutex_unlock(&context_mutex);
4405 macdrv_dispose_opengl_context(context->context);
4406 free(context);
4407 return TRUE;
4410 /***********************************************************************
4411 * macdrv_wglGetPixelFormat
4413 static int WINAPI macdrv_wglGetPixelFormat(HDC hdc)
4415 int format;
4417 format = get_dc_pixel_format(hdc);
4419 if (!is_valid_pixel_format(format)) /* not set yet */
4420 format = 0;
4421 else if (!is_displayable_pixel_format(format))
4423 /* Non-displayable formats can't be used with traditional WGL calls.
4424 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4425 format = 1;
4428 TRACE(" hdc %p -> %d\n", hdc, format);
4429 return format;
4432 /***********************************************************************
4433 * macdrv_wglGetProcAddress
4435 static PROC WINAPI macdrv_wglGetProcAddress(const char *proc)
4437 void *ret;
4439 if (!strncmp(proc, "wgl", 3)) return NULL;
4440 ret = dlsym(opengl_handle, proc);
4441 if (ret)
4443 if (TRACE_ON(wgl))
4445 Dl_info info;
4446 if (dladdr(ret, &info))
4447 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4448 else
4449 TRACE("%s -> %p (no library info)\n", proc, ret);
4452 else
4453 WARN("failed to find proc %s\n", debugstr_a(proc));
4454 return ret;
4457 /***********************************************************************
4458 * macdrv_wglMakeCurrent
4460 static BOOL WINAPI macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4462 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4463 (context ? context->cglcontext : NULL));
4465 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4468 /**********************************************************************
4469 * macdrv_wglSetPixelFormat
4471 static BOOL WINAPI macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4473 return set_pixel_format(hdc, fmt, FALSE);
4476 /***********************************************************************
4477 * macdrv_wglShareLists
4479 static BOOL WINAPI macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4481 macdrv_opengl_context saved_context;
4482 CGLContextObj saved_cglcontext;
4484 TRACE("org %p dest %p\n", org, dest);
4486 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4487 * at context creation time but in case of WGL it is done using wglShareLists.
4489 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4490 * and when a program requests sharing we recreate the destination context if it hasn't been made
4491 * current or when it hasn't shared display lists before.
4494 if (dest->has_been_current)
4496 WARN("could not share display lists, the destination context has been current already\n");
4497 return FALSE;
4499 else if (dest->sharing)
4501 WARN("could not share display lists because dest has already shared lists before\n");
4502 return FALSE;
4505 /* Re-create the Mac context and share display lists */
4506 saved_context = dest->context;
4507 saved_cglcontext = dest->cglcontext;
4508 dest->context = NULL;
4509 dest->cglcontext = NULL;
4510 if (!create_context(dest, org->cglcontext, dest->major))
4512 dest->context = saved_context;
4513 dest->cglcontext = saved_cglcontext;
4514 return FALSE;
4517 /* Implicitly disposes of saved_cglcontext. */
4518 macdrv_dispose_opengl_context(saved_context);
4520 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4521 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4523 org->sharing = TRUE;
4524 dest->sharing = TRUE;
4526 return TRUE;
4529 /**********************************************************************
4530 * macdrv_wglSwapBuffers
4532 static BOOL WINAPI macdrv_wglSwapBuffers(HDC hdc)
4534 struct wgl_context *context = NtCurrentTeb()->glContext;
4535 BOOL match = FALSE;
4536 HWND hwnd;
4538 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4539 (context ? context->cglcontext : NULL));
4541 if (context)
4543 sync_swap_interval(context);
4544 sync_context(context);
4547 if ((hwnd = NtUserWindowFromDC(hdc)))
4549 struct macdrv_win_data *data;
4551 if (!(data = get_win_data(hwnd)))
4553 SetLastError(ERROR_INVALID_HANDLE);
4554 return FALSE;
4557 if (context && context->draw_view == data->client_cocoa_view)
4558 match = TRUE;
4560 release_win_data(data);
4562 else
4564 struct wgl_pbuffer *pbuffer;
4566 pthread_mutex_lock(&dc_pbuffers_mutex);
4567 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4568 pthread_mutex_unlock(&dc_pbuffers_mutex);
4570 if (!pbuffer)
4572 SetLastError(ERROR_INVALID_HANDLE);
4573 return FALSE;
4576 if (context && context->draw_pbuffer == pbuffer)
4577 match = TRUE;
4580 if (match)
4581 macdrv_flush_opengl_context(context->context);
4582 else
4584 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4586 /* If there is a current context, then wglSwapBuffers should do an implicit
4587 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4588 in the other branch, but we have to do it explicitly here. */
4589 if (context)
4590 pglFlush();
4593 return TRUE;
4596 static struct opengl_funcs opengl_funcs =
4599 macdrv_wglCopyContext, /* p_wglCopyContext */
4600 macdrv_wglCreateContext, /* p_wglCreateContext */
4601 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4602 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4603 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4604 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4605 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4606 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4607 macdrv_wglShareLists, /* p_wglShareLists */
4608 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4612 /**********************************************************************
4613 * macdrv_wine_get_wgl_driver
4615 struct opengl_funcs *macdrv_wine_get_wgl_driver(UINT version)
4617 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
4619 if (version != WINE_WGL_DRIVER_VERSION)
4621 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4622 return NULL;
4625 pthread_once(&init_once, init_opengl);
4626 return opengl_handle ? &opengl_funcs : (void *)-1;