shcore: Use CRT allocation functions.
[wine.git] / dlls / winemac.drv / opengl.c
blob55e5704724b7f6bc46c35bc74b9dcbd6db6fdad6
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 #if 0
23 #pragma makedep unix
24 #endif
26 #include "config.h"
28 #include "macdrv.h"
30 #include "winuser.h"
31 #include "winternl.h"
32 #include "winnt.h"
33 #include "wine/debug.h"
34 #include "wine/wgl.h"
35 #include "wine/wgl_driver.h"
37 #define GL_SILENCE_DEPRECATION
38 #define __gl_h_
39 #define __gltypes_h_
40 #include <OpenGL/OpenGL.h>
41 #include <OpenGL/glu.h>
42 #include <OpenGL/CGLRenderers.h>
43 #include <dlfcn.h>
45 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
48 struct gl_info {
49 char *glExtensions;
51 char wglExtensions[4096];
53 GLint max_viewport_dims[2];
55 unsigned int max_major, max_minor;
58 static struct gl_info gl_info;
61 struct wgl_context
63 struct list entry;
64 int format;
65 GLint renderer_id;
66 macdrv_opengl_context context;
67 CGLContextObj cglcontext;
68 HWND draw_hwnd;
69 macdrv_view draw_view;
70 RECT draw_rect;
71 struct wgl_pbuffer *draw_pbuffer;
72 macdrv_view read_view;
73 RECT read_rect;
74 struct wgl_pbuffer *read_pbuffer;
75 BOOL has_been_current;
76 BOOL sharing;
77 LONG update_swap_interval;
78 LONG view_moved;
79 unsigned int last_flush_time;
80 UINT major;
83 static struct list context_list = LIST_INIT(context_list);
84 static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER;
87 struct wgl_pbuffer
89 CGLPBufferObj pbuffer;
90 int format;
91 BOOL no_texture;
92 int max_level;
93 GLint level;
94 GLenum face;
97 static CFMutableDictionaryRef dc_pbuffers;
98 static pthread_mutex_t dc_pbuffers_mutex = PTHREAD_MUTEX_INITIALIZER;
101 static struct opengl_funcs opengl_funcs;
103 #define USE_GL_FUNC(name) #name,
104 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
105 #undef USE_GL_FUNC
108 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
109 GLsizei width);
110 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
111 static void (*pglFinish)(void);
112 static void (*pglFlush)(void);
113 static void (*pglFlushRenderAPPLE)(void);
114 static const GLubyte *(*pglGetString)(GLenum name);
115 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
116 GLenum format, GLenum type, void *pixels);
117 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
120 struct color_mode {
121 GLint mode;
122 int bits_per_pixel;
123 GLint color_bits; /* including alpha_bits */
124 int red_bits, red_shift;
125 int green_bits, green_shift;
126 int blue_bits, blue_shift;
127 GLint alpha_bits, alpha_shift;
128 BOOL is_float;
129 int color_ordering;
132 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
133 observations of the behavior of Windows systems, but also subjective judgments
134 about what color formats are more "normal" than others.
136 On at least some Windows systems, integer color formats are listed before
137 floating-point formats. Within the integer formats, higher color bits were
138 usually listed before lower color bits, while for floating-point formats it
139 was the reverse. However, that leads D3D to select 64-bit integer formats in
140 preference to 32-bit formats when the latter would be sufficient. It seems
141 that a 32-bit format is much more likely to be normally used in that case.
143 Also, there are certain odd color formats supported on the Mac which seem like
144 they would be less appropriate than more common ones. For instance, the color
145 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
146 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
147 components.
149 For two color formats which differ only in whether or not they have alpha bits,
150 we use the same ordering. pixel_format_comparator() gives alpha bits a
151 different weight than color formats.
153 static const struct color_mode color_modes[] = {
154 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
155 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
156 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
157 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
158 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
159 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
160 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
161 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
162 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
163 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
164 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
165 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
166 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
167 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
168 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
169 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
170 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
171 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
172 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
173 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
174 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
175 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
176 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
177 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
181 static const struct {
182 GLint mode;
183 int bits;
184 } depth_stencil_modes[] = {
185 { kCGL0Bit, 0 },
186 { kCGL1Bit, 1 },
187 { kCGL2Bit, 2 },
188 { kCGL3Bit, 3 },
189 { kCGL4Bit, 4 },
190 { kCGL5Bit, 5 },
191 { kCGL6Bit, 6 },
192 { kCGL8Bit, 8 },
193 { kCGL10Bit, 10 },
194 { kCGL12Bit, 12 },
195 { kCGL16Bit, 16 },
196 { kCGL24Bit, 24 },
197 { kCGL32Bit, 32 },
198 { kCGL48Bit, 48 },
199 { kCGL64Bit, 64 },
200 { kCGL96Bit, 96 },
201 { kCGL128Bit, 128 },
205 typedef struct {
206 GLint renderer_id;
207 GLint buffer_modes;
208 GLint color_modes;
209 GLint accum_modes;
210 GLint depth_modes;
211 GLint stencil_modes;
212 GLint max_aux_buffers;
213 GLint max_sample_buffers;
214 GLint max_samples;
215 BOOL offscreen;
216 BOOL accelerated;
217 BOOL backing_store;
218 BOOL window;
219 BOOL online;
220 } renderer_properties;
223 typedef struct {
224 unsigned int window:1;
225 unsigned int pbuffer:1;
226 unsigned int accelerated:1;
227 unsigned int color_mode:5; /* index into color_modes table */
228 unsigned int aux_buffers:3;
229 unsigned int depth_bits:8;
230 unsigned int stencil_bits:8;
231 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
232 unsigned int double_buffer:1;
233 unsigned int stereo:1;
234 unsigned int sample_buffers:1;
235 unsigned int samples:5;
236 unsigned int backing_store:1;
237 } pixel_format;
240 typedef union
242 pixel_format format;
243 UInt64 code;
244 } pixel_format_or_code;
245 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
248 static pixel_format *pixel_formats;
249 static int nb_formats, nb_displayable_formats;
252 static void *opengl_handle;
255 static const char* debugstr_attrib(int attrib, int value)
257 static const struct {
258 int attrib;
259 const char *name;
260 } attrib_names[] = {
261 #define ATTRIB(a) { a, #a }
262 ATTRIB(WGL_ACCELERATION_ARB),
263 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
264 ATTRIB(WGL_ACCUM_BITS_ARB),
265 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
266 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
267 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
268 ATTRIB(WGL_ALPHA_BITS_ARB),
269 ATTRIB(WGL_ALPHA_SHIFT_ARB),
270 ATTRIB(WGL_AUX_BUFFERS_ARB),
271 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
272 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
273 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
274 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
275 ATTRIB(WGL_BLUE_BITS_ARB),
276 ATTRIB(WGL_BLUE_SHIFT_ARB),
277 ATTRIB(WGL_COLOR_BITS_ARB),
278 ATTRIB(WGL_DEPTH_BITS_ARB),
279 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
280 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
281 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
282 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
283 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
284 ATTRIB(WGL_GREEN_BITS_ARB),
285 ATTRIB(WGL_GREEN_SHIFT_ARB),
286 ATTRIB(WGL_NEED_PALETTE_ARB),
287 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
288 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
289 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
290 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
291 ATTRIB(WGL_PIXEL_TYPE_ARB),
292 ATTRIB(WGL_RED_BITS_ARB),
293 ATTRIB(WGL_RED_SHIFT_ARB),
294 ATTRIB(WGL_RENDERER_ID_WINE),
295 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
296 ATTRIB(WGL_SAMPLES_ARB),
297 ATTRIB(WGL_SHARE_ACCUM_ARB),
298 ATTRIB(WGL_SHARE_DEPTH_ARB),
299 ATTRIB(WGL_SHARE_STENCIL_ARB),
300 ATTRIB(WGL_STENCIL_BITS_ARB),
301 ATTRIB(WGL_STEREO_ARB),
302 ATTRIB(WGL_SUPPORT_GDI_ARB),
303 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
304 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
305 ATTRIB(WGL_SWAP_METHOD_ARB),
306 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
307 ATTRIB(WGL_TRANSPARENT_ARB),
308 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
309 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
310 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
311 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
312 #undef ATTRIB
314 int i;
315 const char *attrib_name = NULL;
316 const char *value_name = NULL;
318 for (i = 0; i < ARRAY_SIZE(attrib_names); i++)
320 if (attrib_names[i].attrib == attrib)
322 attrib_name = attrib_names[i].name;
323 break;
327 if (!attrib_name)
328 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
330 switch (attrib)
332 case WGL_ACCELERATION_ARB:
333 switch (value)
335 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
336 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
337 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
339 break;
340 case WGL_PIXEL_TYPE_ARB:
341 switch (value)
343 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
344 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
345 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
346 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
348 break;
349 case WGL_SWAP_METHOD_ARB:
350 switch (value)
352 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
353 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
354 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
356 break;
359 if (!value_name)
360 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
362 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
366 /**********************************************************************
367 * active_displays_mask
369 static CGOpenGLDisplayMask active_displays_mask(void)
371 CGError err;
372 CGDirectDisplayID displays[32];
373 uint32_t count, i;
374 CGOpenGLDisplayMask mask;
376 err = CGGetActiveDisplayList(ARRAY_SIZE(displays), displays, &count);
377 if (err != kCGErrorSuccess)
379 displays[0] = CGMainDisplayID();
380 count = 1;
383 mask = 0;
384 for (i = 0; i < count; i++)
385 mask |= CGDisplayIDToOpenGLDisplayMask(displays[i]);
387 return mask;
391 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
392 CGLRendererProperty property, GLint *value)
394 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
395 if (err != kCGLNoError)
396 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
397 return (err == kCGLNoError);
401 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
403 GLint value;
405 memset(properties, 0, sizeof(*properties));
407 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
408 properties->renderer_id = value & kCGLRendererIDMatchingMask;
410 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
411 properties->buffer_modes = value;
413 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
414 properties->color_modes = value;
416 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
417 properties->accum_modes = value;
419 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
420 properties->depth_modes = value;
422 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
423 properties->stencil_modes = value;
425 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
426 properties->max_aux_buffers = value;
428 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
429 properties->max_sample_buffers = value;
431 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
432 properties->max_samples = value;
434 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
435 properties->offscreen = (value != 0);
437 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
438 properties->accelerated = (value != 0);
440 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
441 properties->backing_store = (value != 0);
443 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
444 properties->window = (value != 0);
446 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
447 properties->online = (value != 0);
451 static void dump_renderer(const renderer_properties* renderer)
453 int i;
455 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
456 TRACE("Buffer modes:\n");
457 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
458 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
459 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
460 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
462 TRACE("Color buffer modes:\n");
463 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
465 if (renderer->color_modes & color_modes[i].mode)
467 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
468 if (color_modes[i].is_float)
469 TRACE(", Float");
470 TRACE("\n");
474 TRACE("Accumulation buffer sizes: { ");
475 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
477 if (renderer->accum_modes & color_modes[i].mode)
478 TRACE("%d, ", color_modes[i].color_bits);
480 TRACE("}\n");
482 TRACE("Depth buffer sizes: { ");
483 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
485 if (renderer->depth_modes & depth_stencil_modes[i].mode)
486 TRACE("%d, ", depth_stencil_modes[i].bits);
488 TRACE("}\n");
490 TRACE("Stencil buffer sizes: { ");
491 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
493 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
494 TRACE("%d, ", depth_stencil_modes[i].bits);
496 TRACE("}\n");
498 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
499 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
500 TRACE("Max. Samples: %d\n", renderer->max_samples);
501 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
502 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
503 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
504 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
505 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
509 static inline UInt64 code_for_pixel_format(const pixel_format* format)
511 pixel_format_or_code pfc;
513 pfc.code = 0;
514 pfc.format = *format;
515 return pfc.code;
519 static inline pixel_format pixel_format_for_code(UInt64 code)
521 pixel_format_or_code pfc;
523 pfc.code = code;
524 return pfc.format;
528 static const char *debugstr_pf(const pixel_format *pf)
530 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",
531 pf->window,
532 pf->pbuffer,
533 pf->accelerated,
534 color_modes[pf->color_mode].color_bits,
535 (color_modes[pf->color_mode].is_float ? "f" : ""),
536 color_modes[pf->color_mode].alpha_bits,
537 pf->depth_bits,
538 pf->stencil_bits,
539 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
540 pf->aux_buffers,
541 pf->backing_store,
542 pf->double_buffer,
543 pf->stereo,
544 pf->sample_buffers,
545 pf->samples,
546 code_for_pixel_format(pf));
550 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
552 int best = -1;
553 int i;
555 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
557 if ((modes & color_modes[i].mode) &&
558 color_modes[i].color_bits >= color_size &&
559 color_modes[i].alpha_bits >= alpha_size &&
560 !color_modes[i].is_float == !color_float)
562 if (best < 0) /* no existing best choice */
563 best = i;
564 else if (color_modes[i].color_bits == color_size &&
565 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
567 /* prefer it over a best which isn't exact or which has a higher bpp */
568 if (color_modes[best].color_bits != color_size ||
569 color_modes[best].alpha_bits != alpha_size ||
570 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
571 best = i;
573 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
574 (color_modes[i].color_bits == color_modes[best].color_bits &&
575 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
576 best = i;
580 if (best < 0)
582 /* Couldn't find a match. Return first one that renderer supports. */
583 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
585 if (modes & color_modes[i].mode)
586 return i;
590 return best;
594 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
596 int best = -1;
597 int i;
599 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
601 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
603 /* Prefer the fewest color bits, then prefer more alpha bits, then
604 prefer more bits per pixel. */
605 if (best < 0)
606 best = i;
607 else if (color_modes[i].color_bits < color_modes[best].color_bits)
608 best = i;
609 else if (color_modes[i].color_bits == color_modes[best].color_bits)
611 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
612 best = i;
613 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
614 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
615 best = i;
620 if (best < 0)
622 /* Couldn't find a match. Return last one that renderer supports. */
623 for (i = ARRAY_SIZE(color_modes) - 1; i >= 0; i--)
625 if (modes & color_modes[i].mode)
626 return i;
630 return best;
634 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
635 CFMutableSetRef pixel_format_set)
637 CGLPixelFormatAttribute attribs[64] = {
638 kCGLPFAMinimumPolicy,
639 kCGLPFAClosestPolicy,
640 kCGLPFARendererID, renderer.renderer_id,
641 kCGLPFASingleRenderer,
643 int n = 5, n_stack[16], n_stack_idx = -1;
644 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
645 new_pixel_formats = 0;
646 pixel_format request;
647 unsigned int double_buffer;
648 unsigned int accelerated = renderer.accelerated;
650 if (accelerated)
652 attribs[n++] = kCGLPFAAccelerated;
653 attribs[n++] = kCGLPFANoRecovery;
655 else if (!allow_software_rendering)
657 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
658 return;
661 n_stack[++n_stack_idx] = n;
662 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
664 unsigned int aux;
666 n = n_stack[n_stack_idx];
668 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
669 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
670 continue;
672 if (double_buffer)
673 attribs[n++] = kCGLPFADoubleBuffer;
674 memset(&request, 0, sizeof(request));
675 request.accelerated = accelerated;
676 request.double_buffer = double_buffer;
678 /* Don't bother with in-between aux buffers values: either 0 or max. */
679 n_stack[++n_stack_idx] = n;
680 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
682 unsigned int color_mode;
684 n = n_stack[n_stack_idx];
686 attribs[n++] = kCGLPFAAuxBuffers;
687 attribs[n++] = aux;
688 request.aux_buffers = aux;
690 n_stack[++n_stack_idx] = n;
691 for (color_mode = 0; color_mode < ARRAY_SIZE(color_modes); color_mode++)
693 unsigned int depth_mode;
695 n = n_stack[n_stack_idx];
697 if (!(renderer.color_modes & color_modes[color_mode].mode))
698 continue;
700 attribs[n++] = kCGLPFAColorSize;
701 attribs[n++] = color_modes[color_mode].color_bits;
702 attribs[n++] = kCGLPFAAlphaSize;
703 attribs[n++] = color_modes[color_mode].alpha_bits;
704 if (color_modes[color_mode].is_float)
705 attribs[n++] = kCGLPFAColorFloat;
706 request.color_mode = color_mode;
708 n_stack[++n_stack_idx] = n;
709 for (depth_mode = 0; depth_mode < ARRAY_SIZE(depth_stencil_modes); depth_mode++)
711 unsigned int stencil_mode;
713 n = n_stack[n_stack_idx];
715 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
716 continue;
718 attribs[n++] = kCGLPFADepthSize;
719 attribs[n++] = depth_stencil_modes[depth_mode].bits;
720 request.depth_bits = depth_stencil_modes[depth_mode].bits;
722 n_stack[++n_stack_idx] = n;
723 for (stencil_mode = 0; stencil_mode < ARRAY_SIZE(depth_stencil_modes); stencil_mode++)
725 unsigned int stereo;
727 n = n_stack[n_stack_idx];
729 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
730 continue;
731 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 &&
732 depth_stencil_modes[depth_mode].bits != 32 && stencil_mode > 0)
733 continue;
735 attribs[n++] = kCGLPFAStencilSize;
736 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
737 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
739 /* FIXME: Could trim search space a bit here depending on GPU.
740 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
741 n_stack[++n_stack_idx] = n;
742 for (stereo = 0; stereo <= 1; stereo++)
744 int accum_mode;
746 n = n_stack[n_stack_idx];
748 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
749 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
750 continue;
752 if (stereo)
753 attribs[n++] = kCGLPFAStereo;
754 request.stereo = stereo;
756 /* Starts at -1 for a 0 accum size */
757 n_stack[++n_stack_idx] = n;
758 for (accum_mode = -1; accum_mode < (int) ARRAY_SIZE(color_modes); accum_mode++)
760 unsigned int target_pass;
762 n = n_stack[n_stack_idx];
764 if (accum_mode >= 0)
766 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
767 continue;
769 attribs[n++] = kCGLPFAAccumSize;
770 attribs[n++] = color_modes[accum_mode].color_bits;
771 request.accum_mode = accum_mode + 1;
773 else
774 request.accum_mode = 0;
776 /* Targets to request are:
777 accelerated: window OR window + pbuffer
778 software: window + pbuffer */
779 n_stack[++n_stack_idx] = n;
780 for (target_pass = 0; target_pass <= accelerated; target_pass++)
782 unsigned int samples, max_samples;
784 n = n_stack[n_stack_idx];
786 attribs[n++] = kCGLPFAWindow;
787 request.window = 1;
789 if (!accelerated || target_pass > 0)
791 attribs[n++] = kCGLPFAPBuffer;
792 request.pbuffer = 1;
794 else
795 request.pbuffer = 0;
797 /* FIXME: Could trim search space a bit here depending on GPU.
798 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
799 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
800 n_stack[++n_stack_idx] = n;
801 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
802 for (samples = 1; samples <= max_samples; samples *= 2)
804 unsigned int backing_store, min_backing_store, max_backing_store;
806 n = n_stack[n_stack_idx];
808 if (samples > 1)
810 attribs[n++] = kCGLPFASampleBuffers;
811 attribs[n++] = renderer.max_sample_buffers;
812 attribs[n++] = kCGLPFASamples;
813 attribs[n++] = samples;
814 request.sample_buffers = renderer.max_sample_buffers;
815 request.samples = samples;
817 else
818 request.sample_buffers = request.samples = 0;
820 if (renderer.backing_store && double_buffer)
822 /* The software renderer seems to always preserve the backing store, whether
823 we ask for it or not. So don't bother not asking for it. */
824 min_backing_store = accelerated ? 0 : 1;
825 max_backing_store = 1;
827 else
828 min_backing_store = max_backing_store = 0;
829 n_stack[++n_stack_idx] = n;
830 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
832 CGLPixelFormatObj pix;
833 GLint virtualScreens;
834 CGLError err;
836 n = n_stack[n_stack_idx];
838 if (backing_store)
839 attribs[n++] = kCGLPFABackingStore;
840 request.backing_store = backing_store;
842 attribs[n] = 0;
844 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
845 if (err == kCGLNoError && pix)
847 pixel_format pf;
848 GLint value, color_size, alpha_size, color_float;
849 UInt64 pf_code;
850 CFNumberRef code_object;
851 BOOL dupe;
853 memset(&pf, 0, sizeof(pf));
855 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
856 pf.accelerated = value;
857 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
858 pf.aux_buffers = value;
859 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
860 pf.depth_bits = value;
861 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
862 pf.double_buffer = value;
863 if (pf.double_buffer &&
864 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
865 pf.backing_store = value;
866 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
867 pf.pbuffer = value;
868 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
869 pf.sample_buffers = value;
870 if (pf.sample_buffers &&
871 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
872 pf.samples = value;
873 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
874 pf.stencil_bits = value;
875 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
876 pf.stereo = value;
877 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
878 pf.window = value;
880 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
881 color_size = 0;
882 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
883 alpha_size = 0;
884 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
885 color_float = 0;
886 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
888 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
889 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
891 CGLReleasePixelFormat(pix);
893 pf_code = code_for_pixel_format(&pf);
895 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
896 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
897 dupe_pixel_formats++;
898 else
900 CFSetAddValue(pixel_format_set, code_object);
901 CFArrayAppendValue(pixel_format_array, code_object);
902 new_pixel_formats++;
904 CFRelease(code_object);
906 if (pf_code == code_for_pixel_format(&request))
907 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
908 else
910 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
911 dupe ? " (duplicate)" : "");
914 else
916 failed_pixel_formats++;
917 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
920 tried_pixel_formats++;
923 n_stack_idx--;
926 n_stack_idx--;
929 n_stack_idx--;
932 n_stack_idx--;
935 n_stack_idx--;
938 n_stack_idx--;
941 n_stack_idx--;
944 n_stack_idx--;
947 n_stack_idx--;
950 n_stack_idx--;
952 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
953 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
954 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
955 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
959 /* The docs for WGL_ARB_pixel_format say:
960 Indices are assigned to pixel formats in the following order:
961 1. Accelerated pixel formats that are displayable
962 2. Accelerated pixel formats that are displayable and which have
963 extended attributes
964 3. Generic pixel formats
965 4. Accelerated pixel formats that are non displayable
967 static int pixel_format_category(pixel_format pf)
969 /* non-displayable */
970 if (!pf.window)
971 return 4;
973 /* non-accelerated a.k.a. software a.k.a. generic */
974 if (!pf.accelerated)
975 return 3;
977 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
978 if (color_modes[pf.color_mode].is_float)
979 return 2;
981 /* accelerated, displayable, no extended attributes */
982 return 1;
986 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
988 CFNumberRef number1 = val1;
989 CFNumberRef number2 = val2;
990 UInt64 code1, code2;
991 pixel_format pf1, pf2;
992 int category1, category2;
994 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
995 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
996 pf1 = pixel_format_for_code(code1);
997 pf2 = pixel_format_for_code(code2);
998 category1 = pixel_format_category(pf1);
999 category2 = pixel_format_category(pf2);
1001 if (category1 < category2)
1002 return kCFCompareLessThan;
1003 if (category1 > category2)
1004 return kCFCompareGreaterThan;
1006 /* Within a category, sort the "best" formats toward the front since that's
1007 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1008 matches at least one Windows 7 machine's behavior.
1010 /* Accelerated before unaccelerated. */
1011 if (pf1.accelerated && !pf2.accelerated)
1012 return kCFCompareLessThan;
1013 if (!pf1.accelerated && pf2.accelerated)
1014 return kCFCompareGreaterThan;
1016 /* Explicit color mode ordering. */
1017 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1018 return kCFCompareLessThan;
1019 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1020 return kCFCompareGreaterThan;
1022 /* Non-pbuffer-capable before pbuffer-capable. */
1023 if (!pf1.pbuffer && pf2.pbuffer)
1024 return kCFCompareLessThan;
1025 if (pf1.pbuffer && !pf2.pbuffer)
1026 return kCFCompareGreaterThan;
1028 /* Fewer samples before more samples. */
1029 if (pf1.samples < pf2.samples)
1030 return kCFCompareLessThan;
1031 if (pf1.samples > pf2.samples)
1032 return kCFCompareGreaterThan;
1034 /* Monoscopic before stereoscopic. (This is a guess.) */
1035 if (!pf1.stereo && pf2.stereo)
1036 return kCFCompareLessThan;
1037 if (pf1.stereo && !pf2.stereo)
1038 return kCFCompareGreaterThan;
1040 /* Single buffered before double buffered. */
1041 if (!pf1.double_buffer && pf2.double_buffer)
1042 return kCFCompareLessThan;
1043 if (pf1.double_buffer && !pf2.double_buffer)
1044 return kCFCompareGreaterThan;
1046 /* Possibly-optimized double buffering before backing-store-preserving
1047 double buffering. */
1048 if (!pf1.backing_store && pf2.backing_store)
1049 return kCFCompareLessThan;
1050 if (pf1.backing_store && !pf2.backing_store)
1051 return kCFCompareGreaterThan;
1053 /* Bigger depth buffer before smaller depth buffer. */
1054 if (pf1.depth_bits > pf2.depth_bits)
1055 return kCFCompareLessThan;
1056 if (pf1.depth_bits < pf2.depth_bits)
1057 return kCFCompareGreaterThan;
1059 /* Smaller stencil buffer before bigger stencil buffer. */
1060 if (pf1.stencil_bits < pf2.stencil_bits)
1061 return kCFCompareLessThan;
1062 if (pf1.stencil_bits > pf2.stencil_bits)
1063 return kCFCompareGreaterThan;
1065 /* Smaller alpha bits before larger alpha bits. */
1066 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1067 return kCFCompareLessThan;
1068 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1069 return kCFCompareGreaterThan;
1071 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1072 if (pf1.accum_mode)
1074 if (pf2.accum_mode)
1076 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1077 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1078 return kCFCompareLessThan;
1079 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1080 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1081 return kCFCompareGreaterThan;
1083 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1084 return kCFCompareLessThan;
1085 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1086 return kCFCompareGreaterThan;
1088 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1089 return kCFCompareLessThan;
1090 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1091 return kCFCompareGreaterThan;
1093 else
1094 return kCFCompareGreaterThan;
1096 else if (pf2.accum_mode)
1097 return kCFCompareLessThan;
1099 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1100 if (pf1.aux_buffers < pf2.aux_buffers)
1101 return kCFCompareLessThan;
1102 if (pf1.aux_buffers > pf2.aux_buffers)
1103 return kCFCompareGreaterThan;
1105 /* If we get here, arbitrarily sort based on code. */
1106 if (code1 < code2)
1107 return kCFCompareLessThan;
1108 if (code1 > code2)
1109 return kCFCompareGreaterThan;
1110 return kCFCompareEqualTo;
1114 static BOOL init_pixel_formats(void)
1116 BOOL ret = FALSE;
1117 CGLRendererInfoObj renderer_info;
1118 GLint rendererCount;
1119 CGLError err;
1120 CFMutableSetRef pixel_format_set;
1121 CFMutableArrayRef pixel_format_array;
1122 int i;
1123 CFRange range;
1125 TRACE("()\n");
1127 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1128 if (err)
1130 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1131 return FALSE;
1134 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1135 if (!pixel_format_set)
1137 WARN("CFSetCreateMutable failed\n");
1138 CGLDestroyRendererInfo(renderer_info);
1139 return FALSE;
1142 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1143 if (!pixel_format_array)
1145 WARN("CFArrayCreateMutable failed\n");
1146 CFRelease(pixel_format_set);
1147 CGLDestroyRendererInfo(renderer_info);
1148 return FALSE;
1151 for (i = 0; i < rendererCount; i++)
1153 renderer_properties renderer;
1155 get_renderer_properties(renderer_info, i, &renderer);
1156 if (TRACE_ON(wgl))
1158 TRACE("renderer_properties %d:\n", i);
1159 dump_renderer(&renderer);
1162 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1165 CFRelease(pixel_format_set);
1166 CGLDestroyRendererInfo(renderer_info);
1168 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1169 if (range.length)
1171 pixel_formats = malloc(range.length * sizeof(*pixel_formats));
1172 if (pixel_formats)
1174 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1175 for (i = 0; i < range.length; i++)
1177 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1178 UInt64 code;
1180 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1181 pixel_formats[i] = pixel_format_for_code(code);
1182 if (pixel_formats[i].window)
1183 nb_displayable_formats++;
1186 nb_formats = range.length;
1187 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1188 ret = TRUE;
1190 else
1191 WARN("failed to allocate pixel format list\n");
1193 else
1194 WARN("got no pixel formats\n");
1196 CFRelease(pixel_format_array);
1197 return ret;
1201 static inline BOOL is_valid_pixel_format(int format)
1203 return format > 0 && format <= nb_formats;
1207 static inline BOOL is_displayable_pixel_format(int format)
1209 return format > 0 && format <= nb_displayable_formats;
1213 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1215 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1216 * format in case of probing the number of pixel formats.
1218 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1220 TRACE("Returning format %d\n", format);
1221 return &pixel_formats[format - 1];
1223 return NULL;
1227 static BOOL init_gl_info(void)
1229 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1230 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1232 CGDirectDisplayID display = CGMainDisplayID();
1233 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1234 CGLPixelFormatAttribute attribs[] = {
1235 kCGLPFADisplayMask, displayMask,
1238 CGLPixelFormatAttribute core_attribs[] =
1240 kCGLPFADisplayMask, displayMask,
1241 kCGLPFAAccelerated,
1242 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1245 CGLPixelFormatObj pix;
1246 GLint virtualScreens;
1247 CGLError err;
1248 CGLContextObj context;
1249 CGLContextObj old_context = CGLGetCurrentContext();
1250 const char *str;
1251 size_t length;
1253 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1254 if (err != kCGLNoError || !pix)
1256 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1257 return FALSE;
1260 err = CGLCreateContext(pix, NULL, &context);
1261 CGLReleasePixelFormat(pix);
1262 if (err != kCGLNoError || !context)
1264 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1265 return FALSE;
1268 err = CGLSetCurrentContext(context);
1269 if (err != kCGLNoError)
1271 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1272 CGLReleaseContext(context);
1273 return FALSE;
1276 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1277 length = strlen(str) + sizeof(legacy_extensions);
1278 if (allow_vsync)
1279 length += strlen(legacy_ext_swap_control);
1280 gl_info.glExtensions = malloc(length);
1281 strcpy(gl_info.glExtensions, str);
1282 strcat(gl_info.glExtensions, legacy_extensions);
1283 if (allow_vsync)
1284 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1286 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1288 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1289 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1290 TRACE("GL version : %s\n", str);
1291 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1293 CGLSetCurrentContext(old_context);
1294 CGLReleaseContext(context);
1296 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1297 if (err != kCGLNoError || !pix)
1299 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1300 err, CGLErrorString(err));
1301 return TRUE;
1304 err = CGLCreateContext(pix, NULL, &context);
1305 CGLReleasePixelFormat(pix);
1306 if (err != kCGLNoError || !context)
1308 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1309 err, CGLErrorString(err));
1310 return TRUE;
1313 err = CGLSetCurrentContext(context);
1314 if (err != kCGLNoError)
1316 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1317 err, CGLErrorString(err));
1318 CGLReleaseContext(context);
1319 return TRUE;
1322 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1323 TRACE("Core context GL version: %s\n", str);
1324 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1325 CGLSetCurrentContext(old_context);
1326 CGLReleaseContext(context);
1328 return TRUE;
1332 static int get_dc_pixel_format(HWND hwnd, HDC hdc)
1334 int format;
1336 if (hwnd)
1338 struct macdrv_win_data *data;
1340 if (!(data = get_win_data(hwnd)))
1342 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1343 return 0;
1346 format = data->pixel_format;
1347 release_win_data(data);
1349 else
1351 struct wgl_pbuffer *pbuffer;
1353 pthread_mutex_lock(&dc_pbuffers_mutex);
1354 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1355 if (pbuffer)
1356 format = pbuffer->format;
1357 else
1359 WARN("no window or pbuffer for DC %p\n", hdc);
1360 format = 0;
1362 pthread_mutex_unlock(&dc_pbuffers_mutex);
1365 return format;
1369 /**********************************************************************
1370 * create_context
1372 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1374 const pixel_format *pf;
1375 CGLPixelFormatAttribute attribs[64];
1376 int n = 0;
1377 CGLPixelFormatObj pix;
1378 GLint virtualScreens;
1379 CGLError err;
1380 BOOL core = major >= 3;
1382 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1383 if (!pf)
1385 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1386 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
1387 return FALSE;
1390 attribs[n++] = kCGLPFAMinimumPolicy;
1391 attribs[n++] = kCGLPFAClosestPolicy;
1393 if (context->renderer_id)
1395 attribs[n++] = kCGLPFARendererID;
1396 attribs[n++] = context->renderer_id;
1397 attribs[n++] = kCGLPFASingleRenderer;
1398 attribs[n++] = kCGLPFANoRecovery;
1401 if (pf->accelerated)
1403 attribs[n++] = kCGLPFAAccelerated;
1404 attribs[n++] = kCGLPFANoRecovery;
1406 else
1408 attribs[n++] = kCGLPFARendererID;
1409 attribs[n++] = kCGLRendererGenericFloatID;
1412 if (pf->double_buffer)
1413 attribs[n++] = kCGLPFADoubleBuffer;
1415 if (!core)
1417 attribs[n++] = kCGLPFAAuxBuffers;
1418 attribs[n++] = pf->aux_buffers;
1421 attribs[n++] = kCGLPFAColorSize;
1422 attribs[n++] = color_modes[pf->color_mode].color_bits;
1423 attribs[n++] = kCGLPFAAlphaSize;
1424 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1425 if (color_modes[pf->color_mode].is_float)
1426 attribs[n++] = kCGLPFAColorFloat;
1428 attribs[n++] = kCGLPFADepthSize;
1429 attribs[n++] = pf->depth_bits;
1431 attribs[n++] = kCGLPFAStencilSize;
1432 attribs[n++] = pf->stencil_bits;
1434 if (pf->stereo)
1435 attribs[n++] = kCGLPFAStereo;
1437 if (pf->accum_mode && !core)
1439 attribs[n++] = kCGLPFAAccumSize;
1440 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1443 if (pf->pbuffer && !core)
1444 attribs[n++] = kCGLPFAPBuffer;
1446 if (pf->sample_buffers && pf->samples)
1448 attribs[n++] = kCGLPFASampleBuffers;
1449 attribs[n++] = pf->sample_buffers;
1450 attribs[n++] = kCGLPFASamples;
1451 attribs[n++] = pf->samples;
1454 if (pf->backing_store)
1455 attribs[n++] = kCGLPFABackingStore;
1457 if (core)
1459 attribs[n++] = kCGLPFAOpenGLProfile;
1460 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1461 if (major == 3)
1462 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1463 else
1464 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1465 #else
1466 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1467 #endif
1470 attribs[n] = 0;
1472 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1473 if (err != kCGLNoError || !pix)
1475 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1476 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1477 return FALSE;
1480 err = CGLCreateContext(pix, share, &context->cglcontext);
1481 CGLReleasePixelFormat(pix);
1482 if (err != kCGLNoError || !context->cglcontext)
1484 context->cglcontext = NULL;
1485 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1486 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1487 return FALSE;
1490 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1492 GLint opacity = 0;
1493 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1494 if (err != kCGLNoError)
1495 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1497 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1499 GLint order = -1;
1500 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1501 if (err != kCGLNoError)
1502 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1505 context->context = macdrv_create_opengl_context(context->cglcontext);
1506 CGLReleaseContext(context->cglcontext);
1507 if (!context->context)
1509 WARN("macdrv_create_opengl_context() failed\n");
1510 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1511 return FALSE;
1513 context->major = major;
1515 InterlockedExchange(&context->update_swap_interval, TRUE);
1517 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1519 return TRUE;
1523 /**********************************************************************
1524 * set_pixel_format
1526 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1528 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL internal)
1530 struct macdrv_win_data *data;
1531 const pixel_format *pf;
1532 HWND hwnd = NtUserWindowFromDC(hdc);
1533 BOOL ret = FALSE;
1535 TRACE("hdc %p format %d\n", hdc, fmt);
1537 if (!hwnd || hwnd == NtUserGetDesktopWindow())
1539 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1540 return FALSE;
1543 if (!internal)
1545 /* cannot change it if already set */
1546 int prev = win32u_get_window_pixel_format( hwnd );
1548 if (prev)
1549 return prev == fmt;
1552 if (!(data = get_win_data(hwnd)))
1554 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1555 return FALSE;
1558 /* Check if fmt is in our list of supported formats to see if it is supported. */
1559 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1560 if (!pf)
1562 ERR("Invalid pixel format: %d\n", fmt);
1563 goto done;
1566 if (!pf->window)
1568 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1569 goto done;
1572 data->pixel_format = fmt;
1574 TRACE("pixel format:\n");
1575 TRACE(" window: %u\n", (unsigned int)pf->window);
1576 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1577 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1578 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1579 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1580 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1581 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1582 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1583 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1584 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1585 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1586 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1587 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1588 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1589 ret = TRUE;
1591 done:
1592 release_win_data(data);
1593 if (ret && gl_surface_mode == GL_SURFACE_BEHIND)
1594 win32u_set_window_pixel_format(hwnd, fmt, internal);
1595 return ret;
1599 /**********************************************************************
1600 * mark_contexts_for_moved_view
1602 static void mark_contexts_for_moved_view(macdrv_view view)
1604 struct wgl_context *context;
1606 pthread_mutex_lock(&context_mutex);
1607 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1609 if (context->draw_view == view)
1610 InterlockedExchange(&context->view_moved, TRUE);
1612 pthread_mutex_unlock(&context_mutex);
1616 /**********************************************************************
1617 * sync_context_rect
1619 static BOOL sync_context_rect(struct wgl_context *context)
1621 BOOL ret = FALSE;
1622 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1624 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1626 if (data && data->client_cocoa_view == context->draw_view)
1628 RECT rect = data->client_rect;
1629 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1630 if (!EqualRect(&context->draw_rect, &rect))
1632 context->draw_rect = rect;
1633 ret = TRUE;
1636 release_win_data(data);
1638 return ret;
1642 /**********************************************************************
1643 * make_context_current
1645 static void make_context_current(struct wgl_context *context, BOOL read)
1647 macdrv_view view;
1648 RECT view_rect;
1649 struct wgl_pbuffer *pbuffer;
1651 if (read)
1653 view = context->read_view;
1654 view_rect = context->read_rect;
1655 pbuffer = context->read_pbuffer;
1657 else
1659 sync_context_rect(context);
1661 view = context->draw_view;
1662 view_rect = context->draw_rect;
1663 pbuffer = context->draw_pbuffer;
1666 if (view || !pbuffer)
1667 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1668 else
1670 GLint enabled;
1672 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1673 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1674 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1675 pbuffer->level, 0);
1676 CGLSetCurrentContext(context->cglcontext);
1681 /**********************************************************************
1682 * sync_context
1684 static void sync_context(struct wgl_context *context)
1686 if (sync_context_rect(context))
1687 make_context_current(context, FALSE);
1691 /**********************************************************************
1692 * set_swap_interval
1694 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1696 CGLError err;
1698 /* In theory, for single-buffered contexts, there's no such thing as a swap
1699 so the swap interval shouldn't matter. But OS X will synchronize flushes
1700 of single-buffered contexts if the interval is set to non-zero. */
1701 if (interval && !pixel_formats[context->format - 1].double_buffer)
1702 interval = 0;
1704 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1705 if (err != kCGLNoError)
1706 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1708 return err == kCGLNoError;
1712 /**********************************************************************
1713 * sync_swap_interval
1715 static void sync_swap_interval(struct wgl_context *context)
1717 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1719 int interval;
1721 if (!allow_vsync)
1722 interval = 0;
1723 else if (context->draw_hwnd)
1725 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1726 if (data)
1728 interval = data->swap_interval;
1729 release_win_data(data);
1731 else /* window was destroyed? */
1732 interval = 1;
1734 else /* pbuffer */
1735 interval = 0;
1737 set_swap_interval(context, interval);
1742 /**********************************************************************
1743 * get_iokit_display_property
1745 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1747 GLint accelerated;
1748 GLint display_mask;
1749 int i;
1751 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1753 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1754 return FALSE;
1757 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1759 WARN("failed to get kCGLRPDisplayMask\n");
1760 return FALSE;
1763 for (i = 0; i < sizeof(GLint) * 8; i++)
1765 GLint this_display_mask = (GLint)(1U << i);
1766 if (this_display_mask & display_mask)
1768 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1769 io_service_t service;
1770 CFDataRef data;
1771 uint32_t prop_value;
1773 if (!display_id)
1774 continue;
1775 service = CGDisplayIOServicePort(display_id);
1776 if (!service)
1778 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1779 continue;
1782 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1783 kIORegistryIterateRecursively | kIORegistryIterateParents);
1784 if (!data)
1786 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1787 continue;
1789 if (CFGetTypeID(data) != CFDataGetTypeID())
1791 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1792 CFRelease(data);
1793 continue;
1795 if (CFDataGetLength(data) != sizeof(prop_value))
1797 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1798 (unsigned long long)CFDataGetLength(data));
1799 CFRelease(data);
1800 continue;
1803 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1804 CFRelease(data);
1805 *value = prop_value;
1806 return TRUE;
1810 return FALSE;
1814 /**********************************************************************
1815 * create_pixel_format_for_renderer
1817 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1818 * responsible for releasing the pixel format object.
1820 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1822 GLint renderer_id;
1823 CGLPixelFormatAttribute attrs[] = {
1824 kCGLPFARendererID, 0,
1825 kCGLPFASingleRenderer,
1826 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1829 CGError err;
1830 CGLPixelFormatObj pixel_format;
1831 GLint virtual_screens;
1833 if (core)
1835 attrs[3] = kCGLPFAOpenGLProfile;
1836 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1839 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1840 return NULL;
1842 attrs[1] = renderer_id;
1843 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1844 if (err != kCGLNoError)
1845 pixel_format = NULL;
1846 return pixel_format;
1850 /**********************************************************************
1851 * map_renderer_index
1853 * We can't create pixel formats for all renderers listed. For example,
1854 * in a dual-GPU system, the integrated GPU is typically unavailable
1855 * when the discrete GPU is active.
1857 * This function conceptually creates a list of "good" renderers from the
1858 * list of all renderers. It treats the input "renderer" parameter as an
1859 * index into that list of good renderers and returns the corresponding
1860 * index into the list of all renderers.
1862 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1864 GLint good_count, i;
1866 good_count = 0;
1867 for (i = 0; i < renderer_count; i++)
1869 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1870 if (pix)
1872 CGLReleasePixelFormat(pix);
1873 good_count++;
1874 if (good_count > renderer)
1875 break;
1877 else
1878 TRACE("skipping bad renderer %d\n", i);
1881 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1882 return i;
1886 /**********************************************************************
1887 * get_gl_string
1889 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1891 const char* ret = NULL;
1892 CGLContextObj context, old_context;
1893 CGLError err;
1895 err = CGLCreateContext(pixel_format, NULL, &context);
1896 if (err == kCGLNoError && context)
1898 old_context = CGLGetCurrentContext();
1899 err = CGLSetCurrentContext(context);
1900 if (err == kCGLNoError)
1902 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1903 CGLSetCurrentContext(old_context);
1905 else
1906 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1907 CGLReleaseContext(context);
1909 else
1910 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1912 return ret;
1916 /**********************************************************************
1917 * get_fallback_renderer_version
1919 static void get_fallback_renderer_version(GLuint *value)
1921 BOOL got_it = FALSE;
1922 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1923 kCFURLPOSIXPathStyle, TRUE);
1924 if (url)
1926 CFBundleRef bundle = CFBundleCreate(NULL, url);
1927 CFRelease(url);
1928 if (bundle)
1930 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1931 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1933 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1934 char* buf = malloc(len);
1935 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1937 unsigned int major, minor, bugfix;
1938 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1939 if (count >= 2)
1941 value[0] = major;
1942 value[1] = minor;
1943 if (count == 3)
1944 value[2] = bugfix;
1945 else
1946 value[2] = 0;
1947 got_it = TRUE;
1950 free(buf);
1952 CFRelease(bundle);
1956 if (!got_it)
1958 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1959 earliest version that the Mac driver supports. */
1960 value[0] = 1;
1961 value[1] = 6;
1962 value[2] = 14;
1967 /**********************************************************************
1968 * parse_renderer_version
1970 * Get the renderer version from the OpenGL version string. Assumes
1971 * the string is of the form
1972 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1973 * where major, minor, and bugfix are what we're interested in. This
1974 * form for the vendor specific information is not generally applicable,
1975 * but seems reliable on OS X.
1977 static BOOL parse_renderer_version(const char* version, GLuint *value)
1979 const char* p = strchr(version, ' ');
1980 int count;
1981 unsigned int major, minor, bugfix;
1983 if (p) p = strchr(p + 1, '-');
1984 if (!p) return FALSE;
1986 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
1987 if (count < 2)
1988 return FALSE;
1990 value[0] = major;
1991 value[1] = minor;
1992 if (count == 3)
1993 value[2] = bugfix;
1994 else
1995 value[2] = 0;
1997 return TRUE;
2001 /**********************************************************************
2002 * query_renderer_integer
2004 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2006 BOOL ret = FALSE;
2007 CGLError err;
2009 if (TRACE_ON(wgl))
2011 GLint renderer_id;
2012 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2013 renderer_id = 0;
2014 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2017 switch (attribute)
2019 case WGL_RENDERER_ACCELERATED_WINE:
2020 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2021 break;
2022 *value = !!*value;
2023 ret = TRUE;
2024 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2025 break;
2027 case WGL_RENDERER_DEVICE_ID_WINE:
2028 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2029 if (!ret)
2031 *value = 0xffffffff;
2032 ret = TRUE;
2034 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2035 break;
2037 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2038 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2040 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2041 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2043 if (pixel_format)
2045 const char* version = get_gl_string(pixel_format, GL_VERSION);
2047 CGLReleasePixelFormat(pixel_format);
2048 if (version)
2050 unsigned int major, minor;
2052 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2054 value[0] = major;
2055 value[1] = minor;
2056 ret = TRUE;
2061 if (!ret)
2063 value[0] = value[1] = 0;
2064 ret = TRUE;
2066 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2067 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2068 break;
2071 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2073 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2075 if (pixel_format)
2077 CGLReleasePixelFormat(pixel_format);
2078 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2079 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2081 else
2083 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2084 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2086 ret = TRUE;
2087 break;
2090 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2091 /* FIXME: no API to query this */
2092 *value = 0;
2093 ret = TRUE;
2094 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2095 break;
2097 case WGL_RENDERER_VENDOR_ID_WINE:
2098 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2099 if (!ret)
2101 *value = 0xffffffff;
2102 ret = TRUE;
2104 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2105 break;
2107 case WGL_RENDERER_VERSION_WINE:
2109 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2111 if (!pixel_format)
2112 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2113 if (pixel_format)
2115 const char* version = get_gl_string(pixel_format, GL_VERSION);
2117 CGLReleasePixelFormat(pixel_format);
2118 if (version)
2119 ret = parse_renderer_version(version, value);
2122 if (!ret)
2124 get_fallback_renderer_version(value);
2125 ret = TRUE;
2127 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2128 break;
2131 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2132 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2133 if (err != kCGLNoError && err != kCGLBadProperty)
2134 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2135 if (err != kCGLNoError)
2137 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2138 *value /= 1024 * 1024;
2139 else
2140 *value = 0;
2142 ret = TRUE;
2143 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2144 break;
2146 default:
2147 FIXME("unrecognized attribute 0x%04x\n", attribute);
2148 break;
2151 return ret;
2155 /**********************************************************************
2156 * macdrv_glCopyColorTable
2158 * Hook into glCopyColorTable as part of the implementation of
2159 * wglMakeContextCurrentARB. If the context has a separate readable,
2160 * temporarily make that current, do glCopyColorTable, and then set it
2161 * back to the drawable. This is modeled after what Mesa GLX's Apple
2162 * implementation does.
2164 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2165 GLsizei width)
2167 struct wgl_context *context = NtCurrentTeb()->glContext;
2169 if (context->read_view || context->read_pbuffer)
2170 make_context_current(context, TRUE);
2172 pglCopyColorTable(target, internalformat, x, y, width);
2174 if (context->read_view || context->read_pbuffer)
2175 make_context_current(context, FALSE);
2179 /**********************************************************************
2180 * macdrv_glCopyPixels
2182 * Hook into glCopyPixels as part of the implementation of
2183 * wglMakeContextCurrentARB. If the context has a separate readable,
2184 * temporarily make that current, do glCopyPixels, and then set it back
2185 * to the drawable. This is modeled after what Mesa GLX's Apple
2186 * implementation does.
2188 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2190 struct wgl_context *context = NtCurrentTeb()->glContext;
2192 if (context->read_view || context->read_pbuffer)
2193 make_context_current(context, TRUE);
2195 pglCopyPixels(x, y, width, height, type);
2197 if (context->read_view || context->read_pbuffer)
2198 make_context_current(context, FALSE);
2202 /**********************************************************************
2203 * macdrv_glFinish
2205 static void macdrv_glFinish(void)
2207 struct wgl_context *context = NtCurrentTeb()->glContext;
2209 sync_swap_interval(context);
2210 sync_context(context);
2211 pglFinish();
2215 /**********************************************************************
2216 * macdrv_glFlush
2218 static void macdrv_glFlush(void)
2220 struct wgl_context *context = NtCurrentTeb()->glContext;
2222 sync_swap_interval(context);
2223 sync_context(context);
2225 if (skip_single_buffer_flushes)
2227 const pixel_format *pf = &pixel_formats[context->format - 1];
2228 unsigned int now = NtGetTickCount();
2230 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2231 context->last_flush_time, now);
2232 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2234 TRACE("calling glFlushRenderAPPLE()\n");
2235 pglFlushRenderAPPLE();
2236 return;
2238 else
2240 TRACE("calling glFlush()\n");
2241 context->last_flush_time = now;
2245 pglFlush();
2249 /**********************************************************************
2250 * macdrv_glGetString
2252 * Hook into glGetString in order to return some legacy WGL extensions
2253 * that couldn't be advertised via the standard
2254 * WGL_ARB_extensions_string mechanism. Some programs, especially
2255 * older ones, expect to find certain older extensions, such as
2256 * WGL_EXT_extensions_string itself, in the standard GL extensions
2257 * string, and won't query any other WGL extensions unless they find
2258 * that particular extension there.
2260 static const GLubyte *macdrv_glGetString(GLenum name)
2262 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2263 return (const GLubyte *)gl_info.glExtensions;
2264 else
2265 return pglGetString(name);
2269 /**********************************************************************
2270 * macdrv_glReadPixels
2272 * Hook into glReadPixels as part of the implementation of
2273 * wglMakeContextCurrentARB. If the context has a separate readable,
2274 * temporarily make that current, do glReadPixels, and then set it back
2275 * to the drawable. This is modeled after what Mesa GLX's Apple
2276 * implementation does.
2278 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2279 GLenum format, GLenum type, void *pixels)
2281 struct wgl_context *context = NtCurrentTeb()->glContext;
2283 if (context->read_view || context->read_pbuffer)
2284 make_context_current(context, TRUE);
2286 pglReadPixels(x, y, width, height, format, type, pixels);
2288 if (context->read_view || context->read_pbuffer)
2289 make_context_current(context, FALSE);
2293 /**********************************************************************
2294 * macdrv_glViewport
2296 * Hook into glViewport as an opportunity to update the OpenGL context
2297 * if necessary. This is modeled after what Mesa GLX's Apple
2298 * implementation does.
2300 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2302 struct wgl_context *context = NtCurrentTeb()->glContext;
2304 sync_context(context);
2305 macdrv_update_opengl_context(context->context);
2306 pglViewport(x, y, width, height);
2310 /***********************************************************************
2311 * macdrv_wglBindTexImageARB
2313 * WGL_ARB_render_texture: wglBindTexImageARB
2315 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2317 struct wgl_context *context = NtCurrentTeb()->glContext;
2318 GLenum source;
2319 CGLError err;
2321 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2323 if (pbuffer->no_texture)
2325 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
2326 return GL_FALSE;
2329 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2330 opengl_funcs.gl.p_glFlush();
2332 switch (iBuffer)
2334 case WGL_FRONT_LEFT_ARB:
2335 if (pixel_formats[pbuffer->format - 1].stereo)
2336 source = GL_FRONT_LEFT;
2337 else
2338 source = GL_FRONT;
2339 break;
2340 case WGL_FRONT_RIGHT_ARB:
2341 source = GL_FRONT_RIGHT;
2342 break;
2343 case WGL_BACK_LEFT_ARB:
2344 if (pixel_formats[pbuffer->format - 1].stereo)
2345 source = GL_BACK_LEFT;
2346 else
2347 source = GL_BACK;
2348 break;
2349 case WGL_BACK_RIGHT_ARB:
2350 source = GL_BACK_RIGHT;
2351 break;
2352 case WGL_AUX0_ARB: source = GL_AUX0; break;
2353 case WGL_AUX1_ARB: source = GL_AUX1; break;
2354 case WGL_AUX2_ARB: source = GL_AUX2; break;
2355 case WGL_AUX3_ARB: source = GL_AUX3; break;
2357 case WGL_AUX4_ARB:
2358 case WGL_AUX5_ARB:
2359 case WGL_AUX6_ARB:
2360 case WGL_AUX7_ARB:
2361 case WGL_AUX8_ARB:
2362 case WGL_AUX9_ARB:
2363 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2364 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2365 return GL_FALSE;
2367 default:
2368 WARN("unknown source buffer 0x%x\n", iBuffer);
2369 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2370 return GL_FALSE;
2373 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2374 if (err != kCGLNoError)
2376 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2377 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
2378 return GL_FALSE;
2381 return GL_TRUE;
2385 /***********************************************************************
2386 * macdrv_wglChoosePixelFormatARB
2388 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2390 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2391 const FLOAT *pfAttribFList, UINT nMaxFormats,
2392 int *piFormats, UINT *nNumFormats)
2394 pixel_format pf, valid;
2395 const int *iptr;
2396 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2397 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2398 int float_color;
2399 BOOL srgb;
2400 int i, found = 0;
2402 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2403 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2404 if (pfAttribFList)
2405 FIXME("unused pfAttribFList\n");
2407 memset(&pf, 0, sizeof(pf));
2408 memset(&valid, 0, sizeof(valid));
2409 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2410 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2411 float_color = -1;
2412 srgb = FALSE;
2414 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2416 int attr = iptr[0];
2417 int value = iptr[1];
2419 TRACE("%s\n", debugstr_attrib(attr, value));
2421 switch (attr)
2423 case WGL_DRAW_TO_WINDOW_ARB:
2424 if (valid.window && (!pf.window != !value)) goto cant_match;
2425 pf.window = (value != 0);
2426 valid.window = 1;
2427 break;
2429 case WGL_DRAW_TO_BITMAP_ARB:
2430 goto cant_match;
2432 case WGL_ACCELERATION_ARB:
2433 if (value == WGL_FULL_ACCELERATION_ARB)
2434 value = 1;
2435 else if (value == WGL_NO_ACCELERATION_ARB)
2436 value = 0;
2437 else
2438 goto cant_match;
2439 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2440 pf.accelerated = value;
2441 valid.accelerated = 1;
2442 break;
2444 case WGL_NEED_PALETTE_ARB:
2445 case WGL_NEED_SYSTEM_PALETTE_ARB:
2446 case WGL_SWAP_LAYER_BUFFERS_ARB:
2447 if (value) goto cant_match;
2448 break;
2450 case WGL_SWAP_METHOD_ARB:
2451 if (value == WGL_SWAP_COPY_ARB)
2452 value = 1;
2453 else if (value == WGL_SWAP_UNDEFINED_ARB)
2454 value = 0;
2455 else
2456 goto cant_match;
2457 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2458 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2459 pf.backing_store = value;
2460 valid.backing_store = 1;
2461 break;
2463 case WGL_NUMBER_OVERLAYS_ARB:
2464 case WGL_NUMBER_UNDERLAYS_ARB:
2465 if (value) goto cant_match;
2466 break;
2468 case WGL_SHARE_DEPTH_ARB:
2469 case WGL_SHARE_STENCIL_ARB:
2470 case WGL_SHARE_ACCUM_ARB:
2471 /* no effect */
2472 break;
2474 case WGL_SUPPORT_GDI_ARB:
2475 if (value) goto cant_match;
2476 break;
2478 case WGL_SUPPORT_OPENGL_ARB:
2479 if (!value) goto cant_match;
2480 break;
2482 case WGL_DOUBLE_BUFFER_ARB:
2483 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2484 pf.double_buffer = (value != 0);
2485 valid.double_buffer = 1;
2486 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2487 break;
2489 case WGL_STEREO_ARB:
2490 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2491 pf.stereo = (value != 0);
2492 valid.stereo = 1;
2493 break;
2495 case WGL_PIXEL_TYPE_ARB:
2496 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2497 value = 1;
2498 else if (value == WGL_TYPE_RGBA_ARB)
2499 value = 0;
2500 else
2502 /* Mac contexts don't support rendering to unsigned floating
2503 point formats, even if GL_EXT_packed_float is supported.
2504 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2505 goto cant_match;
2507 if (float_color != -1 && float_color != value) goto cant_match;
2508 if (srgb && value) goto cant_match;
2509 float_color = value;
2510 break;
2512 case WGL_COLOR_BITS_ARB:
2513 if (color_bits < value) color_bits = value;
2514 break;
2516 case WGL_RED_BITS_ARB:
2517 if (srgb && value > 8) goto cant_match;
2518 if (red_bits < value) red_bits = value;
2519 break;
2521 case WGL_GREEN_BITS_ARB:
2522 if (srgb && value > 8) goto cant_match;
2523 if (green_bits < value) green_bits = value;
2524 break;
2526 case WGL_BLUE_BITS_ARB:
2527 if (srgb && value > 8) goto cant_match;
2528 if (blue_bits < value) blue_bits = value;
2529 break;
2531 case WGL_ALPHA_BITS_ARB:
2532 if (alpha_bits < value) alpha_bits = value;
2533 break;
2535 case WGL_ACCUM_BITS_ARB:
2536 if (accum_bits < value) accum_bits = value;
2537 break;
2539 case WGL_ACCUM_RED_BITS_ARB:
2540 if (accum_red_bits < value) accum_red_bits = value;
2541 break;
2543 case WGL_ACCUM_GREEN_BITS_ARB:
2544 if (accum_green_bits < value) accum_green_bits = value;
2545 break;
2547 case WGL_ACCUM_BLUE_BITS_ARB:
2548 if (accum_blue_bits < value) accum_blue_bits = value;
2549 break;
2551 case WGL_ACCUM_ALPHA_BITS_ARB:
2552 if (accum_alpha_bits < value) accum_alpha_bits = value;
2553 break;
2555 case WGL_DEPTH_BITS_ARB:
2556 if (value > 255) goto cant_match;
2557 if (pf.depth_bits < value) pf.depth_bits = value;
2558 break;
2560 case WGL_STENCIL_BITS_ARB:
2561 if (value > 255) goto cant_match;
2562 if (pf.stencil_bits < value) pf.stencil_bits = value;
2563 break;
2565 case WGL_AUX_BUFFERS_ARB:
2566 if (value > 7) goto cant_match;
2567 if (pf.aux_buffers < value) pf.aux_buffers = value;
2568 break;
2570 case WGL_SAMPLE_BUFFERS_ARB:
2571 if (value > 1) goto cant_match;
2572 if (pf.sample_buffers < value) pf.sample_buffers = value;
2573 break;
2575 case WGL_SAMPLES_ARB:
2576 if (value > 31) goto cant_match;
2577 if (pf.samples < value) pf.samples = value;
2578 break;
2580 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2581 /* sRGB is only supported for 8-bit integer color components */
2582 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2583 goto cant_match;
2584 srgb = TRUE;
2585 break;
2587 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2588 case WGL_RED_SHIFT_ARB:
2589 case WGL_GREEN_SHIFT_ARB:
2590 case WGL_BLUE_SHIFT_ARB:
2591 case WGL_ALPHA_SHIFT_ARB:
2592 case WGL_TRANSPARENT_ARB:
2593 case WGL_TRANSPARENT_RED_VALUE_ARB:
2594 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2595 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2596 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2597 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2598 /* ignored */
2599 break;
2601 case WGL_DRAW_TO_PBUFFER_ARB:
2602 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2603 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2604 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2605 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2606 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2607 pf.pbuffer = (value != 0);
2608 valid.pbuffer = 1;
2609 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2610 !alpha_bits)
2611 alpha_bits = 1;
2612 break;
2614 default:
2615 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2616 return GL_FALSE;
2620 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",
2621 valid.window ? (pf.window ? "1" : "0") : "?",
2622 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2623 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2624 color_bits,
2625 float_color == -1 ? "?" : float_color ? "f" : "",
2626 red_bits,
2627 green_bits,
2628 blue_bits,
2629 alpha_bits,
2630 (int)srgb,
2631 accum_bits,
2632 accum_red_bits,
2633 accum_green_bits,
2634 accum_blue_bits,
2635 accum_alpha_bits,
2636 pf.depth_bits,
2637 pf.stencil_bits,
2638 pf.aux_buffers,
2639 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2640 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2641 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2642 pf.sample_buffers,
2643 pf.samples);
2645 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2647 const struct color_mode *mode;
2649 if (valid.window && pixel_formats[i].window != pf.window) continue;
2650 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2651 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2652 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2653 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2654 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2656 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2657 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2658 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2659 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2660 if (pixel_formats[i].samples < pf.samples) continue;
2662 mode = &color_modes[pixel_formats[i].color_mode];
2663 /* If the mode doesn't have alpha, check requested color bits against
2664 bits per pixel instead of the mode's color bits. On Windows, color
2665 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2666 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2667 expects that to match such a pixel format, we need to accommodate that. */
2668 if (mode->alpha_bits)
2670 if (mode->color_bits < color_bits)
2671 continue;
2673 else
2675 if (mode->bits_per_pixel < color_bits)
2676 continue;
2678 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2679 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2680 continue;
2681 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2682 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2683 continue;
2685 if (pixel_formats[i].accum_mode)
2687 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2688 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2689 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2690 mode->alpha_bits < accum_alpha_bits)
2691 continue;
2693 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2694 continue;
2696 piFormats[found++] = i + 1;
2697 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2700 cant_match:
2701 *nNumFormats = found;
2703 return TRUE;
2707 /***********************************************************************
2708 * macdrv_wglCreateContextAttribsARB
2710 * WGL_ARB_create_context: wglCreateContextAttribsARB
2712 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2713 struct wgl_context *share_context,
2714 const int *attrib_list)
2716 int format;
2717 struct wgl_context *context;
2718 const int *iptr;
2719 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2720 BOOL core = FALSE;
2721 GLint renderer_id = 0;
2723 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2725 format = get_dc_pixel_format(NtUserWindowFromDC(hdc), hdc);
2727 if (!is_valid_pixel_format(format))
2729 ERR("Invalid pixel format %d, expect problems!\n", format);
2730 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
2731 return NULL;
2734 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2736 int attr = iptr[0];
2737 int value = iptr[1];
2739 TRACE("%s\n", debugstr_attrib(attr, value));
2741 switch (attr)
2743 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2744 major = value;
2745 break;
2747 case WGL_CONTEXT_MINOR_VERSION_ARB:
2748 minor = value;
2749 break;
2751 case WGL_CONTEXT_LAYER_PLANE_ARB:
2752 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2753 break;
2755 case WGL_CONTEXT_FLAGS_ARB:
2756 flags = value;
2757 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2758 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2759 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2760 break;
2762 case WGL_CONTEXT_PROFILE_MASK_ARB:
2763 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2764 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2766 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2767 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2768 return NULL;
2770 profile = value;
2771 break;
2773 case WGL_RENDERER_ID_WINE:
2775 CGLError err;
2776 CGLRendererInfoObj renderer_info;
2777 GLint renderer_count, temp;
2779 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2780 if (err != kCGLNoError)
2782 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2783 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
2784 return NULL;
2787 value = map_renderer_index(renderer_info, renderer_count, value);
2789 if (value >= renderer_count)
2791 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2792 CGLDestroyRendererInfo(renderer_info);
2793 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2794 return NULL;
2797 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2799 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2800 CGLDestroyRendererInfo(renderer_info);
2801 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
2802 return NULL;
2805 CGLDestroyRendererInfo(renderer_info);
2807 if (renderer_id && temp != renderer_id)
2809 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2810 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2811 return NULL;
2813 renderer_id = temp;
2814 break;
2817 default:
2818 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2819 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2820 return NULL;
2824 if ((major == 3 && (minor == 2 || minor == 3)) ||
2825 (major == 4 && (minor == 0 || minor == 1)))
2827 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2829 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2830 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2831 return NULL;
2833 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2835 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2836 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2837 return NULL;
2839 if (major > gl_info.max_major ||
2840 (major == gl_info.max_major && minor > gl_info.max_minor))
2842 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2843 major, minor);
2844 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2845 return NULL;
2847 core = TRUE;
2849 else if (major >= 3)
2851 WARN("Profile version %u.%u not supported\n", major, minor);
2852 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2853 return NULL;
2855 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2856 (major == 2 && (minor < 0 || minor > 1)))
2858 WARN("Invalid GL version requested\n");
2859 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2860 return NULL;
2862 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2864 WARN("Forward compatible context requested for GL version < 3\n");
2865 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2866 return NULL;
2869 if (!(context = calloc(1, sizeof(*context)))) return NULL;
2871 context->format = format;
2872 context->renderer_id = renderer_id;
2873 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2875 free(context);
2876 return NULL;
2879 pthread_mutex_lock(&context_mutex);
2880 list_add_tail(&context_list, &context->entry);
2881 pthread_mutex_unlock(&context_mutex);
2883 return context;
2887 /**********************************************************************
2888 * macdrv_wglCreatePbufferARB
2890 * WGL_ARB_pbuffer: wglCreatePbufferARB
2892 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2893 const int *piAttribList)
2895 struct wgl_pbuffer* pbuffer;
2896 GLenum target = 0;
2897 GLenum internalFormat = 0;
2898 CGLError err;
2900 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2901 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2903 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2905 WARN("invalid pixel format %d\n", iPixelFormat);
2906 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
2907 return NULL;
2910 pbuffer = calloc(1, sizeof(*pbuffer));
2911 pbuffer->format = iPixelFormat;
2913 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2915 int attr = piAttribList[0];
2916 int value = piAttribList[1];
2918 switch (attr)
2920 case WGL_PBUFFER_LARGEST_ARB:
2921 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2922 break;
2924 case WGL_TEXTURE_FORMAT_ARB:
2925 switch (value)
2927 case WGL_TEXTURE_RGBA_ARB:
2928 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2929 internalFormat = GL_RGBA;
2930 break;
2931 case WGL_TEXTURE_RGB_ARB:
2932 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2933 internalFormat = GL_RGB;
2934 break;
2935 case WGL_NO_TEXTURE_ARB:
2936 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2937 internalFormat = 0;
2938 break;
2939 default:
2940 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2941 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2942 goto done;
2944 break;
2946 case WGL_TEXTURE_TARGET_ARB:
2947 pbuffer->face = 0;
2948 switch (value)
2950 case WGL_NO_TEXTURE_ARB:
2951 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2952 target = 0;
2953 break;
2954 case WGL_TEXTURE_CUBE_MAP_ARB:
2955 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2956 target = GL_TEXTURE_CUBE_MAP;
2957 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2958 break;
2959 case WGL_TEXTURE_1D_ARB:
2960 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2961 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
2962 goto done;
2963 case WGL_TEXTURE_2D_ARB:
2964 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2965 target = GL_TEXTURE_2D;
2966 break;
2967 case WGL_TEXTURE_RECTANGLE_NV:
2968 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2969 target = GL_TEXTURE_RECTANGLE;
2970 break;
2971 default:
2972 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2973 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2974 goto done;
2976 break;
2978 case WGL_MIPMAP_TEXTURE_ARB:
2979 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2980 pbuffer->max_level = 0;
2981 if (value)
2983 int size = min(iWidth, iHeight) / 2;
2984 while (size)
2986 pbuffer->max_level++;
2987 size /= 2;
2990 break;
2992 default:
2993 WARN("unknown attribute 0x%x\n", attr);
2994 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2995 goto done;
2999 if (!target || !internalFormat)
3001 pbuffer->no_texture = TRUE;
3002 /* no actual way to turn off ability to texture; use most permissive target */
3003 target = GL_TEXTURE_RECTANGLE;
3004 internalFormat = GL_RGB;
3007 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3008 if (err != kCGLNoError)
3010 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3011 pbuffer->pbuffer = NULL;
3012 if (err == kCGLBadAlloc)
3013 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
3014 else
3015 RtlSetLastWin32Error(ERROR_INVALID_DATA);
3018 done:
3019 if (!pbuffer->pbuffer)
3021 free(pbuffer);
3022 return NULL;
3025 TRACE(" -> %p\n", pbuffer);
3026 return pbuffer;
3030 /**********************************************************************
3031 * macdrv_wglDestroyPbufferARB
3033 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3035 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3037 TRACE("pbuffer %p\n", pbuffer);
3038 if (pbuffer && pbuffer->pbuffer)
3039 CGLReleasePBuffer(pbuffer->pbuffer);
3040 free(pbuffer);
3041 return GL_TRUE;
3045 /**********************************************************************
3046 * macdrv_wglGetExtensionsStringARB
3048 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3050 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3052 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3053 this can be specific to the CGL renderer like we're supposed to do. */
3054 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3055 return gl_info.wglExtensions;
3059 /**********************************************************************
3060 * macdrv_wglGetExtensionsStringEXT
3062 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3064 static const char *macdrv_wglGetExtensionsStringEXT(void)
3066 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3067 return gl_info.wglExtensions;
3071 /**********************************************************************
3072 * macdrv_wglGetPbufferDCARB
3074 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3076 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3078 HDC hdc;
3079 struct wgl_pbuffer *prev;
3081 hdc = NtGdiOpenDCW(NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL);
3082 if (!hdc) return 0;
3084 pthread_mutex_lock(&dc_pbuffers_mutex);
3085 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3086 if (prev)
3088 CGLReleasePBuffer(prev->pbuffer);
3089 free(prev);
3091 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3092 pthread_mutex_unlock(&dc_pbuffers_mutex);
3094 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3095 return hdc;
3099 /**********************************************************************
3100 * macdrv_wglGetPixelFormatAttribivARB
3102 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3104 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3105 UINT nAttributes, const int *piAttributes, int *piValues)
3107 const pixel_format *pf;
3108 UINT i;
3110 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3111 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3113 if (!nAttributes) return GL_TRUE;
3115 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3117 piValues[0] = nb_formats;
3118 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3119 return GL_TRUE;
3122 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3123 if (!pf)
3125 WARN("invalid pixel format %d\n", iPixelFormat);
3126 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3127 return GL_FALSE;
3130 for (i = 0; i < nAttributes; ++i)
3132 switch (piAttributes[i])
3134 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3135 piValues[i] = nb_formats;
3136 break;
3138 case WGL_DRAW_TO_WINDOW_ARB:
3139 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3140 break;
3142 case WGL_DRAW_TO_BITMAP_ARB:
3143 piValues[i] = GL_FALSE;
3144 break;
3146 case WGL_ACCELERATION_ARB:
3147 if (iLayerPlane) goto invalid_layer;
3148 if (pf->accelerated)
3149 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3150 else
3151 piValues[i] = WGL_NO_ACCELERATION_ARB;
3152 break;
3154 case WGL_NEED_PALETTE_ARB:
3155 case WGL_NEED_SYSTEM_PALETTE_ARB:
3156 case WGL_SWAP_LAYER_BUFFERS_ARB:
3157 piValues[i] = GL_FALSE;
3158 break;
3160 case WGL_SWAP_METHOD_ARB:
3161 if (pf->double_buffer && pf->backing_store)
3162 piValues[i] = WGL_SWAP_COPY_ARB;
3163 else
3164 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3165 break;
3167 case WGL_NUMBER_OVERLAYS_ARB:
3168 case WGL_NUMBER_UNDERLAYS_ARB:
3169 piValues[i] = 0;
3170 break;
3172 case WGL_TRANSPARENT_ARB:
3173 if (iLayerPlane) goto invalid_layer;
3174 piValues[i] = GL_FALSE;
3175 break;
3177 case WGL_TRANSPARENT_RED_VALUE_ARB:
3178 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3179 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3180 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3181 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3182 if (iLayerPlane) goto invalid_layer;
3183 piValues[i] = 0;
3184 break;
3186 case WGL_SHARE_DEPTH_ARB:
3187 case WGL_SHARE_STENCIL_ARB:
3188 case WGL_SHARE_ACCUM_ARB:
3189 if (iLayerPlane) goto invalid_layer;
3190 piValues[i] = GL_TRUE;
3191 break;
3193 case WGL_SUPPORT_GDI_ARB:
3194 if (iLayerPlane) goto invalid_layer;
3195 piValues[i] = GL_FALSE;
3196 break;
3198 case WGL_SUPPORT_OPENGL_ARB:
3199 if (iLayerPlane) goto invalid_layer;
3200 piValues[i] = GL_TRUE;
3201 break;
3203 case WGL_DOUBLE_BUFFER_ARB:
3204 if (iLayerPlane) goto invalid_layer;
3205 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3206 break;
3208 case WGL_STEREO_ARB:
3209 if (iLayerPlane) goto invalid_layer;
3210 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3211 break;
3213 case WGL_PIXEL_TYPE_ARB:
3214 if (iLayerPlane) goto invalid_layer;
3215 if (color_modes[pf->color_mode].is_float)
3216 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3217 else
3218 piValues[i] = WGL_TYPE_RGBA_ARB;
3219 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3220 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3221 However, Mac contexts don't support rendering to unsigned floating-point
3222 formats, even when GL_EXT_packed_float is supported. */
3223 break;
3225 case WGL_COLOR_BITS_ARB:
3226 if (iLayerPlane) goto invalid_layer;
3227 /* If the mode doesn't have alpha, return bits per pixel instead
3228 of color bits. On Windows, color bits sometimes exceeds r+g+b
3229 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3230 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3231 pixel format, we need to accommodate that. */
3232 if (color_modes[pf->color_mode].alpha_bits)
3233 piValues[i] = color_modes[pf->color_mode].color_bits;
3234 else
3235 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3236 break;
3238 case WGL_RED_BITS_ARB:
3239 if (iLayerPlane) goto invalid_layer;
3240 piValues[i] = color_modes[pf->color_mode].red_bits;
3241 break;
3243 case WGL_RED_SHIFT_ARB:
3244 if (iLayerPlane) goto invalid_layer;
3245 piValues[i] = color_modes[pf->color_mode].red_shift;
3246 break;
3248 case WGL_GREEN_BITS_ARB:
3249 if (iLayerPlane) goto invalid_layer;
3250 piValues[i] = color_modes[pf->color_mode].green_bits;
3251 break;
3253 case WGL_GREEN_SHIFT_ARB:
3254 if (iLayerPlane) goto invalid_layer;
3255 piValues[i] = color_modes[pf->color_mode].green_shift;
3256 break;
3258 case WGL_BLUE_BITS_ARB:
3259 if (iLayerPlane) goto invalid_layer;
3260 piValues[i] = color_modes[pf->color_mode].blue_bits;
3261 break;
3263 case WGL_BLUE_SHIFT_ARB:
3264 if (iLayerPlane) goto invalid_layer;
3265 piValues[i] = color_modes[pf->color_mode].blue_shift;
3266 break;
3268 case WGL_ALPHA_BITS_ARB:
3269 if (iLayerPlane) goto invalid_layer;
3270 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3271 break;
3273 case WGL_ALPHA_SHIFT_ARB:
3274 if (iLayerPlane) goto invalid_layer;
3275 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3276 break;
3278 case WGL_ACCUM_BITS_ARB:
3279 if (iLayerPlane) goto invalid_layer;
3280 if (pf->accum_mode)
3281 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3282 else
3283 piValues[i] = 0;
3284 break;
3286 case WGL_ACCUM_RED_BITS_ARB:
3287 if (iLayerPlane) goto invalid_layer;
3288 if (pf->accum_mode)
3289 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3290 else
3291 piValues[i] = 0;
3292 break;
3294 case WGL_ACCUM_GREEN_BITS_ARB:
3295 if (iLayerPlane) goto invalid_layer;
3296 if (pf->accum_mode)
3297 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3298 else
3299 piValues[i] = 0;
3300 break;
3302 case WGL_ACCUM_BLUE_BITS_ARB:
3303 if (iLayerPlane) goto invalid_layer;
3304 if (pf->accum_mode)
3305 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3306 else
3307 piValues[i] = 0;
3308 break;
3310 case WGL_ACCUM_ALPHA_BITS_ARB:
3311 if (iLayerPlane) goto invalid_layer;
3312 if (pf->accum_mode)
3313 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3314 else
3315 piValues[i] = 0;
3316 break;
3318 case WGL_DEPTH_BITS_ARB:
3319 if (iLayerPlane) goto invalid_layer;
3320 piValues[i] = pf->depth_bits;
3321 break;
3323 case WGL_STENCIL_BITS_ARB:
3324 if (iLayerPlane) goto invalid_layer;
3325 piValues[i] = pf->stencil_bits;
3326 break;
3328 case WGL_AUX_BUFFERS_ARB:
3329 if (iLayerPlane) goto invalid_layer;
3330 piValues[i] = pf->aux_buffers;
3331 break;
3333 case WGL_SAMPLE_BUFFERS_ARB:
3334 if (iLayerPlane) goto invalid_layer;
3335 piValues[i] = pf->sample_buffers;
3336 break;
3338 case WGL_SAMPLES_ARB:
3339 if (iLayerPlane) goto invalid_layer;
3340 piValues[i] = pf->samples;
3341 break;
3343 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3344 if (iLayerPlane) goto invalid_layer;
3345 /* sRGB is only supported for 8-bit integer color components */
3346 if (color_modes[pf->color_mode].red_bits == 8 &&
3347 color_modes[pf->color_mode].green_bits == 8 &&
3348 color_modes[pf->color_mode].blue_bits == 8 &&
3349 !color_modes[pf->color_mode].is_float)
3350 piValues[i] = GL_TRUE;
3351 else
3352 piValues[i] = GL_FALSE;
3353 break;
3355 case WGL_DRAW_TO_PBUFFER_ARB:
3356 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3357 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3358 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3359 break;
3361 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3362 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3363 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3364 break;
3366 case WGL_MAX_PBUFFER_WIDTH_ARB:
3367 piValues[i] = gl_info.max_viewport_dims[0];
3368 break;
3370 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3371 piValues[i] = gl_info.max_viewport_dims[1];
3372 break;
3374 case WGL_MAX_PBUFFER_PIXELS_ARB:
3375 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3376 break;
3378 default:
3379 WARN("invalid attribute %x\n", piAttributes[i]);
3380 return GL_FALSE;
3383 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3386 return GL_TRUE;
3388 invalid_layer:
3389 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3390 return GL_FALSE;
3394 /**********************************************************************
3395 * macdrv_wglGetPixelFormatAttribfvARB
3397 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3399 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3400 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3402 int *attr;
3403 int ret;
3405 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3406 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3408 /* Allocate a temporary array to store integer values */
3409 attr = malloc(nAttributes * sizeof(int));
3410 if (!attr)
3412 ERR("couldn't allocate %d array\n", nAttributes);
3413 return GL_FALSE;
3416 /* Piggy-back on wglGetPixelFormatAttribivARB */
3417 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3418 if (ret)
3420 UINT i;
3422 /* Convert integer values to float. Should also check for attributes
3423 that can give decimal values here */
3424 for (i = 0; i < nAttributes; i++)
3425 pfValues[i] = attr[i];
3428 free(attr);
3429 return ret;
3433 /**********************************************************************
3434 * macdrv_wglGetSwapIntervalEXT
3436 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3438 static int macdrv_wglGetSwapIntervalEXT(void)
3440 struct wgl_context *context = NtCurrentTeb()->glContext;
3441 struct macdrv_win_data *data;
3442 long value;
3443 CGLError err;
3445 TRACE("\n");
3447 if ((data = get_win_data(context->draw_hwnd)))
3449 value = data->swap_interval;
3450 release_win_data(data);
3452 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3453 set_swap_interval(context, allow_vsync ? value : 0);
3455 else
3457 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3458 if (err != kCGLNoError)
3460 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3461 err, CGLErrorString(err));
3462 value = 1;
3466 return value;
3470 /***********************************************************************
3471 * macdrv_wglMakeContextCurrentARB
3473 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3475 * This is not supported directly by OpenGL on the Mac. We emulate it
3476 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3477 * temporarily swap the drawable. This follows the technique used in
3478 * the implementation of Mesa GLX for Apple.
3480 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3482 struct macdrv_win_data *data;
3483 HWND hwnd;
3485 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3486 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3488 if (!context)
3490 macdrv_make_context_current(NULL, NULL, CGRectNull);
3491 NtCurrentTeb()->glContext = NULL;
3492 return TRUE;
3495 if ((hwnd = NtUserWindowFromDC(draw_hdc)))
3497 if (!(data = get_win_data(hwnd)))
3499 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3500 return FALSE;
3503 if (!data->pixel_format)
3505 WARN("no pixel format set\n");
3506 release_win_data(data);
3507 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3508 return FALSE;
3510 if (context->format != data->pixel_format)
3512 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3513 release_win_data(data);
3514 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3515 return FALSE;
3518 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd)
3519 set_swap_interval(context, allow_vsync ? data->swap_interval : 0);
3521 context->draw_hwnd = hwnd;
3522 context->draw_view = data->client_cocoa_view;
3523 context->draw_rect = data->client_rect;
3524 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3525 context->draw_pbuffer = NULL;
3526 release_win_data(data);
3528 else
3530 struct wgl_pbuffer *pbuffer;
3532 pthread_mutex_lock(&dc_pbuffers_mutex);
3533 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3534 if (pbuffer)
3536 if (context->format != pbuffer->format)
3538 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3539 pthread_mutex_unlock(&dc_pbuffers_mutex);
3540 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3541 return FALSE;
3544 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer)
3545 set_swap_interval(context, 0);
3547 else
3549 WARN("no window or pbuffer for DC\n");
3550 pthread_mutex_unlock(&dc_pbuffers_mutex);
3551 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3552 return FALSE;
3555 context->draw_hwnd = NULL;
3556 context->draw_view = NULL;
3557 context->draw_pbuffer = pbuffer;
3558 pthread_mutex_unlock(&dc_pbuffers_mutex);
3561 context->read_view = NULL;
3562 context->read_pbuffer = NULL;
3563 if (read_hdc && read_hdc != draw_hdc)
3565 if ((hwnd = NtUserWindowFromDC(read_hdc)))
3567 if ((data = get_win_data(hwnd)))
3569 if (data->client_cocoa_view != context->draw_view)
3571 context->read_view = data->client_cocoa_view;
3572 context->read_rect = data->client_rect;
3573 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3575 release_win_data(data);
3578 else
3580 pthread_mutex_lock(&dc_pbuffers_mutex);
3581 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3582 pthread_mutex_unlock(&dc_pbuffers_mutex);
3586 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3587 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3588 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3590 make_context_current(context, FALSE);
3591 context->has_been_current = TRUE;
3592 NtCurrentTeb()->glContext = context;
3594 return TRUE;
3598 /**********************************************************************
3599 * macdrv_wglQueryCurrentRendererIntegerWINE
3601 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3603 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3605 BOOL ret = FALSE;
3606 struct wgl_context *context = NtCurrentTeb()->glContext;
3607 CGLPixelFormatObj pixel_format;
3608 CGLError err;
3609 GLint virtual_screen;
3610 GLint display_mask;
3611 GLint pf_renderer_id;
3612 CGLRendererInfoObj renderer_info;
3613 GLint renderer_count;
3614 GLint renderer;
3616 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3617 (context ? context->cglcontext : NULL), attribute, value);
3619 if (attribute == WGL_RENDERER_VERSION_WINE)
3621 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3622 get_fallback_renderer_version(value);
3623 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3624 return TRUE;
3627 pixel_format = CGLGetPixelFormat(context->cglcontext);
3628 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3629 if (err != kCGLNoError)
3631 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3632 return FALSE;
3635 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3636 if (err != kCGLNoError)
3638 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3639 return FALSE;
3642 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3643 if (err != kCGLNoError)
3645 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3646 return FALSE;
3649 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3650 if (err != kCGLNoError)
3652 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3653 return FALSE;
3656 for (renderer = 0; renderer < renderer_count; renderer++)
3658 GLint renderer_id;
3660 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3661 continue;
3663 if (renderer_id == pf_renderer_id)
3665 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3666 break;
3670 if (renderer >= renderer_count)
3671 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3673 CGLDestroyRendererInfo(renderer_info);
3674 return ret;
3678 /**********************************************************************
3679 * macdrv_wglQueryCurrentRendererStringWINE
3681 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3683 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3685 const char* ret = NULL;
3686 struct wgl_context *context = NtCurrentTeb()->glContext;
3688 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3689 (context ? context->cglcontext : NULL), attribute);
3691 switch (attribute)
3693 case WGL_RENDERER_DEVICE_ID_WINE:
3695 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3696 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3697 break;
3700 case WGL_RENDERER_VENDOR_ID_WINE:
3702 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3703 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3704 break;
3707 default:
3708 FIXME("unrecognized attribute 0x%04x\n", attribute);
3709 break;
3712 return ret;
3716 /**********************************************************************
3717 * macdrv_wglQueryPbufferARB
3719 * WGL_ARB_pbuffer: wglQueryPbufferARB
3721 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3723 CGLError err;
3724 GLsizei width;
3725 GLsizei height;
3726 GLenum target;
3727 GLenum internalFormat;
3728 GLint mipmap;
3730 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3732 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3733 if (err != kCGLNoError)
3735 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3736 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3737 return GL_FALSE;
3740 switch (iAttribute)
3742 case WGL_PBUFFER_WIDTH_ARB:
3743 *piValue = width;
3744 break;
3745 case WGL_PBUFFER_HEIGHT_ARB:
3746 *piValue = height;
3747 break;
3748 case WGL_PBUFFER_LOST_ARB:
3749 /* Mac PBuffers can't be lost */
3750 *piValue = GL_FALSE;
3751 break;
3752 case WGL_TEXTURE_FORMAT_ARB:
3753 if (pbuffer->no_texture)
3754 *piValue = WGL_NO_TEXTURE_ARB;
3755 else switch (internalFormat)
3757 case GL_RGBA:
3758 *piValue = WGL_TEXTURE_RGBA_ARB;
3759 break;
3760 case GL_RGB:
3761 default:
3762 *piValue = WGL_TEXTURE_RGB_ARB;
3763 break;
3765 break;
3766 case WGL_TEXTURE_TARGET_ARB:
3767 if (pbuffer->no_texture)
3768 *piValue = WGL_NO_TEXTURE_ARB;
3769 else switch (target)
3771 case GL_TEXTURE_CUBE_MAP:
3772 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3773 break;
3774 case GL_TEXTURE_2D:
3775 *piValue = WGL_TEXTURE_2D_ARB;
3776 break;
3777 case GL_TEXTURE_RECTANGLE:
3778 default:
3779 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3780 break;
3782 break;
3783 case WGL_MIPMAP_TEXTURE_ARB:
3784 *piValue = (pbuffer->max_level > 0);
3785 break;
3786 case WGL_MIPMAP_LEVEL_ARB:
3787 *piValue = pbuffer->level;
3788 break;
3789 case WGL_CUBE_MAP_FACE_ARB:
3790 switch (pbuffer->face)
3792 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3793 default:
3794 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3795 break;
3796 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3797 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3798 break;
3799 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3800 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3801 break;
3802 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3803 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3804 break;
3805 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3806 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3807 break;
3808 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3809 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3810 break;
3812 break;
3813 default:
3814 WARN("invalid attribute 0x%x\n", iAttribute);
3815 RtlSetLastWin32Error(ERROR_INVALID_DATA);
3816 return GL_FALSE;
3819 return GL_TRUE;
3823 /**********************************************************************
3824 * macdrv_wglQueryRendererIntegerWINE
3826 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3828 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3830 BOOL ret = FALSE;
3831 CGLRendererInfoObj renderer_info;
3832 GLint renderer_count;
3833 CGLError err;
3835 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3837 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3838 if (err != kCGLNoError)
3840 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3841 return FALSE;
3844 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3846 if (renderer < renderer_count)
3847 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3848 else
3849 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3851 CGLDestroyRendererInfo(renderer_info);
3852 return ret;
3856 /**********************************************************************
3857 * macdrv_wglQueryRendererStringWINE
3859 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3861 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3863 const char* ret = NULL;
3864 CGLRendererInfoObj renderer_info;
3865 GLint renderer_count;
3866 CGLError err;
3868 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3870 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3871 if (err != kCGLNoError)
3873 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3874 return FALSE;
3877 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3879 if (renderer >= renderer_count)
3881 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3882 goto done;
3885 switch (attribute)
3887 case WGL_RENDERER_DEVICE_ID_WINE:
3888 case WGL_RENDERER_VENDOR_ID_WINE:
3890 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3891 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3893 if (!pixel_format)
3894 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3895 if (pixel_format)
3897 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3898 CGLReleasePixelFormat(pixel_format);
3901 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3902 break;
3905 default:
3906 FIXME("unrecognized attribute 0x%04x\n", attribute);
3907 break;
3910 done:
3911 CGLDestroyRendererInfo(renderer_info);
3912 return ret;
3916 /**********************************************************************
3917 * macdrv_wglReleasePbufferDCARB
3919 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3921 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3923 struct wgl_pbuffer *prev;
3925 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3927 pthread_mutex_lock(&dc_pbuffers_mutex);
3929 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3930 if (prev)
3932 if (prev != pbuffer)
3933 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3934 CGLReleasePBuffer(prev->pbuffer);
3935 free(prev);
3936 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3938 else hdc = 0;
3940 pthread_mutex_unlock(&dc_pbuffers_mutex);
3942 return hdc && NtGdiDeleteObjectApp(hdc);
3946 /**********************************************************************
3947 * macdrv_wglReleaseTexImageARB
3949 * WGL_ARB_render_texture: wglReleaseTexImageARB
3951 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3953 struct wgl_context *context = NtCurrentTeb()->glContext;
3954 CGLError err;
3956 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3958 if (pbuffer->no_texture)
3960 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
3961 return GL_FALSE;
3964 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3965 if (err != kCGLNoError)
3967 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3968 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
3969 return GL_FALSE;
3972 return GL_TRUE;
3976 /**********************************************************************
3977 * macdrv_wglSetPbufferAttribARB
3979 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3981 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3983 struct wgl_context *context = NtCurrentTeb()->glContext;
3985 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3987 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3989 int attr = piAttribList[0];
3990 int value = piAttribList[1];
3991 switch (attr)
3993 case WGL_MIPMAP_LEVEL_ARB:
3994 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3995 pbuffer->level = value;
3996 break;
3997 case WGL_CUBE_MAP_FACE_ARB:
3998 switch (value)
4000 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
4001 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4002 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4003 break;
4004 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4005 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4006 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4007 break;
4008 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4009 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4010 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4011 break;
4012 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4013 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4014 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4015 break;
4016 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4017 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4018 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4019 break;
4020 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4021 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4022 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4023 break;
4024 default:
4025 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4026 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4027 return GL_FALSE;
4029 break;
4030 default:
4031 WARN("invalid attribute 0x%x\n", attr);
4032 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4033 return GL_FALSE;
4037 if (context && context->draw_pbuffer == pbuffer)
4038 make_context_current(context, FALSE);
4040 return GL_TRUE;
4044 /**********************************************************************
4045 * macdrv_wglSetPixelFormatWINE
4047 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4049 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4051 return set_pixel_format(hdc, fmt, TRUE);
4055 /**********************************************************************
4056 * macdrv_wglSwapIntervalEXT
4058 * WGL_EXT_swap_control: wglSwapIntervalEXT
4060 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4062 struct wgl_context *context = NtCurrentTeb()->glContext;
4063 BOOL changed = FALSE;
4065 TRACE("interval %d\n", interval);
4067 if (interval < 0)
4069 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4070 return FALSE;
4072 if (interval > 1)
4073 interval = 1;
4075 if (context->draw_hwnd)
4077 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4078 if (data)
4080 changed = data->swap_interval != interval;
4081 if (changed)
4082 data->swap_interval = interval;
4083 release_win_data(data);
4086 else /* pbuffer */
4087 interval = 0;
4089 if (!allow_vsync)
4090 interval = 0;
4092 InterlockedExchange(&context->update_swap_interval, FALSE);
4093 if (!set_swap_interval(context, interval))
4095 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
4096 return FALSE;
4099 if (changed)
4101 struct wgl_context *ctx;
4103 pthread_mutex_lock(&context_mutex);
4104 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4106 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4107 InterlockedExchange(&context->update_swap_interval, TRUE);
4109 pthread_mutex_unlock(&context_mutex);
4112 return TRUE;
4116 static void register_extension(const char *ext)
4118 if (gl_info.wglExtensions[0])
4119 strcat(gl_info.wglExtensions, " ");
4120 strcat(gl_info.wglExtensions, ext);
4122 TRACE("'%s'\n", ext);
4125 static void load_extensions(void)
4128 * ARB Extensions
4130 register_extension("WGL_ARB_extensions_string");
4131 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4133 register_extension("WGL_ARB_make_current_read");
4134 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4135 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4137 register_extension("WGL_ARB_pixel_format");
4138 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4139 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4140 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4142 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4144 register_extension("WGL_ARB_pixel_format_float");
4145 register_extension("WGL_ATI_pixel_format_float");
4148 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4149 register_extension("WGL_ARB_multisample");
4151 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4152 register_extension("WGL_ARB_framebuffer_sRGB");
4154 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4156 register_extension("WGL_ARB_pbuffer");
4157 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4158 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4159 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4160 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4161 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4163 register_extension("WGL_ARB_render_texture");
4164 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4165 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4166 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4168 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4169 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4170 register_extension("WGL_NV_render_texture_rectangle");
4173 register_extension("WGL_ARB_create_context");
4174 register_extension("WGL_ARB_create_context_profile");
4175 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4178 * EXT Extensions
4180 register_extension("WGL_EXT_extensions_string");
4181 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4183 if (allow_vsync)
4185 register_extension("WGL_EXT_swap_control");
4186 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4187 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4190 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4191 check for either, so register them separately. */
4192 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4193 register_extension("WGL_EXT_framebuffer_sRGB");
4195 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4196 register_extension("WGL_EXT_pixel_format_packed_float");
4199 * WINE-specific WGL Extensions
4202 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4203 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4205 register_extension("WGL_WINE_pixel_format_passthrough");
4206 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4208 register_extension("WGL_WINE_query_renderer");
4209 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4210 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4211 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4212 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4216 static void init_opengl(void)
4218 unsigned int i;
4220 TRACE("()\n");
4222 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4223 if (!dc_pbuffers)
4225 WARN("CFDictionaryCreateMutable failed\n");
4226 return;
4229 opengl_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD);
4230 if (!opengl_handle)
4232 ERR("Failed to load OpenGL: %s\n", dlerror());
4233 ERR("OpenGL support is disabled.\n");
4234 return;
4237 for (i = 0; i < ARRAY_SIZE(opengl_func_names); i++)
4239 if (!(((void **)&opengl_funcs.gl)[i] = dlsym(opengl_handle, opengl_func_names[i])))
4241 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4242 goto failed;
4246 if (!init_gl_info())
4247 goto failed;
4249 /* redirect some standard OpenGL functions */
4250 #define REDIRECT(func) \
4251 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4252 REDIRECT(glCopyPixels);
4253 REDIRECT(glGetString);
4254 REDIRECT(glReadPixels);
4255 REDIRECT(glViewport);
4256 if (skip_single_buffer_flushes || allow_vsync)
4257 REDIRECT(glFlush);
4258 if (allow_vsync)
4259 REDIRECT(glFinish);
4260 #undef REDIRECT
4262 /* redirect some OpenGL extension functions */
4263 #define REDIRECT(func) \
4264 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4265 REDIRECT(glCopyColorTable);
4266 #undef REDIRECT
4268 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4269 pglFlushRenderAPPLE = dlsym(opengl_handle, "glFlushRenderAPPLE");
4271 load_extensions();
4272 if (!init_pixel_formats())
4273 goto failed;
4275 return;
4277 failed:
4278 dlclose(opengl_handle);
4279 opengl_handle = NULL;
4283 /***********************************************************************
4284 * sync_gl_view
4286 * Synchronize the Mac GL view position with the Windows child window
4287 * position.
4289 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4291 if (data->client_cocoa_view && data->pixel_format)
4293 RECT old = *old_client_rect, new = data->client_rect;
4295 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4296 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4297 if (!EqualRect(&old, &new))
4299 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4300 mark_contexts_for_moved_view(data->client_cocoa_view);
4306 /**********************************************************************
4307 * macdrv_wglDescribePixelFormat
4309 static int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4311 const pixel_format *pf;
4312 const struct color_mode *mode;
4314 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4316 if (!descr) return nb_displayable_formats;
4317 if (size < sizeof(*descr)) return 0;
4319 if (!(pf = get_pixel_format(fmt, FALSE)))
4320 return 0;
4322 memset(descr, 0, sizeof(*descr));
4323 descr->nSize = sizeof(*descr);
4324 descr->nVersion = 1;
4326 descr->dwFlags = PFD_SUPPORT_OPENGL;
4327 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4328 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4329 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4330 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4331 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4333 descr->iPixelType = PFD_TYPE_RGBA;
4335 mode = &color_modes[pf->color_mode];
4336 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4337 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4338 R8G8B8A0 pixel format). If an app depends on that and expects that
4339 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4340 if (mode->alpha_bits)
4341 descr->cColorBits = mode->color_bits;
4342 else
4343 descr->cColorBits = mode->bits_per_pixel;
4344 descr->cRedBits = mode->red_bits;
4345 descr->cRedShift = mode->red_shift;
4346 descr->cGreenBits = mode->green_bits;
4347 descr->cGreenShift = mode->green_shift;
4348 descr->cBlueBits = mode->blue_bits;
4349 descr->cBlueShift = mode->blue_shift;
4350 descr->cAlphaBits = mode->alpha_bits;
4351 descr->cAlphaShift = mode->alpha_shift;
4353 if (pf->accum_mode)
4355 mode = &color_modes[pf->accum_mode - 1];
4356 descr->cAccumBits = mode->color_bits;
4357 descr->cAccumRedBits = mode->red_bits;
4358 descr->cAccumGreenBits = mode->green_bits;
4359 descr->cAccumBlueBits = mode->blue_bits;
4360 descr->cAccumAlphaBits = mode->alpha_bits;
4363 descr->cDepthBits = pf->depth_bits;
4364 descr->cStencilBits = pf->stencil_bits;
4365 descr->cAuxBuffers = pf->aux_buffers;
4366 descr->iLayerType = PFD_MAIN_PLANE;
4368 TRACE("%s\n", debugstr_pf(pf));
4369 return nb_displayable_formats;
4372 /***********************************************************************
4373 * macdrv_wglCopyContext
4375 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4377 CGLError err;
4379 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4381 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4382 if (err != kCGLNoError)
4383 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4384 return (err == kCGLNoError);
4387 /***********************************************************************
4388 * macdrv_wglCreateContext
4390 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
4392 struct wgl_context *context;
4394 TRACE("hdc %p\n", hdc);
4396 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4398 return context;
4401 /***********************************************************************
4402 * macdrv_wglDeleteContext
4404 static BOOL macdrv_wglDeleteContext(struct wgl_context *context)
4406 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4408 pthread_mutex_lock(&context_mutex);
4409 list_remove(&context->entry);
4410 pthread_mutex_unlock(&context_mutex);
4412 macdrv_dispose_opengl_context(context->context);
4413 free(context);
4414 return TRUE;
4417 /***********************************************************************
4418 * macdrv_wglGetPixelFormat
4420 static int macdrv_wglGetPixelFormat(HDC hdc)
4422 int format;
4423 HWND hwnd;
4425 if ((hwnd = NtUserWindowFromDC( hdc )))
4426 return win32u_get_window_pixel_format( hwnd );
4428 format = get_dc_pixel_format(NULL, hdc);
4430 if (!is_valid_pixel_format(format)) /* not set yet */
4431 format = 0;
4432 else if (!is_displayable_pixel_format(format))
4434 /* Non-displayable formats can't be used with traditional WGL calls.
4435 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4436 format = 1;
4439 TRACE(" hdc %p -> %d\n", hdc, format);
4440 return format;
4443 /***********************************************************************
4444 * macdrv_wglGetProcAddress
4446 static PROC macdrv_wglGetProcAddress(const char *proc)
4448 void *ret;
4450 if (!strncmp(proc, "wgl", 3)) return NULL;
4451 ret = dlsym(opengl_handle, proc);
4452 if (ret)
4454 if (TRACE_ON(wgl))
4456 Dl_info info;
4457 if (dladdr(ret, &info))
4458 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4459 else
4460 TRACE("%s -> %p (no library info)\n", proc, ret);
4463 else
4464 WARN("failed to find proc %s\n", debugstr_a(proc));
4465 return ret;
4468 /***********************************************************************
4469 * macdrv_wglMakeCurrent
4471 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4473 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4474 (context ? context->cglcontext : NULL));
4476 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4479 /**********************************************************************
4480 * macdrv_wglSetPixelFormat
4482 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4484 return set_pixel_format(hdc, fmt, FALSE);
4487 /***********************************************************************
4488 * macdrv_wglShareLists
4490 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4492 macdrv_opengl_context saved_context;
4493 CGLContextObj saved_cglcontext;
4495 TRACE("org %p dest %p\n", org, dest);
4497 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4498 * at context creation time but in case of WGL it is done using wglShareLists.
4500 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4501 * and when a program requests sharing we recreate the destination context if it hasn't been made
4502 * current or when it hasn't shared display lists before.
4505 if (dest->has_been_current)
4507 WARN("could not share display lists, the destination context has been current already\n");
4508 return FALSE;
4510 else if (dest->sharing)
4512 WARN("could not share display lists because dest has already shared lists before\n");
4513 return FALSE;
4516 /* Re-create the Mac context and share display lists */
4517 saved_context = dest->context;
4518 saved_cglcontext = dest->cglcontext;
4519 dest->context = NULL;
4520 dest->cglcontext = NULL;
4521 if (!create_context(dest, org->cglcontext, dest->major))
4523 dest->context = saved_context;
4524 dest->cglcontext = saved_cglcontext;
4525 return FALSE;
4528 /* Implicitly disposes of saved_cglcontext. */
4529 macdrv_dispose_opengl_context(saved_context);
4531 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4532 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4534 org->sharing = TRUE;
4535 dest->sharing = TRUE;
4537 return TRUE;
4540 /**********************************************************************
4541 * macdrv_wglSwapBuffers
4543 static BOOL macdrv_wglSwapBuffers(HDC hdc)
4545 struct wgl_context *context = NtCurrentTeb()->glContext;
4546 BOOL match = FALSE;
4547 HWND hwnd;
4549 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4550 (context ? context->cglcontext : NULL));
4552 if (context)
4554 sync_swap_interval(context);
4555 sync_context(context);
4558 if ((hwnd = NtUserWindowFromDC(hdc)))
4560 struct macdrv_win_data *data;
4562 if (!(data = get_win_data(hwnd)))
4564 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
4565 return FALSE;
4568 if (context && context->draw_view == data->client_cocoa_view)
4569 match = TRUE;
4571 release_win_data(data);
4573 else
4575 struct wgl_pbuffer *pbuffer;
4577 pthread_mutex_lock(&dc_pbuffers_mutex);
4578 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4579 pthread_mutex_unlock(&dc_pbuffers_mutex);
4581 if (!pbuffer)
4583 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
4584 return FALSE;
4587 if (context && context->draw_pbuffer == pbuffer)
4588 match = TRUE;
4591 if (match)
4592 macdrv_flush_opengl_context(context->context);
4593 else
4595 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4597 /* If there is a current context, then wglSwapBuffers should do an implicit
4598 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4599 in the other branch, but we have to do it explicitly here. */
4600 if (context)
4601 pglFlush();
4604 return TRUE;
4607 static struct opengl_funcs opengl_funcs =
4610 macdrv_wglCopyContext, /* p_wglCopyContext */
4611 macdrv_wglCreateContext, /* p_wglCreateContext */
4612 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4613 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4614 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4615 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4616 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4617 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4618 macdrv_wglShareLists, /* p_wglShareLists */
4619 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4623 /**********************************************************************
4624 * macdrv_wine_get_wgl_driver
4626 struct opengl_funcs *macdrv_wine_get_wgl_driver(UINT version)
4628 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
4630 if (version != WINE_WGL_DRIVER_VERSION)
4632 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4633 return NULL;
4636 pthread_once(&init_once, init_opengl);
4637 return opengl_handle ? &opengl_funcs : (void *)-1;