winemac: Use RtlSetLastWin32Error.
[wine.git] / dlls / winemac.drv / opengl.c
blob70b366def567e3bf7735bbfa2c23ed56835dcc03
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 DWORD 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(HDC hdc)
1334 int format;
1335 HWND hwnd;
1337 if ((hwnd = NtUserWindowFromDC(hdc)))
1339 struct macdrv_win_data *data;
1341 if (!(data = get_win_data(hwnd)))
1343 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1344 return 0;
1347 format = data->pixel_format;
1348 release_win_data(data);
1350 else
1352 struct wgl_pbuffer *pbuffer;
1354 pthread_mutex_lock(&dc_pbuffers_mutex);
1355 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1356 if (pbuffer)
1357 format = pbuffer->format;
1358 else
1360 WARN("no window or pbuffer for DC %p\n", hdc);
1361 format = 0;
1363 pthread_mutex_unlock(&dc_pbuffers_mutex);
1366 return format;
1370 /**********************************************************************
1371 * create_context
1373 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1375 const pixel_format *pf;
1376 CGLPixelFormatAttribute attribs[64];
1377 int n = 0;
1378 CGLPixelFormatObj pix;
1379 GLint virtualScreens;
1380 CGLError err;
1381 BOOL core = major >= 3;
1383 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1384 if (!pf)
1386 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1387 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
1388 return FALSE;
1391 attribs[n++] = kCGLPFAMinimumPolicy;
1392 attribs[n++] = kCGLPFAClosestPolicy;
1394 if (context->renderer_id)
1396 attribs[n++] = kCGLPFARendererID;
1397 attribs[n++] = context->renderer_id;
1398 attribs[n++] = kCGLPFASingleRenderer;
1399 attribs[n++] = kCGLPFANoRecovery;
1402 if (pf->accelerated)
1404 attribs[n++] = kCGLPFAAccelerated;
1405 attribs[n++] = kCGLPFANoRecovery;
1407 else
1409 attribs[n++] = kCGLPFARendererID;
1410 attribs[n++] = kCGLRendererGenericFloatID;
1413 if (pf->double_buffer)
1414 attribs[n++] = kCGLPFADoubleBuffer;
1416 if (!core)
1418 attribs[n++] = kCGLPFAAuxBuffers;
1419 attribs[n++] = pf->aux_buffers;
1422 attribs[n++] = kCGLPFAColorSize;
1423 attribs[n++] = color_modes[pf->color_mode].color_bits;
1424 attribs[n++] = kCGLPFAAlphaSize;
1425 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1426 if (color_modes[pf->color_mode].is_float)
1427 attribs[n++] = kCGLPFAColorFloat;
1429 attribs[n++] = kCGLPFADepthSize;
1430 attribs[n++] = pf->depth_bits;
1432 attribs[n++] = kCGLPFAStencilSize;
1433 attribs[n++] = pf->stencil_bits;
1435 if (pf->stereo)
1436 attribs[n++] = kCGLPFAStereo;
1438 if (pf->accum_mode && !core)
1440 attribs[n++] = kCGLPFAAccumSize;
1441 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1444 if (pf->pbuffer && !core)
1445 attribs[n++] = kCGLPFAPBuffer;
1447 if (pf->sample_buffers && pf->samples)
1449 attribs[n++] = kCGLPFASampleBuffers;
1450 attribs[n++] = pf->sample_buffers;
1451 attribs[n++] = kCGLPFASamples;
1452 attribs[n++] = pf->samples;
1455 if (pf->backing_store)
1456 attribs[n++] = kCGLPFABackingStore;
1458 if (core)
1460 attribs[n++] = kCGLPFAOpenGLProfile;
1461 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1462 if (major == 3)
1463 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1464 else
1465 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1466 #else
1467 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1468 #endif
1471 attribs[n] = 0;
1473 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1474 if (err != kCGLNoError || !pix)
1476 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1477 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1478 return FALSE;
1481 err = CGLCreateContext(pix, share, &context->cglcontext);
1482 CGLReleasePixelFormat(pix);
1483 if (err != kCGLNoError || !context->cglcontext)
1485 context->cglcontext = NULL;
1486 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1487 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1488 return FALSE;
1491 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1493 GLint opacity = 0;
1494 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1495 if (err != kCGLNoError)
1496 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1498 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1500 GLint order = -1;
1501 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1502 if (err != kCGLNoError)
1503 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1506 context->context = macdrv_create_opengl_context(context->cglcontext);
1507 CGLReleaseContext(context->cglcontext);
1508 if (!context->context)
1510 WARN("macdrv_create_opengl_context() failed\n");
1511 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
1512 return FALSE;
1514 context->major = major;
1516 InterlockedExchange(&context->update_swap_interval, TRUE);
1518 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1520 return TRUE;
1524 /**********************************************************************
1525 * set_pixel_format
1527 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1529 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1531 struct macdrv_win_data *data;
1532 const pixel_format *pf;
1533 HWND hwnd = NtUserWindowFromDC(hdc);
1534 BOOL ret = FALSE;
1536 TRACE("hdc %p format %d\n", hdc, fmt);
1538 if (!hwnd || hwnd == NtUserGetDesktopWindow())
1540 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1541 return FALSE;
1544 if (!(data = get_win_data(hwnd)))
1546 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1547 return FALSE;
1550 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1552 ret = (data->pixel_format == fmt);
1553 goto done;
1556 /* Check if fmt is in our list of supported formats to see if it is supported. */
1557 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1558 if (!pf)
1560 ERR("Invalid pixel format: %d\n", fmt);
1561 goto done;
1564 if (!pf->window)
1566 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1567 goto done;
1570 data->pixel_format = fmt;
1572 TRACE("pixel format:\n");
1573 TRACE(" window: %u\n", (unsigned int)pf->window);
1574 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1575 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1576 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1577 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1578 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1579 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1580 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1581 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1582 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1583 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1584 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1585 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1586 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1587 ret = TRUE;
1589 done:
1590 release_win_data(data);
1591 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) NtUserSetWindowPixelFormat(hwnd, fmt);
1592 return ret;
1596 /**********************************************************************
1597 * mark_contexts_for_moved_view
1599 static void mark_contexts_for_moved_view(macdrv_view view)
1601 struct wgl_context *context;
1603 pthread_mutex_lock(&context_mutex);
1604 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1606 if (context->draw_view == view)
1607 InterlockedExchange(&context->view_moved, TRUE);
1609 pthread_mutex_unlock(&context_mutex);
1613 /**********************************************************************
1614 * sync_context_rect
1616 static BOOL sync_context_rect(struct wgl_context *context)
1618 BOOL ret = FALSE;
1619 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1621 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1623 if (data && data->client_cocoa_view == context->draw_view)
1625 RECT rect = data->client_rect;
1626 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1627 if (!EqualRect(&context->draw_rect, &rect))
1629 context->draw_rect = rect;
1630 ret = TRUE;
1633 release_win_data(data);
1635 return ret;
1639 /**********************************************************************
1640 * make_context_current
1642 static void make_context_current(struct wgl_context *context, BOOL read)
1644 macdrv_view view;
1645 RECT view_rect;
1646 struct wgl_pbuffer *pbuffer;
1648 if (read)
1650 view = context->read_view;
1651 view_rect = context->read_rect;
1652 pbuffer = context->read_pbuffer;
1654 else
1656 sync_context_rect(context);
1658 view = context->draw_view;
1659 view_rect = context->draw_rect;
1660 pbuffer = context->draw_pbuffer;
1663 if (view || !pbuffer)
1664 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1665 else
1667 GLint enabled;
1669 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1670 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1671 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1672 pbuffer->level, 0);
1673 CGLSetCurrentContext(context->cglcontext);
1678 /**********************************************************************
1679 * sync_context
1681 static void sync_context(struct wgl_context *context)
1683 if (sync_context_rect(context))
1684 make_context_current(context, FALSE);
1688 /**********************************************************************
1689 * set_swap_interval
1691 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1693 CGLError err;
1695 /* In theory, for single-buffered contexts, there's no such thing as a swap
1696 so the swap interval shouldn't matter. But OS X will synchronize flushes
1697 of single-buffered contexts if the interval is set to non-zero. */
1698 if (interval && !pixel_formats[context->format - 1].double_buffer)
1699 interval = 0;
1701 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1702 if (err != kCGLNoError)
1703 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1705 return err == kCGLNoError;
1709 /**********************************************************************
1710 * sync_swap_interval
1712 static void sync_swap_interval(struct wgl_context *context)
1714 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1716 int interval;
1718 if (!allow_vsync)
1719 interval = 0;
1720 else if (context->draw_hwnd)
1722 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1723 if (data)
1725 interval = data->swap_interval;
1726 release_win_data(data);
1728 else /* window was destroyed? */
1729 interval = 1;
1731 else /* pbuffer */
1732 interval = 0;
1734 set_swap_interval(context, interval);
1739 /**********************************************************************
1740 * get_iokit_display_property
1742 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1744 GLint accelerated;
1745 GLint display_mask;
1746 int i;
1748 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1750 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1751 return FALSE;
1754 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1756 WARN("failed to get kCGLRPDisplayMask\n");
1757 return FALSE;
1760 for (i = 0; i < sizeof(GLint) * 8; i++)
1762 GLint this_display_mask = (GLint)(1U << i);
1763 if (this_display_mask & display_mask)
1765 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1766 io_service_t service;
1767 CFDataRef data;
1768 uint32_t prop_value;
1770 if (!display_id)
1771 continue;
1772 service = CGDisplayIOServicePort(display_id);
1773 if (!service)
1775 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1776 continue;
1779 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1780 kIORegistryIterateRecursively | kIORegistryIterateParents);
1781 if (!data)
1783 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1784 continue;
1786 if (CFGetTypeID(data) != CFDataGetTypeID())
1788 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1789 CFRelease(data);
1790 continue;
1792 if (CFDataGetLength(data) != sizeof(prop_value))
1794 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1795 (unsigned long long)CFDataGetLength(data));
1796 CFRelease(data);
1797 continue;
1800 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1801 CFRelease(data);
1802 *value = prop_value;
1803 return TRUE;
1807 return FALSE;
1811 /**********************************************************************
1812 * create_pixel_format_for_renderer
1814 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1815 * responsible for releasing the pixel format object.
1817 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1819 GLint renderer_id;
1820 CGLPixelFormatAttribute attrs[] = {
1821 kCGLPFARendererID, 0,
1822 kCGLPFASingleRenderer,
1823 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1826 CGError err;
1827 CGLPixelFormatObj pixel_format;
1828 GLint virtual_screens;
1830 if (core)
1832 attrs[3] = kCGLPFAOpenGLProfile;
1833 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1836 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1837 return NULL;
1839 attrs[1] = renderer_id;
1840 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1841 if (err != kCGLNoError)
1842 pixel_format = NULL;
1843 return pixel_format;
1847 /**********************************************************************
1848 * map_renderer_index
1850 * We can't create pixel formats for all renderers listed. For example,
1851 * in a dual-GPU system, the integrated GPU is typically unavailable
1852 * when the discrete GPU is active.
1854 * This function conceptually creates a list of "good" renderers from the
1855 * list of all renderers. It treats the input "renderer" parameter as an
1856 * index into that list of good renderers and returns the corresponding
1857 * index into the list of all renderers.
1859 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1861 GLint good_count, i;
1863 good_count = 0;
1864 for (i = 0; i < renderer_count; i++)
1866 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1867 if (pix)
1869 CGLReleasePixelFormat(pix);
1870 good_count++;
1871 if (good_count > renderer)
1872 break;
1874 else
1875 TRACE("skipping bad renderer %d\n", i);
1878 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1879 return i;
1883 /**********************************************************************
1884 * get_gl_string
1886 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1888 const char* ret = NULL;
1889 CGLContextObj context, old_context;
1890 CGLError err;
1892 err = CGLCreateContext(pixel_format, NULL, &context);
1893 if (err == kCGLNoError && context)
1895 old_context = CGLGetCurrentContext();
1896 err = CGLSetCurrentContext(context);
1897 if (err == kCGLNoError)
1899 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1900 CGLSetCurrentContext(old_context);
1902 else
1903 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1904 CGLReleaseContext(context);
1906 else
1907 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1909 return ret;
1913 /**********************************************************************
1914 * get_fallback_renderer_version
1916 static void get_fallback_renderer_version(GLuint *value)
1918 BOOL got_it = FALSE;
1919 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1920 kCFURLPOSIXPathStyle, TRUE);
1921 if (url)
1923 CFBundleRef bundle = CFBundleCreate(NULL, url);
1924 CFRelease(url);
1925 if (bundle)
1927 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1928 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1930 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1931 char* buf = malloc(len);
1932 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1934 unsigned int major, minor, bugfix;
1935 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1936 if (count >= 2)
1938 value[0] = major;
1939 value[1] = minor;
1940 if (count == 3)
1941 value[2] = bugfix;
1942 else
1943 value[2] = 0;
1944 got_it = TRUE;
1947 free(buf);
1949 CFRelease(bundle);
1953 if (!got_it)
1955 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1956 earliest version that the Mac driver supports. */
1957 value[0] = 1;
1958 value[1] = 6;
1959 value[2] = 14;
1964 /**********************************************************************
1965 * parse_renderer_version
1967 * Get the renderer version from the OpenGL version string. Assumes
1968 * the string is of the form
1969 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1970 * where major, minor, and bugfix are what we're interested in. This
1971 * form for the vendor specific information is not generally applicable,
1972 * but seems reliable on OS X.
1974 static BOOL parse_renderer_version(const char* version, GLuint *value)
1976 const char* p = strchr(version, ' ');
1977 int count;
1978 unsigned int major, minor, bugfix;
1980 if (p) p = strchr(p + 1, '-');
1981 if (!p) return FALSE;
1983 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
1984 if (count < 2)
1985 return FALSE;
1987 value[0] = major;
1988 value[1] = minor;
1989 if (count == 3)
1990 value[2] = bugfix;
1991 else
1992 value[2] = 0;
1994 return TRUE;
1998 /**********************************************************************
1999 * query_renderer_integer
2001 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2003 BOOL ret = FALSE;
2004 CGLError err;
2006 if (TRACE_ON(wgl))
2008 GLint renderer_id;
2009 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2010 renderer_id = 0;
2011 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2014 switch (attribute)
2016 case WGL_RENDERER_ACCELERATED_WINE:
2017 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2018 break;
2019 *value = !!*value;
2020 ret = TRUE;
2021 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2022 break;
2024 case WGL_RENDERER_DEVICE_ID_WINE:
2025 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2026 if (!ret)
2028 *value = 0xffffffff;
2029 ret = TRUE;
2031 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2032 break;
2034 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2035 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2037 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2038 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2040 if (pixel_format)
2042 const char* version = get_gl_string(pixel_format, GL_VERSION);
2044 CGLReleasePixelFormat(pixel_format);
2045 if (version)
2047 unsigned int major, minor;
2049 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2051 value[0] = major;
2052 value[1] = minor;
2053 ret = TRUE;
2058 if (!ret)
2060 value[0] = value[1] = 0;
2061 ret = TRUE;
2063 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2064 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2065 break;
2068 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2070 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2072 if (pixel_format)
2074 CGLReleasePixelFormat(pixel_format);
2075 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2076 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2078 else
2080 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2081 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2083 ret = TRUE;
2084 break;
2087 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2088 /* FIXME: no API to query this */
2089 *value = 0;
2090 ret = TRUE;
2091 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2092 break;
2094 case WGL_RENDERER_VENDOR_ID_WINE:
2095 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2096 if (!ret)
2098 *value = 0xffffffff;
2099 ret = TRUE;
2101 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2102 break;
2104 case WGL_RENDERER_VERSION_WINE:
2106 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2108 if (!pixel_format)
2109 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2110 if (pixel_format)
2112 const char* version = get_gl_string(pixel_format, GL_VERSION);
2114 CGLReleasePixelFormat(pixel_format);
2115 if (version)
2116 ret = parse_renderer_version(version, value);
2119 if (!ret)
2121 get_fallback_renderer_version(value);
2122 ret = TRUE;
2124 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2125 break;
2128 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2129 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2130 if (err != kCGLNoError && err != kCGLBadProperty)
2131 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2132 if (err != kCGLNoError)
2134 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2135 *value /= 1024 * 1024;
2136 else
2137 *value = 0;
2139 ret = TRUE;
2140 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2141 break;
2143 default:
2144 FIXME("unrecognized attribute 0x%04x\n", attribute);
2145 break;
2148 return ret;
2152 /**********************************************************************
2153 * macdrv_glCopyColorTable
2155 * Hook into glCopyColorTable as part of the implementation of
2156 * wglMakeContextCurrentARB. If the context has a separate readable,
2157 * temporarily make that current, do glCopyColorTable, and then set it
2158 * back to the drawable. This is modeled after what Mesa GLX's Apple
2159 * implementation does.
2161 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2162 GLsizei width)
2164 struct wgl_context *context = NtCurrentTeb()->glContext;
2166 if (context->read_view || context->read_pbuffer)
2167 make_context_current(context, TRUE);
2169 pglCopyColorTable(target, internalformat, x, y, width);
2171 if (context->read_view || context->read_pbuffer)
2172 make_context_current(context, FALSE);
2176 /**********************************************************************
2177 * macdrv_glCopyPixels
2179 * Hook into glCopyPixels as part of the implementation of
2180 * wglMakeContextCurrentARB. If the context has a separate readable,
2181 * temporarily make that current, do glCopyPixels, and then set it back
2182 * to the drawable. This is modeled after what Mesa GLX's Apple
2183 * implementation does.
2185 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2187 struct wgl_context *context = NtCurrentTeb()->glContext;
2189 if (context->read_view || context->read_pbuffer)
2190 make_context_current(context, TRUE);
2192 pglCopyPixels(x, y, width, height, type);
2194 if (context->read_view || context->read_pbuffer)
2195 make_context_current(context, FALSE);
2199 /**********************************************************************
2200 * macdrv_glFinish
2202 static void macdrv_glFinish(void)
2204 struct wgl_context *context = NtCurrentTeb()->glContext;
2206 sync_swap_interval(context);
2207 sync_context(context);
2208 pglFinish();
2212 /**********************************************************************
2213 * macdrv_glFlush
2215 static void macdrv_glFlush(void)
2217 struct wgl_context *context = NtCurrentTeb()->glContext;
2219 sync_swap_interval(context);
2220 sync_context(context);
2222 if (skip_single_buffer_flushes)
2224 const pixel_format *pf = &pixel_formats[context->format - 1];
2225 DWORD now = NtGetTickCount();
2227 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2228 context->last_flush_time, now);
2229 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2231 TRACE("calling glFlushRenderAPPLE()\n");
2232 pglFlushRenderAPPLE();
2233 return;
2235 else
2237 TRACE("calling glFlush()\n");
2238 context->last_flush_time = now;
2242 pglFlush();
2246 /**********************************************************************
2247 * macdrv_glGetString
2249 * Hook into glGetString in order to return some legacy WGL extensions
2250 * that couldn't be advertised via the standard
2251 * WGL_ARB_extensions_string mechanism. Some programs, especially
2252 * older ones, expect to find certain older extensions, such as
2253 * WGL_EXT_extensions_string itself, in the standard GL extensions
2254 * string, and won't query any other WGL extensions unless they find
2255 * that particular extension there.
2257 static const GLubyte *macdrv_glGetString(GLenum name)
2259 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2260 return (const GLubyte *)gl_info.glExtensions;
2261 else
2262 return pglGetString(name);
2266 /**********************************************************************
2267 * macdrv_glReadPixels
2269 * Hook into glReadPixels as part of the implementation of
2270 * wglMakeContextCurrentARB. If the context has a separate readable,
2271 * temporarily make that current, do glReadPixels, and then set it back
2272 * to the drawable. This is modeled after what Mesa GLX's Apple
2273 * implementation does.
2275 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2276 GLenum format, GLenum type, void *pixels)
2278 struct wgl_context *context = NtCurrentTeb()->glContext;
2280 if (context->read_view || context->read_pbuffer)
2281 make_context_current(context, TRUE);
2283 pglReadPixels(x, y, width, height, format, type, pixels);
2285 if (context->read_view || context->read_pbuffer)
2286 make_context_current(context, FALSE);
2290 /**********************************************************************
2291 * macdrv_glViewport
2293 * Hook into glViewport as an opportunity to update the OpenGL context
2294 * if necessary. This is modeled after what Mesa GLX's Apple
2295 * implementation does.
2297 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2299 struct wgl_context *context = NtCurrentTeb()->glContext;
2301 sync_context(context);
2302 macdrv_update_opengl_context(context->context);
2303 pglViewport(x, y, width, height);
2307 /***********************************************************************
2308 * macdrv_wglBindTexImageARB
2310 * WGL_ARB_render_texture: wglBindTexImageARB
2312 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2314 struct wgl_context *context = NtCurrentTeb()->glContext;
2315 GLenum source;
2316 CGLError err;
2318 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2320 if (pbuffer->no_texture)
2322 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
2323 return GL_FALSE;
2326 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2327 opengl_funcs.gl.p_glFlush();
2329 switch (iBuffer)
2331 case WGL_FRONT_LEFT_ARB:
2332 if (pixel_formats[pbuffer->format - 1].stereo)
2333 source = GL_FRONT_LEFT;
2334 else
2335 source = GL_FRONT;
2336 break;
2337 case WGL_FRONT_RIGHT_ARB:
2338 source = GL_FRONT_RIGHT;
2339 break;
2340 case WGL_BACK_LEFT_ARB:
2341 if (pixel_formats[pbuffer->format - 1].stereo)
2342 source = GL_BACK_LEFT;
2343 else
2344 source = GL_BACK;
2345 break;
2346 case WGL_BACK_RIGHT_ARB:
2347 source = GL_BACK_RIGHT;
2348 break;
2349 case WGL_AUX0_ARB: source = GL_AUX0; break;
2350 case WGL_AUX1_ARB: source = GL_AUX1; break;
2351 case WGL_AUX2_ARB: source = GL_AUX2; break;
2352 case WGL_AUX3_ARB: source = GL_AUX3; break;
2354 case WGL_AUX4_ARB:
2355 case WGL_AUX5_ARB:
2356 case WGL_AUX6_ARB:
2357 case WGL_AUX7_ARB:
2358 case WGL_AUX8_ARB:
2359 case WGL_AUX9_ARB:
2360 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2361 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2362 return GL_FALSE;
2364 default:
2365 WARN("unknown source buffer 0x%x\n", iBuffer);
2366 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2367 return GL_FALSE;
2370 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2371 if (err != kCGLNoError)
2373 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2374 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
2375 return GL_FALSE;
2378 return GL_TRUE;
2382 /***********************************************************************
2383 * macdrv_wglChoosePixelFormatARB
2385 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2387 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2388 const FLOAT *pfAttribFList, UINT nMaxFormats,
2389 int *piFormats, UINT *nNumFormats)
2391 pixel_format pf, valid;
2392 const int *iptr;
2393 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2394 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2395 int float_color;
2396 BOOL srgb;
2397 int i, found = 0;
2399 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2400 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2401 if (pfAttribFList)
2402 FIXME("unused pfAttribFList\n");
2404 memset(&pf, 0, sizeof(pf));
2405 memset(&valid, 0, sizeof(valid));
2406 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2407 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2408 float_color = -1;
2409 srgb = FALSE;
2411 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2413 int attr = iptr[0];
2414 int value = iptr[1];
2416 TRACE("%s\n", debugstr_attrib(attr, value));
2418 switch (attr)
2420 case WGL_DRAW_TO_WINDOW_ARB:
2421 if (valid.window && (!pf.window != !value)) goto cant_match;
2422 pf.window = (value != 0);
2423 valid.window = 1;
2424 break;
2426 case WGL_DRAW_TO_BITMAP_ARB:
2427 goto cant_match;
2429 case WGL_ACCELERATION_ARB:
2430 if (value == WGL_FULL_ACCELERATION_ARB)
2431 value = 1;
2432 else if (value == WGL_NO_ACCELERATION_ARB)
2433 value = 0;
2434 else
2435 goto cant_match;
2436 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2437 pf.accelerated = value;
2438 valid.accelerated = 1;
2439 break;
2441 case WGL_NEED_PALETTE_ARB:
2442 case WGL_NEED_SYSTEM_PALETTE_ARB:
2443 case WGL_SWAP_LAYER_BUFFERS_ARB:
2444 if (value) goto cant_match;
2445 break;
2447 case WGL_SWAP_METHOD_ARB:
2448 if (value == WGL_SWAP_COPY_ARB)
2449 value = 1;
2450 else if (value == WGL_SWAP_UNDEFINED_ARB)
2451 value = 0;
2452 else
2453 goto cant_match;
2454 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2455 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2456 pf.backing_store = value;
2457 valid.backing_store = 1;
2458 break;
2460 case WGL_NUMBER_OVERLAYS_ARB:
2461 case WGL_NUMBER_UNDERLAYS_ARB:
2462 if (value) goto cant_match;
2463 break;
2465 case WGL_SHARE_DEPTH_ARB:
2466 case WGL_SHARE_STENCIL_ARB:
2467 case WGL_SHARE_ACCUM_ARB:
2468 /* no effect */
2469 break;
2471 case WGL_SUPPORT_GDI_ARB:
2472 if (value) goto cant_match;
2473 break;
2475 case WGL_SUPPORT_OPENGL_ARB:
2476 if (!value) goto cant_match;
2477 break;
2479 case WGL_DOUBLE_BUFFER_ARB:
2480 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2481 pf.double_buffer = (value != 0);
2482 valid.double_buffer = 1;
2483 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2484 break;
2486 case WGL_STEREO_ARB:
2487 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2488 pf.stereo = (value != 0);
2489 valid.stereo = 1;
2490 break;
2492 case WGL_PIXEL_TYPE_ARB:
2493 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2494 value = 1;
2495 else if (value == WGL_TYPE_RGBA_ARB)
2496 value = 0;
2497 else
2499 /* Mac contexts don't support rendering to unsigned floating
2500 point formats, even if GL_EXT_packed_float is supported.
2501 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2502 goto cant_match;
2504 if (float_color != -1 && float_color != value) goto cant_match;
2505 if (srgb && value) goto cant_match;
2506 float_color = value;
2507 break;
2509 case WGL_COLOR_BITS_ARB:
2510 if (color_bits < value) color_bits = value;
2511 break;
2513 case WGL_RED_BITS_ARB:
2514 if (srgb && value > 8) goto cant_match;
2515 if (red_bits < value) red_bits = value;
2516 break;
2518 case WGL_GREEN_BITS_ARB:
2519 if (srgb && value > 8) goto cant_match;
2520 if (green_bits < value) green_bits = value;
2521 break;
2523 case WGL_BLUE_BITS_ARB:
2524 if (srgb && value > 8) goto cant_match;
2525 if (blue_bits < value) blue_bits = value;
2526 break;
2528 case WGL_ALPHA_BITS_ARB:
2529 if (alpha_bits < value) alpha_bits = value;
2530 break;
2532 case WGL_ACCUM_BITS_ARB:
2533 if (accum_bits < value) accum_bits = value;
2534 break;
2536 case WGL_ACCUM_RED_BITS_ARB:
2537 if (accum_red_bits < value) accum_red_bits = value;
2538 break;
2540 case WGL_ACCUM_GREEN_BITS_ARB:
2541 if (accum_green_bits < value) accum_green_bits = value;
2542 break;
2544 case WGL_ACCUM_BLUE_BITS_ARB:
2545 if (accum_blue_bits < value) accum_blue_bits = value;
2546 break;
2548 case WGL_ACCUM_ALPHA_BITS_ARB:
2549 if (accum_alpha_bits < value) accum_alpha_bits = value;
2550 break;
2552 case WGL_DEPTH_BITS_ARB:
2553 if (value > 255) goto cant_match;
2554 if (pf.depth_bits < value) pf.depth_bits = value;
2555 break;
2557 case WGL_STENCIL_BITS_ARB:
2558 if (value > 255) goto cant_match;
2559 if (pf.stencil_bits < value) pf.stencil_bits = value;
2560 break;
2562 case WGL_AUX_BUFFERS_ARB:
2563 if (value > 7) goto cant_match;
2564 if (pf.aux_buffers < value) pf.aux_buffers = value;
2565 break;
2567 case WGL_SAMPLE_BUFFERS_ARB:
2568 if (value > 1) goto cant_match;
2569 if (pf.sample_buffers < value) pf.sample_buffers = value;
2570 break;
2572 case WGL_SAMPLES_ARB:
2573 if (value > 31) goto cant_match;
2574 if (pf.samples < value) pf.samples = value;
2575 break;
2577 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2578 /* sRGB is only supported for 8-bit integer color components */
2579 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2580 goto cant_match;
2581 srgb = TRUE;
2582 break;
2584 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2585 case WGL_RED_SHIFT_ARB:
2586 case WGL_GREEN_SHIFT_ARB:
2587 case WGL_BLUE_SHIFT_ARB:
2588 case WGL_ALPHA_SHIFT_ARB:
2589 case WGL_TRANSPARENT_ARB:
2590 case WGL_TRANSPARENT_RED_VALUE_ARB:
2591 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2592 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2593 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2594 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2595 /* ignored */
2596 break;
2598 case WGL_DRAW_TO_PBUFFER_ARB:
2599 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2600 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2601 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2602 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2603 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2604 pf.pbuffer = (value != 0);
2605 valid.pbuffer = 1;
2606 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2607 !alpha_bits)
2608 alpha_bits = 1;
2609 break;
2611 default:
2612 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2613 return GL_FALSE;
2617 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",
2618 valid.window ? (pf.window ? "1" : "0") : "?",
2619 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2620 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2621 color_bits,
2622 float_color == -1 ? "?" : float_color ? "f" : "",
2623 red_bits,
2624 green_bits,
2625 blue_bits,
2626 alpha_bits,
2627 (int)srgb,
2628 accum_bits,
2629 accum_red_bits,
2630 accum_green_bits,
2631 accum_blue_bits,
2632 accum_alpha_bits,
2633 pf.depth_bits,
2634 pf.stencil_bits,
2635 pf.aux_buffers,
2636 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2637 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2638 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2639 pf.sample_buffers,
2640 pf.samples);
2642 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2644 const struct color_mode *mode;
2646 if (valid.window && pixel_formats[i].window != pf.window) continue;
2647 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2648 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2649 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2650 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2651 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2653 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2654 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2655 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2656 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2657 if (pixel_formats[i].samples < pf.samples) continue;
2659 mode = &color_modes[pixel_formats[i].color_mode];
2660 /* If the mode doesn't have alpha, check requested color bits against
2661 bits per pixel instead of the mode's color bits. On Windows, color
2662 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2663 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2664 expects that to match such a pixel format, we need to accommodate that. */
2665 if (mode->alpha_bits)
2667 if (mode->color_bits < color_bits)
2668 continue;
2670 else
2672 if (mode->bits_per_pixel < color_bits)
2673 continue;
2675 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2676 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2677 continue;
2678 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2679 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2680 continue;
2682 if (pixel_formats[i].accum_mode)
2684 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2685 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2686 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2687 mode->alpha_bits < accum_alpha_bits)
2688 continue;
2690 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2691 continue;
2693 piFormats[found++] = i + 1;
2694 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2697 cant_match:
2698 *nNumFormats = found;
2700 return TRUE;
2704 /***********************************************************************
2705 * macdrv_wglCreateContextAttribsARB
2707 * WGL_ARB_create_context: wglCreateContextAttribsARB
2709 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2710 struct wgl_context *share_context,
2711 const int *attrib_list)
2713 int format;
2714 struct wgl_context *context;
2715 const int *iptr;
2716 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2717 BOOL core = FALSE;
2718 GLint renderer_id = 0;
2720 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2722 format = get_dc_pixel_format(hdc);
2724 if (!is_valid_pixel_format(format))
2726 ERR("Invalid pixel format %d, expect problems!\n", format);
2727 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
2728 return NULL;
2731 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2733 int attr = iptr[0];
2734 int value = iptr[1];
2736 TRACE("%s\n", debugstr_attrib(attr, value));
2738 switch (attr)
2740 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2741 major = value;
2742 break;
2744 case WGL_CONTEXT_MINOR_VERSION_ARB:
2745 minor = value;
2746 break;
2748 case WGL_CONTEXT_LAYER_PLANE_ARB:
2749 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2750 break;
2752 case WGL_CONTEXT_FLAGS_ARB:
2753 flags = value;
2754 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2755 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2756 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2757 break;
2759 case WGL_CONTEXT_PROFILE_MASK_ARB:
2760 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2761 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2763 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2764 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2765 return NULL;
2767 profile = value;
2768 break;
2770 case WGL_RENDERER_ID_WINE:
2772 CGLError err;
2773 CGLRendererInfoObj renderer_info;
2774 GLint renderer_count, temp;
2776 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2777 if (err != kCGLNoError)
2779 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2780 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
2781 return NULL;
2784 value = map_renderer_index(renderer_info, renderer_count, value);
2786 if (value >= renderer_count)
2788 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2789 CGLDestroyRendererInfo(renderer_info);
2790 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2791 return NULL;
2794 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2796 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2797 CGLDestroyRendererInfo(renderer_info);
2798 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
2799 return NULL;
2802 CGLDestroyRendererInfo(renderer_info);
2804 if (renderer_id && temp != renderer_id)
2806 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2807 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2808 return NULL;
2810 renderer_id = temp;
2811 break;
2814 default:
2815 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2816 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);
2817 return NULL;
2821 if ((major == 3 && (minor == 2 || minor == 3)) ||
2822 (major == 4 && (minor == 0 || minor == 1)))
2824 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2826 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2827 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2828 return NULL;
2830 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2832 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2833 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2834 return NULL;
2836 if (major > gl_info.max_major ||
2837 (major == gl_info.max_major && minor > gl_info.max_minor))
2839 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2840 major, minor);
2841 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB);
2842 return NULL;
2844 core = TRUE;
2846 else if (major >= 3)
2848 WARN("Profile version %u.%u not supported\n", major, minor);
2849 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2850 return NULL;
2852 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2853 (major == 2 && (minor < 0 || minor > 1)))
2855 WARN("Invalid GL version requested\n");
2856 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2857 return NULL;
2859 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2861 WARN("Forward compatible context requested for GL version < 3\n");
2862 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB);
2863 return NULL;
2866 if (!(context = calloc(1, sizeof(*context)))) return NULL;
2868 context->format = format;
2869 context->renderer_id = renderer_id;
2870 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2872 free(context);
2873 return NULL;
2876 pthread_mutex_lock(&context_mutex);
2877 list_add_tail(&context_list, &context->entry);
2878 pthread_mutex_unlock(&context_mutex);
2880 return context;
2884 /**********************************************************************
2885 * macdrv_wglCreatePbufferARB
2887 * WGL_ARB_pbuffer: wglCreatePbufferARB
2889 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2890 const int *piAttribList)
2892 struct wgl_pbuffer* pbuffer;
2893 GLenum target = 0;
2894 GLenum internalFormat = 0;
2895 CGLError err;
2897 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2898 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2900 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2902 WARN("invalid pixel format %d\n", iPixelFormat);
2903 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
2904 return NULL;
2907 pbuffer = calloc(1, sizeof(*pbuffer));
2908 pbuffer->format = iPixelFormat;
2910 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2912 int attr = piAttribList[0];
2913 int value = piAttribList[1];
2915 switch (attr)
2917 case WGL_PBUFFER_LARGEST_ARB:
2918 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2919 break;
2921 case WGL_TEXTURE_FORMAT_ARB:
2922 switch (value)
2924 case WGL_TEXTURE_RGBA_ARB:
2925 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2926 internalFormat = GL_RGBA;
2927 break;
2928 case WGL_TEXTURE_RGB_ARB:
2929 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2930 internalFormat = GL_RGB;
2931 break;
2932 case WGL_NO_TEXTURE_ARB:
2933 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2934 internalFormat = 0;
2935 break;
2936 default:
2937 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2938 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2939 goto done;
2941 break;
2943 case WGL_TEXTURE_TARGET_ARB:
2944 pbuffer->face = 0;
2945 switch (value)
2947 case WGL_NO_TEXTURE_ARB:
2948 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2949 target = 0;
2950 break;
2951 case WGL_TEXTURE_CUBE_MAP_ARB:
2952 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2953 target = GL_TEXTURE_CUBE_MAP;
2954 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2955 break;
2956 case WGL_TEXTURE_1D_ARB:
2957 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2958 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
2959 goto done;
2960 case WGL_TEXTURE_2D_ARB:
2961 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2962 target = GL_TEXTURE_2D;
2963 break;
2964 case WGL_TEXTURE_RECTANGLE_NV:
2965 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2966 target = GL_TEXTURE_RECTANGLE;
2967 break;
2968 default:
2969 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2970 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2971 goto done;
2973 break;
2975 case WGL_MIPMAP_TEXTURE_ARB:
2976 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2977 pbuffer->max_level = 0;
2978 if (value)
2980 int size = min(iWidth, iHeight) / 2;
2981 while (size)
2983 pbuffer->max_level++;
2984 size /= 2;
2987 break;
2989 default:
2990 WARN("unknown attribute 0x%x\n", attr);
2991 RtlSetLastWin32Error(ERROR_INVALID_DATA);
2992 goto done;
2996 if (!target || !internalFormat)
2998 pbuffer->no_texture = TRUE;
2999 /* no actual way to turn off ability to texture; use most permissive target */
3000 target = GL_TEXTURE_RECTANGLE;
3001 internalFormat = GL_RGB;
3004 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3005 if (err != kCGLNoError)
3007 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3008 pbuffer->pbuffer = NULL;
3009 if (err == kCGLBadAlloc)
3010 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
3011 else
3012 RtlSetLastWin32Error(ERROR_INVALID_DATA);
3015 done:
3016 if (!pbuffer->pbuffer)
3018 free(pbuffer);
3019 return NULL;
3022 TRACE(" -> %p\n", pbuffer);
3023 return pbuffer;
3027 /**********************************************************************
3028 * macdrv_wglDestroyPbufferARB
3030 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3032 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3034 TRACE("pbuffer %p\n", pbuffer);
3035 if (pbuffer && pbuffer->pbuffer)
3036 CGLReleasePBuffer(pbuffer->pbuffer);
3037 free(pbuffer);
3038 return GL_TRUE;
3042 /**********************************************************************
3043 * macdrv_wglGetExtensionsStringARB
3045 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3047 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3049 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3050 this can be specific to the CGL renderer like we're supposed to do. */
3051 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3052 return gl_info.wglExtensions;
3056 /**********************************************************************
3057 * macdrv_wglGetExtensionsStringEXT
3059 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3061 static const char *macdrv_wglGetExtensionsStringEXT(void)
3063 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3064 return gl_info.wglExtensions;
3068 /**********************************************************************
3069 * macdrv_wglGetPbufferDCARB
3071 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3073 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3075 HDC hdc;
3076 struct wgl_pbuffer *prev;
3078 hdc = NtGdiOpenDCW(NULL, NULL, NULL, 0, TRUE, NULL, NULL, NULL);
3079 if (!hdc) return 0;
3081 pthread_mutex_lock(&dc_pbuffers_mutex);
3082 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3083 if (prev)
3085 CGLReleasePBuffer(prev->pbuffer);
3086 free(prev);
3088 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3089 pthread_mutex_unlock(&dc_pbuffers_mutex);
3091 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3092 return hdc;
3096 /**********************************************************************
3097 * macdrv_wglGetPixelFormatAttribivARB
3099 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3101 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3102 UINT nAttributes, const int *piAttributes, int *piValues)
3104 const pixel_format *pf;
3105 UINT i;
3107 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3108 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3110 if (!nAttributes) return GL_TRUE;
3112 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3114 piValues[0] = nb_formats;
3115 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3116 return GL_TRUE;
3119 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3120 if (!pf)
3122 WARN("invalid pixel format %d\n", iPixelFormat);
3123 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3124 return GL_FALSE;
3127 for (i = 0; i < nAttributes; ++i)
3129 switch (piAttributes[i])
3131 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3132 piValues[i] = nb_formats;
3133 break;
3135 case WGL_DRAW_TO_WINDOW_ARB:
3136 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3137 break;
3139 case WGL_DRAW_TO_BITMAP_ARB:
3140 piValues[i] = GL_FALSE;
3141 break;
3143 case WGL_ACCELERATION_ARB:
3144 if (iLayerPlane) goto invalid_layer;
3145 if (pf->accelerated)
3146 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3147 else
3148 piValues[i] = WGL_NO_ACCELERATION_ARB;
3149 break;
3151 case WGL_NEED_PALETTE_ARB:
3152 case WGL_NEED_SYSTEM_PALETTE_ARB:
3153 case WGL_SWAP_LAYER_BUFFERS_ARB:
3154 piValues[i] = GL_FALSE;
3155 break;
3157 case WGL_SWAP_METHOD_ARB:
3158 if (pf->double_buffer && pf->backing_store)
3159 piValues[i] = WGL_SWAP_COPY_ARB;
3160 else
3161 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3162 break;
3164 case WGL_NUMBER_OVERLAYS_ARB:
3165 case WGL_NUMBER_UNDERLAYS_ARB:
3166 piValues[i] = 0;
3167 break;
3169 case WGL_TRANSPARENT_ARB:
3170 if (iLayerPlane) goto invalid_layer;
3171 piValues[i] = GL_FALSE;
3172 break;
3174 case WGL_TRANSPARENT_RED_VALUE_ARB:
3175 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3176 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3177 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3178 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3179 if (iLayerPlane) goto invalid_layer;
3180 piValues[i] = 0;
3181 break;
3183 case WGL_SHARE_DEPTH_ARB:
3184 case WGL_SHARE_STENCIL_ARB:
3185 case WGL_SHARE_ACCUM_ARB:
3186 if (iLayerPlane) goto invalid_layer;
3187 piValues[i] = GL_TRUE;
3188 break;
3190 case WGL_SUPPORT_GDI_ARB:
3191 if (iLayerPlane) goto invalid_layer;
3192 piValues[i] = GL_FALSE;
3193 break;
3195 case WGL_SUPPORT_OPENGL_ARB:
3196 if (iLayerPlane) goto invalid_layer;
3197 piValues[i] = GL_TRUE;
3198 break;
3200 case WGL_DOUBLE_BUFFER_ARB:
3201 if (iLayerPlane) goto invalid_layer;
3202 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3203 break;
3205 case WGL_STEREO_ARB:
3206 if (iLayerPlane) goto invalid_layer;
3207 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3208 break;
3210 case WGL_PIXEL_TYPE_ARB:
3211 if (iLayerPlane) goto invalid_layer;
3212 if (color_modes[pf->color_mode].is_float)
3213 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3214 else
3215 piValues[i] = WGL_TYPE_RGBA_ARB;
3216 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3217 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3218 However, Mac contexts don't support rendering to unsigned floating-point
3219 formats, even when GL_EXT_packed_float is supported. */
3220 break;
3222 case WGL_COLOR_BITS_ARB:
3223 if (iLayerPlane) goto invalid_layer;
3224 /* If the mode doesn't have alpha, return bits per pixel instead
3225 of color bits. On Windows, color bits sometimes exceeds r+g+b
3226 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3227 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3228 pixel format, we need to accommodate that. */
3229 if (color_modes[pf->color_mode].alpha_bits)
3230 piValues[i] = color_modes[pf->color_mode].color_bits;
3231 else
3232 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3233 break;
3235 case WGL_RED_BITS_ARB:
3236 if (iLayerPlane) goto invalid_layer;
3237 piValues[i] = color_modes[pf->color_mode].red_bits;
3238 break;
3240 case WGL_RED_SHIFT_ARB:
3241 if (iLayerPlane) goto invalid_layer;
3242 piValues[i] = color_modes[pf->color_mode].red_shift;
3243 break;
3245 case WGL_GREEN_BITS_ARB:
3246 if (iLayerPlane) goto invalid_layer;
3247 piValues[i] = color_modes[pf->color_mode].green_bits;
3248 break;
3250 case WGL_GREEN_SHIFT_ARB:
3251 if (iLayerPlane) goto invalid_layer;
3252 piValues[i] = color_modes[pf->color_mode].green_shift;
3253 break;
3255 case WGL_BLUE_BITS_ARB:
3256 if (iLayerPlane) goto invalid_layer;
3257 piValues[i] = color_modes[pf->color_mode].blue_bits;
3258 break;
3260 case WGL_BLUE_SHIFT_ARB:
3261 if (iLayerPlane) goto invalid_layer;
3262 piValues[i] = color_modes[pf->color_mode].blue_shift;
3263 break;
3265 case WGL_ALPHA_BITS_ARB:
3266 if (iLayerPlane) goto invalid_layer;
3267 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3268 break;
3270 case WGL_ALPHA_SHIFT_ARB:
3271 if (iLayerPlane) goto invalid_layer;
3272 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3273 break;
3275 case WGL_ACCUM_BITS_ARB:
3276 if (iLayerPlane) goto invalid_layer;
3277 if (pf->accum_mode)
3278 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3279 else
3280 piValues[i] = 0;
3281 break;
3283 case WGL_ACCUM_RED_BITS_ARB:
3284 if (iLayerPlane) goto invalid_layer;
3285 if (pf->accum_mode)
3286 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3287 else
3288 piValues[i] = 0;
3289 break;
3291 case WGL_ACCUM_GREEN_BITS_ARB:
3292 if (iLayerPlane) goto invalid_layer;
3293 if (pf->accum_mode)
3294 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3295 else
3296 piValues[i] = 0;
3297 break;
3299 case WGL_ACCUM_BLUE_BITS_ARB:
3300 if (iLayerPlane) goto invalid_layer;
3301 if (pf->accum_mode)
3302 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3303 else
3304 piValues[i] = 0;
3305 break;
3307 case WGL_ACCUM_ALPHA_BITS_ARB:
3308 if (iLayerPlane) goto invalid_layer;
3309 if (pf->accum_mode)
3310 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3311 else
3312 piValues[i] = 0;
3313 break;
3315 case WGL_DEPTH_BITS_ARB:
3316 if (iLayerPlane) goto invalid_layer;
3317 piValues[i] = pf->depth_bits;
3318 break;
3320 case WGL_STENCIL_BITS_ARB:
3321 if (iLayerPlane) goto invalid_layer;
3322 piValues[i] = pf->stencil_bits;
3323 break;
3325 case WGL_AUX_BUFFERS_ARB:
3326 if (iLayerPlane) goto invalid_layer;
3327 piValues[i] = pf->aux_buffers;
3328 break;
3330 case WGL_SAMPLE_BUFFERS_ARB:
3331 if (iLayerPlane) goto invalid_layer;
3332 piValues[i] = pf->sample_buffers;
3333 break;
3335 case WGL_SAMPLES_ARB:
3336 if (iLayerPlane) goto invalid_layer;
3337 piValues[i] = pf->samples;
3338 break;
3340 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3341 if (iLayerPlane) goto invalid_layer;
3342 /* sRGB is only supported for 8-bit integer color components */
3343 if (color_modes[pf->color_mode].red_bits == 8 &&
3344 color_modes[pf->color_mode].green_bits == 8 &&
3345 color_modes[pf->color_mode].blue_bits == 8 &&
3346 !color_modes[pf->color_mode].is_float)
3347 piValues[i] = GL_TRUE;
3348 else
3349 piValues[i] = GL_FALSE;
3350 break;
3352 case WGL_DRAW_TO_PBUFFER_ARB:
3353 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3354 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3355 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3356 break;
3358 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3359 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3360 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3361 break;
3363 case WGL_MAX_PBUFFER_WIDTH_ARB:
3364 piValues[i] = gl_info.max_viewport_dims[0];
3365 break;
3367 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3368 piValues[i] = gl_info.max_viewport_dims[1];
3369 break;
3371 case WGL_MAX_PBUFFER_PIXELS_ARB:
3372 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3373 break;
3375 default:
3376 WARN("invalid attribute %x\n", piAttributes[i]);
3377 return GL_FALSE;
3380 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3383 return GL_TRUE;
3385 invalid_layer:
3386 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3387 return GL_FALSE;
3391 /**********************************************************************
3392 * macdrv_wglGetPixelFormatAttribfvARB
3394 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3396 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3397 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3399 int *attr;
3400 int ret;
3402 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3403 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3405 /* Allocate a temporary array to store integer values */
3406 attr = malloc(nAttributes * sizeof(int));
3407 if (!attr)
3409 ERR("couldn't allocate %d array\n", nAttributes);
3410 return GL_FALSE;
3413 /* Piggy-back on wglGetPixelFormatAttribivARB */
3414 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3415 if (ret)
3417 UINT i;
3419 /* Convert integer values to float. Should also check for attributes
3420 that can give decimal values here */
3421 for (i = 0; i < nAttributes; i++)
3422 pfValues[i] = attr[i];
3425 free(attr);
3426 return ret;
3430 /**********************************************************************
3431 * macdrv_wglGetSwapIntervalEXT
3433 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3435 static int macdrv_wglGetSwapIntervalEXT(void)
3437 struct wgl_context *context = NtCurrentTeb()->glContext;
3438 struct macdrv_win_data *data;
3439 long value;
3440 CGLError err;
3442 TRACE("\n");
3444 if ((data = get_win_data(context->draw_hwnd)))
3446 value = data->swap_interval;
3447 release_win_data(data);
3449 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3450 set_swap_interval(context, allow_vsync ? value : 0);
3452 else
3454 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3455 if (err != kCGLNoError)
3457 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3458 err, CGLErrorString(err));
3459 value = 1;
3463 return value;
3467 /***********************************************************************
3468 * macdrv_wglMakeContextCurrentARB
3470 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3472 * This is not supported directly by OpenGL on the Mac. We emulate it
3473 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3474 * temporarily swap the drawable. This follows the technique used in
3475 * the implementation of Mesa GLX for Apple.
3477 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3479 struct macdrv_win_data *data;
3480 HWND hwnd;
3482 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3483 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3485 if (!context)
3487 macdrv_make_context_current(NULL, NULL, CGRectNull);
3488 NtCurrentTeb()->glContext = NULL;
3489 return TRUE;
3492 if ((hwnd = NtUserWindowFromDC(draw_hdc)))
3494 if (!(data = get_win_data(hwnd)))
3496 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3497 return FALSE;
3500 if (!data->pixel_format)
3502 WARN("no pixel format set\n");
3503 release_win_data(data);
3504 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3505 return FALSE;
3507 if (context->format != data->pixel_format)
3509 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3510 release_win_data(data);
3511 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3512 return FALSE;
3515 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd)
3516 set_swap_interval(context, allow_vsync ? data->swap_interval : 0);
3518 context->draw_hwnd = hwnd;
3519 context->draw_view = data->client_cocoa_view;
3520 context->draw_rect = data->client_rect;
3521 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3522 context->draw_pbuffer = NULL;
3523 release_win_data(data);
3525 else
3527 struct wgl_pbuffer *pbuffer;
3529 pthread_mutex_lock(&dc_pbuffers_mutex);
3530 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3531 if (pbuffer)
3533 if (context->format != pbuffer->format)
3535 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3536 pthread_mutex_unlock(&dc_pbuffers_mutex);
3537 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT);
3538 return FALSE;
3541 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer)
3542 set_swap_interval(context, 0);
3544 else
3546 WARN("no window or pbuffer for DC\n");
3547 pthread_mutex_unlock(&dc_pbuffers_mutex);
3548 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3549 return FALSE;
3552 context->draw_hwnd = NULL;
3553 context->draw_view = NULL;
3554 context->draw_pbuffer = pbuffer;
3555 pthread_mutex_unlock(&dc_pbuffers_mutex);
3558 context->read_view = NULL;
3559 context->read_pbuffer = NULL;
3560 if (read_hdc && read_hdc != draw_hdc)
3562 if ((hwnd = NtUserWindowFromDC(read_hdc)))
3564 if ((data = get_win_data(hwnd)))
3566 if (data->client_cocoa_view != context->draw_view)
3568 context->read_view = data->client_cocoa_view;
3569 context->read_rect = data->client_rect;
3570 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3572 release_win_data(data);
3575 else
3577 pthread_mutex_lock(&dc_pbuffers_mutex);
3578 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3579 pthread_mutex_unlock(&dc_pbuffers_mutex);
3583 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3584 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3585 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3587 make_context_current(context, FALSE);
3588 context->has_been_current = TRUE;
3589 NtCurrentTeb()->glContext = context;
3591 return TRUE;
3595 /**********************************************************************
3596 * macdrv_wglQueryCurrentRendererIntegerWINE
3598 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3600 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3602 BOOL ret = FALSE;
3603 struct wgl_context *context = NtCurrentTeb()->glContext;
3604 CGLPixelFormatObj pixel_format;
3605 CGLError err;
3606 GLint virtual_screen;
3607 GLint display_mask;
3608 GLint pf_renderer_id;
3609 CGLRendererInfoObj renderer_info;
3610 GLint renderer_count;
3611 GLint renderer;
3613 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3614 (context ? context->cglcontext : NULL), attribute, value);
3616 if (attribute == WGL_RENDERER_VERSION_WINE)
3618 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3619 get_fallback_renderer_version(value);
3620 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3621 return TRUE;
3624 pixel_format = CGLGetPixelFormat(context->cglcontext);
3625 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3626 if (err != kCGLNoError)
3628 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3629 return FALSE;
3632 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3633 if (err != kCGLNoError)
3635 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3636 return FALSE;
3639 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3640 if (err != kCGLNoError)
3642 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3643 return FALSE;
3646 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3647 if (err != kCGLNoError)
3649 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3650 return FALSE;
3653 for (renderer = 0; renderer < renderer_count; renderer++)
3655 GLint renderer_id;
3657 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3658 continue;
3660 if (renderer_id == pf_renderer_id)
3662 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3663 break;
3667 if (renderer >= renderer_count)
3668 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3670 CGLDestroyRendererInfo(renderer_info);
3671 return ret;
3675 /**********************************************************************
3676 * macdrv_wglQueryCurrentRendererStringWINE
3678 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3680 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3682 const char* ret = NULL;
3683 struct wgl_context *context = NtCurrentTeb()->glContext;
3685 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3686 (context ? context->cglcontext : NULL), attribute);
3688 switch (attribute)
3690 case WGL_RENDERER_DEVICE_ID_WINE:
3692 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3693 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3694 break;
3697 case WGL_RENDERER_VENDOR_ID_WINE:
3699 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3700 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3701 break;
3704 default:
3705 FIXME("unrecognized attribute 0x%04x\n", attribute);
3706 break;
3709 return ret;
3713 /**********************************************************************
3714 * macdrv_wglQueryPbufferARB
3716 * WGL_ARB_pbuffer: wglQueryPbufferARB
3718 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3720 CGLError err;
3721 GLsizei width;
3722 GLsizei height;
3723 GLenum target;
3724 GLenum internalFormat;
3725 GLint mipmap;
3727 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3729 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3730 if (err != kCGLNoError)
3732 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3733 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
3734 return GL_FALSE;
3737 switch (iAttribute)
3739 case WGL_PBUFFER_WIDTH_ARB:
3740 *piValue = width;
3741 break;
3742 case WGL_PBUFFER_HEIGHT_ARB:
3743 *piValue = height;
3744 break;
3745 case WGL_PBUFFER_LOST_ARB:
3746 /* Mac PBuffers can't be lost */
3747 *piValue = GL_FALSE;
3748 break;
3749 case WGL_TEXTURE_FORMAT_ARB:
3750 if (pbuffer->no_texture)
3751 *piValue = WGL_NO_TEXTURE_ARB;
3752 else switch (internalFormat)
3754 case GL_RGBA:
3755 *piValue = WGL_TEXTURE_RGBA_ARB;
3756 break;
3757 case GL_RGB:
3758 default:
3759 *piValue = WGL_TEXTURE_RGB_ARB;
3760 break;
3762 break;
3763 case WGL_TEXTURE_TARGET_ARB:
3764 if (pbuffer->no_texture)
3765 *piValue = WGL_NO_TEXTURE_ARB;
3766 else switch (target)
3768 case GL_TEXTURE_CUBE_MAP:
3769 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3770 break;
3771 case GL_TEXTURE_2D:
3772 *piValue = WGL_TEXTURE_2D_ARB;
3773 break;
3774 case GL_TEXTURE_RECTANGLE:
3775 default:
3776 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3777 break;
3779 break;
3780 case WGL_MIPMAP_TEXTURE_ARB:
3781 *piValue = (pbuffer->max_level > 0);
3782 break;
3783 case WGL_MIPMAP_LEVEL_ARB:
3784 *piValue = pbuffer->level;
3785 break;
3786 case WGL_CUBE_MAP_FACE_ARB:
3787 switch (pbuffer->face)
3789 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3790 default:
3791 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3792 break;
3793 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3794 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3795 break;
3796 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3797 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3798 break;
3799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3800 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3801 break;
3802 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3803 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3804 break;
3805 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3806 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3807 break;
3809 break;
3810 default:
3811 WARN("invalid attribute 0x%x\n", iAttribute);
3812 RtlSetLastWin32Error(ERROR_INVALID_DATA);
3813 return GL_FALSE;
3816 return GL_TRUE;
3820 /**********************************************************************
3821 * macdrv_wglQueryRendererIntegerWINE
3823 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3825 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3827 BOOL ret = FALSE;
3828 CGLRendererInfoObj renderer_info;
3829 GLint renderer_count;
3830 CGLError err;
3832 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3834 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3835 if (err != kCGLNoError)
3837 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3838 return FALSE;
3841 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3843 if (renderer < renderer_count)
3844 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3845 else
3846 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3848 CGLDestroyRendererInfo(renderer_info);
3849 return ret;
3853 /**********************************************************************
3854 * macdrv_wglQueryRendererStringWINE
3856 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3858 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3860 const char* ret = NULL;
3861 CGLRendererInfoObj renderer_info;
3862 GLint renderer_count;
3863 CGLError err;
3865 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3867 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3868 if (err != kCGLNoError)
3870 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3871 return FALSE;
3874 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3876 if (renderer >= renderer_count)
3878 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3879 goto done;
3882 switch (attribute)
3884 case WGL_RENDERER_DEVICE_ID_WINE:
3885 case WGL_RENDERER_VENDOR_ID_WINE:
3887 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3888 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3890 if (!pixel_format)
3891 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3892 if (pixel_format)
3894 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3895 CGLReleasePixelFormat(pixel_format);
3898 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3899 break;
3902 default:
3903 FIXME("unrecognized attribute 0x%04x\n", attribute);
3904 break;
3907 done:
3908 CGLDestroyRendererInfo(renderer_info);
3909 return ret;
3913 /**********************************************************************
3914 * macdrv_wglReleasePbufferDCARB
3916 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3918 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3920 struct wgl_pbuffer *prev;
3922 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3924 pthread_mutex_lock(&dc_pbuffers_mutex);
3926 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3927 if (prev)
3929 if (prev != pbuffer)
3930 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3931 CGLReleasePBuffer(prev->pbuffer);
3932 free(prev);
3933 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3935 else hdc = 0;
3937 pthread_mutex_unlock(&dc_pbuffers_mutex);
3939 return hdc && NtGdiDeleteObjectApp(hdc);
3943 /**********************************************************************
3944 * macdrv_wglReleaseTexImageARB
3946 * WGL_ARB_render_texture: wglReleaseTexImageARB
3948 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3950 struct wgl_context *context = NtCurrentTeb()->glContext;
3951 CGLError err;
3953 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3955 if (pbuffer->no_texture)
3957 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
3958 return GL_FALSE;
3961 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3962 if (err != kCGLNoError)
3964 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3965 RtlSetLastWin32Error(ERROR_INVALID_OPERATION);
3966 return GL_FALSE;
3969 return GL_TRUE;
3973 /**********************************************************************
3974 * macdrv_wglSetPbufferAttribARB
3976 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3978 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3980 struct wgl_context *context = NtCurrentTeb()->glContext;
3982 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3984 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3986 int attr = piAttribList[0];
3987 int value = piAttribList[1];
3988 switch (attr)
3990 case WGL_MIPMAP_LEVEL_ARB:
3991 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3992 pbuffer->level = value;
3993 break;
3994 case WGL_CUBE_MAP_FACE_ARB:
3995 switch (value)
3997 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3998 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3999 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4000 break;
4001 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4002 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4003 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4004 break;
4005 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4006 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4007 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4008 break;
4009 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4010 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4011 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4012 break;
4013 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4014 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4015 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4016 break;
4017 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4018 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4019 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4020 break;
4021 default:
4022 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4023 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4024 return GL_FALSE;
4026 break;
4027 default:
4028 WARN("invalid attribute 0x%x\n", attr);
4029 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4030 return GL_FALSE;
4034 if (context && context->draw_pbuffer == pbuffer)
4035 make_context_current(context, FALSE);
4037 return GL_TRUE;
4041 /**********************************************************************
4042 * macdrv_wglSetPixelFormatWINE
4044 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4046 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4048 return set_pixel_format(hdc, fmt, TRUE);
4052 /**********************************************************************
4053 * macdrv_wglSwapIntervalEXT
4055 * WGL_EXT_swap_control: wglSwapIntervalEXT
4057 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4059 struct wgl_context *context = NtCurrentTeb()->glContext;
4060 BOOL changed = FALSE;
4062 TRACE("interval %d\n", interval);
4064 if (interval < 0)
4066 RtlSetLastWin32Error(ERROR_INVALID_DATA);
4067 return FALSE;
4069 if (interval > 1)
4070 interval = 1;
4072 if (context->draw_hwnd)
4074 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4075 if (data)
4077 changed = data->swap_interval != interval;
4078 if (changed)
4079 data->swap_interval = interval;
4080 release_win_data(data);
4083 else /* pbuffer */
4084 interval = 0;
4086 if (!allow_vsync)
4087 interval = 0;
4089 InterlockedExchange(&context->update_swap_interval, FALSE);
4090 if (!set_swap_interval(context, interval))
4092 RtlSetLastWin32Error(ERROR_GEN_FAILURE);
4093 return FALSE;
4096 if (changed)
4098 struct wgl_context *ctx;
4100 pthread_mutex_lock(&context_mutex);
4101 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4103 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4104 InterlockedExchange(&context->update_swap_interval, TRUE);
4106 pthread_mutex_unlock(&context_mutex);
4109 return TRUE;
4113 static void register_extension(const char *ext)
4115 if (gl_info.wglExtensions[0])
4116 strcat(gl_info.wglExtensions, " ");
4117 strcat(gl_info.wglExtensions, ext);
4119 TRACE("'%s'\n", ext);
4122 static void load_extensions(void)
4125 * ARB Extensions
4127 register_extension("WGL_ARB_extensions_string");
4128 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4130 register_extension("WGL_ARB_make_current_read");
4131 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4132 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4134 register_extension("WGL_ARB_pixel_format");
4135 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4136 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4137 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4139 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4141 register_extension("WGL_ARB_pixel_format_float");
4142 register_extension("WGL_ATI_pixel_format_float");
4145 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4146 register_extension("WGL_ARB_multisample");
4148 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4149 register_extension("WGL_ARB_framebuffer_sRGB");
4151 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4153 register_extension("WGL_ARB_pbuffer");
4154 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4155 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4156 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4157 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4158 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4160 register_extension("WGL_ARB_render_texture");
4161 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4162 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4163 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4165 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4166 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4167 register_extension("WGL_NV_render_texture_rectangle");
4170 register_extension("WGL_ARB_create_context");
4171 register_extension("WGL_ARB_create_context_profile");
4172 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4175 * EXT Extensions
4177 register_extension("WGL_EXT_extensions_string");
4178 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4180 if (allow_vsync)
4182 register_extension("WGL_EXT_swap_control");
4183 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4184 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4187 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4188 check for either, so register them separately. */
4189 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4190 register_extension("WGL_EXT_framebuffer_sRGB");
4192 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4193 register_extension("WGL_EXT_pixel_format_packed_float");
4196 * WINE-specific WGL Extensions
4199 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4200 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4202 register_extension("WGL_WINE_pixel_format_passthrough");
4203 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4205 register_extension("WGL_WINE_query_renderer");
4206 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4207 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4208 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4209 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4213 static void init_opengl(void)
4215 unsigned int i;
4217 TRACE("()\n");
4219 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4220 if (!dc_pbuffers)
4222 WARN("CFDictionaryCreateMutable failed\n");
4223 return;
4226 opengl_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD);
4227 if (!opengl_handle)
4229 ERR("Failed to load OpenGL: %s\n", dlerror());
4230 ERR("OpenGL support is disabled.\n");
4231 return;
4234 for (i = 0; i < ARRAY_SIZE(opengl_func_names); i++)
4236 if (!(((void **)&opengl_funcs.gl)[i] = dlsym(opengl_handle, opengl_func_names[i])))
4238 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4239 goto failed;
4243 if (!init_gl_info())
4244 goto failed;
4246 /* redirect some standard OpenGL functions */
4247 #define REDIRECT(func) \
4248 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4249 REDIRECT(glCopyPixels);
4250 REDIRECT(glGetString);
4251 REDIRECT(glReadPixels);
4252 REDIRECT(glViewport);
4253 if (skip_single_buffer_flushes || allow_vsync)
4254 REDIRECT(glFlush);
4255 if (allow_vsync)
4256 REDIRECT(glFinish);
4257 #undef REDIRECT
4259 /* redirect some OpenGL extension functions */
4260 #define REDIRECT(func) \
4261 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4262 REDIRECT(glCopyColorTable);
4263 #undef REDIRECT
4265 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4266 pglFlushRenderAPPLE = dlsym(opengl_handle, "glFlushRenderAPPLE");
4268 load_extensions();
4269 if (!init_pixel_formats())
4270 goto failed;
4272 return;
4274 failed:
4275 dlclose(opengl_handle);
4276 opengl_handle = NULL;
4280 /***********************************************************************
4281 * sync_gl_view
4283 * Synchronize the Mac GL view position with the Windows child window
4284 * position.
4286 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4288 if (data->client_cocoa_view && data->pixel_format)
4290 RECT old = *old_client_rect, new = data->client_rect;
4292 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4293 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4294 if (!EqualRect(&old, &new))
4296 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4297 mark_contexts_for_moved_view(data->client_cocoa_view);
4303 /**********************************************************************
4304 * macdrv_wglDescribePixelFormat
4306 static int WINAPI macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4308 const pixel_format *pf;
4309 const struct color_mode *mode;
4311 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4313 if (!descr) return nb_displayable_formats;
4314 if (size < sizeof(*descr)) return 0;
4316 if (!(pf = get_pixel_format(fmt, FALSE)))
4317 return 0;
4319 memset(descr, 0, sizeof(*descr));
4320 descr->nSize = sizeof(*descr);
4321 descr->nVersion = 1;
4323 descr->dwFlags = PFD_SUPPORT_OPENGL;
4324 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4325 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4326 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4327 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4328 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4330 descr->iPixelType = PFD_TYPE_RGBA;
4332 mode = &color_modes[pf->color_mode];
4333 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4334 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4335 R8G8B8A0 pixel format). If an app depends on that and expects that
4336 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4337 if (mode->alpha_bits)
4338 descr->cColorBits = mode->color_bits;
4339 else
4340 descr->cColorBits = mode->bits_per_pixel;
4341 descr->cRedBits = mode->red_bits;
4342 descr->cRedShift = mode->red_shift;
4343 descr->cGreenBits = mode->green_bits;
4344 descr->cGreenShift = mode->green_shift;
4345 descr->cBlueBits = mode->blue_bits;
4346 descr->cBlueShift = mode->blue_shift;
4347 descr->cAlphaBits = mode->alpha_bits;
4348 descr->cAlphaShift = mode->alpha_shift;
4350 if (pf->accum_mode)
4352 mode = &color_modes[pf->accum_mode - 1];
4353 descr->cAccumBits = mode->color_bits;
4354 descr->cAccumRedBits = mode->red_bits;
4355 descr->cAccumGreenBits = mode->green_bits;
4356 descr->cAccumBlueBits = mode->blue_bits;
4357 descr->cAccumAlphaBits = mode->alpha_bits;
4360 descr->cDepthBits = pf->depth_bits;
4361 descr->cStencilBits = pf->stencil_bits;
4362 descr->cAuxBuffers = pf->aux_buffers;
4363 descr->iLayerType = PFD_MAIN_PLANE;
4365 TRACE("%s\n", debugstr_pf(pf));
4366 return nb_displayable_formats;
4369 /***********************************************************************
4370 * macdrv_wglCopyContext
4372 static BOOL WINAPI macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4374 CGLError err;
4376 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4378 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4379 if (err != kCGLNoError)
4380 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4381 return (err == kCGLNoError);
4384 /***********************************************************************
4385 * macdrv_wglCreateContext
4387 static struct wgl_context * WINAPI macdrv_wglCreateContext(HDC hdc)
4389 struct wgl_context *context;
4391 TRACE("hdc %p\n", hdc);
4393 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4395 return context;
4398 /***********************************************************************
4399 * macdrv_wglDeleteContext
4401 static BOOL WINAPI macdrv_wglDeleteContext(struct wgl_context *context)
4403 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4405 pthread_mutex_lock(&context_mutex);
4406 list_remove(&context->entry);
4407 pthread_mutex_unlock(&context_mutex);
4409 macdrv_dispose_opengl_context(context->context);
4410 free(context);
4411 return TRUE;
4414 /***********************************************************************
4415 * macdrv_wglGetPixelFormat
4417 static int WINAPI macdrv_wglGetPixelFormat(HDC hdc)
4419 int format;
4421 format = get_dc_pixel_format(hdc);
4423 if (!is_valid_pixel_format(format)) /* not set yet */
4424 format = 0;
4425 else if (!is_displayable_pixel_format(format))
4427 /* Non-displayable formats can't be used with traditional WGL calls.
4428 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4429 format = 1;
4432 TRACE(" hdc %p -> %d\n", hdc, format);
4433 return format;
4436 /***********************************************************************
4437 * macdrv_wglGetProcAddress
4439 static PROC WINAPI macdrv_wglGetProcAddress(const char *proc)
4441 void *ret;
4443 if (!strncmp(proc, "wgl", 3)) return NULL;
4444 ret = dlsym(opengl_handle, proc);
4445 if (ret)
4447 if (TRACE_ON(wgl))
4449 Dl_info info;
4450 if (dladdr(ret, &info))
4451 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4452 else
4453 TRACE("%s -> %p (no library info)\n", proc, ret);
4456 else
4457 WARN("failed to find proc %s\n", debugstr_a(proc));
4458 return ret;
4461 /***********************************************************************
4462 * macdrv_wglMakeCurrent
4464 static BOOL WINAPI macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4466 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4467 (context ? context->cglcontext : NULL));
4469 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4472 /**********************************************************************
4473 * macdrv_wglSetPixelFormat
4475 static BOOL WINAPI macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4477 return set_pixel_format(hdc, fmt, FALSE);
4480 /***********************************************************************
4481 * macdrv_wglShareLists
4483 static BOOL WINAPI macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4485 macdrv_opengl_context saved_context;
4486 CGLContextObj saved_cglcontext;
4488 TRACE("org %p dest %p\n", org, dest);
4490 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4491 * at context creation time but in case of WGL it is done using wglShareLists.
4493 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4494 * and when a program requests sharing we recreate the destination context if it hasn't been made
4495 * current or when it hasn't shared display lists before.
4498 if (dest->has_been_current)
4500 WARN("could not share display lists, the destination context has been current already\n");
4501 return FALSE;
4503 else if (dest->sharing)
4505 WARN("could not share display lists because dest has already shared lists before\n");
4506 return FALSE;
4509 /* Re-create the Mac context and share display lists */
4510 saved_context = dest->context;
4511 saved_cglcontext = dest->cglcontext;
4512 dest->context = NULL;
4513 dest->cglcontext = NULL;
4514 if (!create_context(dest, org->cglcontext, dest->major))
4516 dest->context = saved_context;
4517 dest->cglcontext = saved_cglcontext;
4518 return FALSE;
4521 /* Implicitly disposes of saved_cglcontext. */
4522 macdrv_dispose_opengl_context(saved_context);
4524 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4525 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4527 org->sharing = TRUE;
4528 dest->sharing = TRUE;
4530 return TRUE;
4533 /**********************************************************************
4534 * macdrv_wglSwapBuffers
4536 static BOOL WINAPI macdrv_wglSwapBuffers(HDC hdc)
4538 struct wgl_context *context = NtCurrentTeb()->glContext;
4539 BOOL match = FALSE;
4540 HWND hwnd;
4542 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4543 (context ? context->cglcontext : NULL));
4545 if (context)
4547 sync_swap_interval(context);
4548 sync_context(context);
4551 if ((hwnd = NtUserWindowFromDC(hdc)))
4553 struct macdrv_win_data *data;
4555 if (!(data = get_win_data(hwnd)))
4557 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
4558 return FALSE;
4561 if (context && context->draw_view == data->client_cocoa_view)
4562 match = TRUE;
4564 release_win_data(data);
4566 else
4568 struct wgl_pbuffer *pbuffer;
4570 pthread_mutex_lock(&dc_pbuffers_mutex);
4571 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4572 pthread_mutex_unlock(&dc_pbuffers_mutex);
4574 if (!pbuffer)
4576 RtlSetLastWin32Error(ERROR_INVALID_HANDLE);
4577 return FALSE;
4580 if (context && context->draw_pbuffer == pbuffer)
4581 match = TRUE;
4584 if (match)
4585 macdrv_flush_opengl_context(context->context);
4586 else
4588 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4590 /* If there is a current context, then wglSwapBuffers should do an implicit
4591 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4592 in the other branch, but we have to do it explicitly here. */
4593 if (context)
4594 pglFlush();
4597 return TRUE;
4600 static struct opengl_funcs opengl_funcs =
4603 macdrv_wglCopyContext, /* p_wglCopyContext */
4604 macdrv_wglCreateContext, /* p_wglCreateContext */
4605 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4606 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4607 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4608 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4609 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4610 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4611 macdrv_wglShareLists, /* p_wglShareLists */
4612 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4616 /**********************************************************************
4617 * macdrv_wine_get_wgl_driver
4619 struct opengl_funcs *macdrv_wine_get_wgl_driver(UINT version)
4621 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
4623 if (version != WINE_WGL_DRIVER_VERSION)
4625 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4626 return NULL;
4629 pthread_once(&init_once, init_opengl);
4630 return opengl_handle ? &opengl_funcs : (void *)-1;