msvcp140: Implement _Stat and _Lstat.
[wine.git] / dlls / winemac.drv / opengl.c
blob6e1f151e019eb6d6a5e0f051ecb3c32b4f85573e
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
36 #define __gl_h_
37 #define __gltypes_h_
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
41 #include <dlfcn.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 struct gl_info {
47 char *glExtensions;
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
53 unsigned int max_major, max_minor;
56 static struct gl_info gl_info;
59 struct wgl_context
61 struct list entry;
62 int format;
63 GLint renderer_id;
64 macdrv_opengl_context context;
65 CGLContextObj cglcontext;
66 HWND draw_hwnd;
67 macdrv_view draw_view;
68 RECT draw_rect;
69 struct wgl_pbuffer *draw_pbuffer;
70 macdrv_view read_view;
71 RECT read_rect;
72 struct wgl_pbuffer *read_pbuffer;
73 BOOL has_been_current;
74 BOOL sharing;
75 LONG update_swap_interval;
76 LONG view_moved;
77 DWORD last_flush_time;
78 UINT major;
81 static struct list context_list = LIST_INIT(context_list);
83 static CRITICAL_SECTION context_section;
84 static CRITICAL_SECTION_DEBUG critsect_debug =
86 0, 0, &context_section,
87 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
88 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
90 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
93 struct wgl_pbuffer
95 CGLPBufferObj pbuffer;
96 int format;
97 BOOL no_texture;
98 int max_level;
99 GLint level;
100 GLenum face;
103 static CFMutableDictionaryRef dc_pbuffers;
105 static CRITICAL_SECTION dc_pbuffers_section;
106 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
108 0, 0, &dc_pbuffers_section,
109 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
110 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
112 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
115 static struct opengl_funcs opengl_funcs;
117 #define USE_GL_FUNC(name) #name,
118 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
119 #undef USE_GL_FUNC
122 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
123 GLsizei width);
124 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
125 static void (*pglFinish)(void);
126 static void (*pglFlush)(void);
127 static void (*pglFlushRenderAPPLE)(void);
128 static const GLubyte *(*pglGetString)(GLenum name);
129 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
130 GLenum format, GLenum type, void *pixels);
131 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
134 struct color_mode {
135 GLint mode;
136 int bits_per_pixel;
137 GLint color_bits; /* including alpha_bits */
138 int red_bits, red_shift;
139 int green_bits, green_shift;
140 int blue_bits, blue_shift;
141 GLint alpha_bits, alpha_shift;
142 BOOL is_float;
143 int color_ordering;
146 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
147 observations of the behavior of Windows systems, but also subjective judgments
148 about what color formats are more "normal" than others.
150 On at least some Windows systems, integer color formats are listed before
151 floating-point formats. Within the integer formats, higher color bits were
152 usually listed before lower color bits, while for floating-point formats it
153 was the reverse. However, that leads D3D to select 64-bit integer formats in
154 preference to 32-bit formats when the latter would be sufficient. It seems
155 that a 32-bit format is much more likely to be normally used in that case.
157 Also, there are certain odd color formats supported on the Mac which seem like
158 they would be less appropriate than more common ones. For instance, the color
159 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
160 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
161 components.
163 For two color formats which differ only in whether or not they have alpha bits,
164 we use the same ordering. pixel_format_comparator() gives alpha bits a
165 different weight than color formats.
167 static const struct color_mode color_modes[] = {
168 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
169 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
170 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
171 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
172 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
173 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
174 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
175 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
176 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
177 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
178 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
179 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
180 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
181 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
182 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
183 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
184 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
185 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
186 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
187 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
188 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
189 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
190 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
191 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
195 static const struct {
196 GLint mode;
197 int bits;
198 } depth_stencil_modes[] = {
199 { kCGL0Bit, 0 },
200 { kCGL1Bit, 1 },
201 { kCGL2Bit, 2 },
202 { kCGL3Bit, 3 },
203 { kCGL4Bit, 4 },
204 { kCGL5Bit, 5 },
205 { kCGL6Bit, 6 },
206 { kCGL8Bit, 8 },
207 { kCGL10Bit, 10 },
208 { kCGL12Bit, 12 },
209 { kCGL16Bit, 16 },
210 { kCGL24Bit, 24 },
211 { kCGL32Bit, 32 },
212 { kCGL48Bit, 48 },
213 { kCGL64Bit, 64 },
214 { kCGL96Bit, 96 },
215 { kCGL128Bit, 128 },
219 typedef struct {
220 GLint renderer_id;
221 GLint buffer_modes;
222 GLint color_modes;
223 GLint accum_modes;
224 GLint depth_modes;
225 GLint stencil_modes;
226 GLint max_aux_buffers;
227 GLint max_sample_buffers;
228 GLint max_samples;
229 BOOL offscreen;
230 BOOL accelerated;
231 BOOL backing_store;
232 BOOL window;
233 BOOL online;
234 } renderer_properties;
237 typedef struct {
238 unsigned int window:1;
239 unsigned int pbuffer:1;
240 unsigned int accelerated:1;
241 unsigned int color_mode:5; /* index into color_modes table */
242 unsigned int aux_buffers:3;
243 unsigned int depth_bits:8;
244 unsigned int stencil_bits:8;
245 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
246 unsigned int double_buffer:1;
247 unsigned int stereo:1;
248 unsigned int sample_buffers:1;
249 unsigned int samples:5;
250 unsigned int backing_store:1;
251 } pixel_format;
254 typedef union
256 pixel_format format;
257 UInt64 code;
258 } pixel_format_or_code;
259 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
262 static pixel_format *pixel_formats;
263 static int nb_formats, nb_displayable_formats;
266 static void *opengl_handle;
269 static const char* debugstr_attrib(int attrib, int value)
271 static const struct {
272 int attrib;
273 const char *name;
274 } attrib_names[] = {
275 #define ATTRIB(a) { a, #a }
276 ATTRIB(WGL_ACCELERATION_ARB),
277 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
278 ATTRIB(WGL_ACCUM_BITS_ARB),
279 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
280 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
281 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
282 ATTRIB(WGL_ALPHA_BITS_ARB),
283 ATTRIB(WGL_ALPHA_SHIFT_ARB),
284 ATTRIB(WGL_AUX_BUFFERS_ARB),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
286 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
287 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
288 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
289 ATTRIB(WGL_BLUE_BITS_ARB),
290 ATTRIB(WGL_BLUE_SHIFT_ARB),
291 ATTRIB(WGL_COLOR_BITS_ARB),
292 ATTRIB(WGL_DEPTH_BITS_ARB),
293 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
294 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
295 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
296 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
297 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
298 ATTRIB(WGL_GREEN_BITS_ARB),
299 ATTRIB(WGL_GREEN_SHIFT_ARB),
300 ATTRIB(WGL_NEED_PALETTE_ARB),
301 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
302 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
303 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
304 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
305 ATTRIB(WGL_PIXEL_TYPE_ARB),
306 ATTRIB(WGL_RED_BITS_ARB),
307 ATTRIB(WGL_RED_SHIFT_ARB),
308 ATTRIB(WGL_RENDERER_ID_WINE),
309 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
310 ATTRIB(WGL_SAMPLES_ARB),
311 ATTRIB(WGL_SHARE_ACCUM_ARB),
312 ATTRIB(WGL_SHARE_DEPTH_ARB),
313 ATTRIB(WGL_SHARE_STENCIL_ARB),
314 ATTRIB(WGL_STENCIL_BITS_ARB),
315 ATTRIB(WGL_STEREO_ARB),
316 ATTRIB(WGL_SUPPORT_GDI_ARB),
317 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
318 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
319 ATTRIB(WGL_SWAP_METHOD_ARB),
320 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
321 ATTRIB(WGL_TRANSPARENT_ARB),
322 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
323 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
324 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
325 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
326 #undef ATTRIB
328 int i;
329 const char *attrib_name = NULL;
330 const char *value_name = NULL;
332 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
334 if (attrib_names[i].attrib == attrib)
336 attrib_name = attrib_names[i].name;
337 break;
341 if (!attrib_name)
342 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
344 switch (attrib)
346 case WGL_ACCELERATION_ARB:
347 switch (value)
349 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
350 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
351 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
353 break;
354 case WGL_PIXEL_TYPE_ARB:
355 switch (value)
357 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
358 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
359 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
360 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
362 break;
363 case WGL_SWAP_METHOD_ARB:
364 switch (value)
366 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
367 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
368 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
370 break;
373 if (!value_name)
374 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
376 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
380 /**********************************************************************
381 * active_displays_mask
383 static CGOpenGLDisplayMask active_displays_mask(void)
385 CGError err;
386 CGDirectDisplayID displays[32];
387 uint32_t count, i;
388 CGOpenGLDisplayMask mask;
390 err = CGGetActiveDisplayList(sizeof(displays) / sizeof(displays[0]), displays, &count);
391 if (err != kCGErrorSuccess)
393 displays[0] = CGMainDisplayID();
394 count = 1;
397 mask = 0;
398 for (i = 0; i < count; i++)
399 mask |= CGDisplayIDToOpenGLDisplayMask(displays[i]);
401 return mask;
405 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
406 CGLRendererProperty property, GLint *value)
408 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
409 if (err != kCGLNoError)
410 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
411 return (err == kCGLNoError);
415 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
417 GLint value;
419 memset(properties, 0, sizeof(*properties));
421 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
422 properties->renderer_id = value & kCGLRendererIDMatchingMask;
424 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
425 properties->buffer_modes = value;
427 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
428 properties->color_modes = value;
430 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
431 properties->accum_modes = value;
433 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
434 properties->depth_modes = value;
436 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
437 properties->stencil_modes = value;
439 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
440 properties->max_aux_buffers = value;
442 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
443 properties->max_sample_buffers = value;
445 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
446 properties->max_samples = value;
448 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
449 properties->offscreen = (value != 0);
451 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
452 properties->accelerated = (value != 0);
454 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
455 properties->backing_store = (value != 0);
457 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
458 properties->window = (value != 0);
460 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
461 properties->online = (value != 0);
465 static void dump_renderer(const renderer_properties* renderer)
467 int i;
469 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
470 TRACE("Buffer modes:\n");
471 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
472 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
473 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
474 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
476 TRACE("Color buffer modes:\n");
477 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
479 if (renderer->color_modes & color_modes[i].mode)
481 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
482 if (color_modes[i].is_float)
483 TRACE(", Float");
484 TRACE("\n");
488 TRACE("Accumulation buffer sizes: { ");
489 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
491 if (renderer->accum_modes & color_modes[i].mode)
492 TRACE("%d, ", color_modes[i].color_bits);
494 TRACE("}\n");
496 TRACE("Depth buffer sizes: { ");
497 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
499 if (renderer->depth_modes & depth_stencil_modes[i].mode)
500 TRACE("%d, ", depth_stencil_modes[i].bits);
502 TRACE("}\n");
504 TRACE("Stencil buffer sizes: { ");
505 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
507 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
508 TRACE("%d, ", depth_stencil_modes[i].bits);
510 TRACE("}\n");
512 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
513 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
514 TRACE("Max. Samples: %d\n", renderer->max_samples);
515 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
516 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
517 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
518 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
519 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
523 static inline UInt64 code_for_pixel_format(const pixel_format* format)
525 pixel_format_or_code pfc;
527 pfc.code = 0;
528 pfc.format = *format;
529 return pfc.code;
533 static inline pixel_format pixel_format_for_code(UInt64 code)
535 pixel_format_or_code pfc;
537 pfc.code = code;
538 return pfc.format;
542 static const char *debugstr_pf(const pixel_format *pf)
544 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",
545 pf->window,
546 pf->pbuffer,
547 pf->accelerated,
548 color_modes[pf->color_mode].color_bits,
549 (color_modes[pf->color_mode].is_float ? "f" : ""),
550 color_modes[pf->color_mode].alpha_bits,
551 pf->depth_bits,
552 pf->stencil_bits,
553 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
554 pf->aux_buffers,
555 pf->backing_store,
556 pf->double_buffer,
557 pf->stereo,
558 pf->sample_buffers,
559 pf->samples,
560 code_for_pixel_format(pf));
564 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
566 int best = -1;
567 int i;
569 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
571 if ((modes & color_modes[i].mode) &&
572 color_modes[i].color_bits >= color_size &&
573 color_modes[i].alpha_bits >= alpha_size &&
574 !color_modes[i].is_float == !color_float)
576 if (best < 0) /* no existing best choice */
577 best = i;
578 else if (color_modes[i].color_bits == color_size &&
579 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
581 /* prefer it over a best which isn't exact or which has a higher bpp */
582 if (color_modes[best].color_bits != color_size ||
583 color_modes[best].alpha_bits != alpha_size ||
584 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
585 best = i;
587 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
588 (color_modes[i].color_bits == color_modes[best].color_bits &&
589 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
590 best = i;
594 if (best < 0)
596 /* Couldn't find a match. Return first one that renderer supports. */
597 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
599 if (modes & color_modes[i].mode)
600 return i;
604 return best;
608 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
610 int best = -1;
611 int i;
613 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
615 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
617 /* Prefer the fewest color bits, then prefer more alpha bits, then
618 prefer more bits per pixel. */
619 if (best < 0)
620 best = i;
621 else if (color_modes[i].color_bits < color_modes[best].color_bits)
622 best = i;
623 else if (color_modes[i].color_bits == color_modes[best].color_bits)
625 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
626 best = i;
627 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
628 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
629 best = i;
634 if (best < 0)
636 /* Couldn't find a match. Return last one that renderer supports. */
637 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
639 if (modes & color_modes[i].mode)
640 return i;
644 return best;
648 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
649 CFMutableSetRef pixel_format_set)
651 CGLPixelFormatAttribute attribs[64] = {
652 kCGLPFAMinimumPolicy,
653 kCGLPFAClosestPolicy,
654 kCGLPFARendererID, renderer.renderer_id,
655 kCGLPFASingleRenderer,
657 int n = 5, n_stack[16], n_stack_idx = -1;
658 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
659 new_pixel_formats = 0;
660 pixel_format request;
661 unsigned int double_buffer;
662 unsigned int accelerated = renderer.accelerated;
664 if (accelerated)
666 attribs[n++] = kCGLPFAAccelerated;
667 attribs[n++] = kCGLPFANoRecovery;
669 else if (!allow_software_rendering)
671 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
672 return;
675 n_stack[++n_stack_idx] = n;
676 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
678 unsigned int aux;
680 n = n_stack[n_stack_idx];
682 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
683 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
684 continue;
686 if (double_buffer)
687 attribs[n++] = kCGLPFADoubleBuffer;
688 memset(&request, 0, sizeof(request));
689 request.accelerated = accelerated;
690 request.double_buffer = double_buffer;
692 /* Don't bother with in-between aux buffers values: either 0 or max. */
693 n_stack[++n_stack_idx] = n;
694 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
696 unsigned int color_mode;
698 n = n_stack[n_stack_idx];
700 attribs[n++] = kCGLPFAAuxBuffers;
701 attribs[n++] = aux;
702 request.aux_buffers = aux;
704 n_stack[++n_stack_idx] = n;
705 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
707 unsigned int depth_mode;
709 n = n_stack[n_stack_idx];
711 if (!(renderer.color_modes & color_modes[color_mode].mode))
712 continue;
714 attribs[n++] = kCGLPFAColorSize;
715 attribs[n++] = color_modes[color_mode].color_bits;
716 attribs[n++] = kCGLPFAAlphaSize;
717 attribs[n++] = color_modes[color_mode].alpha_bits;
718 if (color_modes[color_mode].is_float)
719 attribs[n++] = kCGLPFAColorFloat;
720 request.color_mode = color_mode;
722 n_stack[++n_stack_idx] = n;
723 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
725 unsigned int stencil_mode;
727 n = n_stack[n_stack_idx];
729 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
730 continue;
732 attribs[n++] = kCGLPFADepthSize;
733 attribs[n++] = depth_stencil_modes[depth_mode].bits;
734 request.depth_bits = depth_stencil_modes[depth_mode].bits;
736 n_stack[++n_stack_idx] = n;
737 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
739 unsigned int stereo;
741 n = n_stack[n_stack_idx];
743 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
744 continue;
745 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
746 continue;
748 attribs[n++] = kCGLPFAStencilSize;
749 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
750 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
752 /* FIXME: Could trim search space a bit here depending on GPU.
753 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
754 n_stack[++n_stack_idx] = n;
755 for (stereo = 0; stereo <= 1; stereo++)
757 int accum_mode;
759 n = n_stack[n_stack_idx];
761 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
762 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
763 continue;
765 if (stereo)
766 attribs[n++] = kCGLPFAStereo;
767 request.stereo = stereo;
769 /* Starts at -1 for a 0 accum size */
770 n_stack[++n_stack_idx] = n;
771 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
773 unsigned int target_pass;
775 n = n_stack[n_stack_idx];
777 if (accum_mode >= 0)
779 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
780 continue;
782 attribs[n++] = kCGLPFAAccumSize;
783 attribs[n++] = color_modes[accum_mode].color_bits;
784 request.accum_mode = accum_mode + 1;
786 else
787 request.accum_mode = 0;
789 /* Targets to request are:
790 accelerated: window OR window + pbuffer
791 software: window + pbuffer */
792 n_stack[++n_stack_idx] = n;
793 for (target_pass = 0; target_pass <= accelerated; target_pass++)
795 unsigned int samples, max_samples;
797 n = n_stack[n_stack_idx];
799 attribs[n++] = kCGLPFAWindow;
800 request.window = 1;
802 if (!accelerated || target_pass > 0)
804 attribs[n++] = kCGLPFAPBuffer;
805 request.pbuffer = 1;
807 else
808 request.pbuffer = 0;
810 /* FIXME: Could trim search space a bit here depending on GPU.
811 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
812 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
813 n_stack[++n_stack_idx] = n;
814 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
815 for (samples = 1; samples <= max_samples; samples *= 2)
817 unsigned int backing_store, min_backing_store, max_backing_store;
819 n = n_stack[n_stack_idx];
821 if (samples > 1)
823 attribs[n++] = kCGLPFASampleBuffers;
824 attribs[n++] = renderer.max_sample_buffers;
825 attribs[n++] = kCGLPFASamples;
826 attribs[n++] = samples;
827 request.sample_buffers = renderer.max_sample_buffers;
828 request.samples = samples;
830 else
831 request.sample_buffers = request.samples = 0;
833 if (renderer.backing_store && double_buffer)
835 /* The software renderer seems to always preserve the backing store, whether
836 we ask for it or not. So don't bother not asking for it. */
837 min_backing_store = accelerated ? 0 : 1;
838 max_backing_store = 1;
840 else
841 min_backing_store = max_backing_store = 0;
842 n_stack[++n_stack_idx] = n;
843 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
845 CGLPixelFormatObj pix;
846 GLint virtualScreens;
847 CGLError err;
849 n = n_stack[n_stack_idx];
851 if (backing_store)
852 attribs[n++] = kCGLPFABackingStore;
853 request.backing_store = backing_store;
855 attribs[n] = 0;
857 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
858 if (err == kCGLNoError && pix)
860 pixel_format pf;
861 GLint value, color_size, alpha_size, color_float;
862 UInt64 pf_code;
863 CFNumberRef code_object;
864 BOOL dupe;
866 memset(&pf, 0, sizeof(pf));
868 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
869 pf.accelerated = value;
870 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
871 pf.aux_buffers = value;
872 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
873 pf.depth_bits = value;
874 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
875 pf.double_buffer = value;
876 if (pf.double_buffer &&
877 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
878 pf.backing_store = value;
879 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
880 pf.pbuffer = value;
881 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
882 pf.sample_buffers = value;
883 if (pf.sample_buffers &&
884 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
885 pf.samples = value;
886 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
887 pf.stencil_bits = value;
888 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
889 pf.stereo = value;
890 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
891 pf.window = value;
893 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
894 color_size = 0;
895 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
896 alpha_size = 0;
897 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
898 color_float = 0;
899 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
901 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
902 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
904 CGLReleasePixelFormat(pix);
906 pf_code = code_for_pixel_format(&pf);
908 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
909 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
910 dupe_pixel_formats++;
911 else
913 CFSetAddValue(pixel_format_set, code_object);
914 CFArrayAppendValue(pixel_format_array, code_object);
915 new_pixel_formats++;
917 CFRelease(code_object);
919 if (pf_code == code_for_pixel_format(&request))
920 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
921 else
923 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
924 dupe ? " (duplicate)" : "");
927 else
929 failed_pixel_formats++;
930 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
933 tried_pixel_formats++;
936 n_stack_idx--;
939 n_stack_idx--;
942 n_stack_idx--;
945 n_stack_idx--;
948 n_stack_idx--;
951 n_stack_idx--;
954 n_stack_idx--;
957 n_stack_idx--;
960 n_stack_idx--;
963 n_stack_idx--;
965 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
966 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
967 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
968 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
972 /* The docs for WGL_ARB_pixel_format say:
973 Indices are assigned to pixel formats in the following order:
974 1. Accelerated pixel formats that are displayable
975 2. Accelerated pixel formats that are displayable and which have
976 extended attributes
977 3. Generic pixel formats
978 4. Accelerated pixel formats that are non displayable
980 static int pixel_format_category(pixel_format pf)
982 /* non-displayable */
983 if (!pf.window)
984 return 4;
986 /* non-accelerated a.k.a. software a.k.a. generic */
987 if (!pf.accelerated)
988 return 3;
990 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
991 if (color_modes[pf.color_mode].is_float)
992 return 2;
994 /* accelerated, displayable, no extended attributes */
995 return 1;
999 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
1001 CFNumberRef number1 = val1;
1002 CFNumberRef number2 = val2;
1003 UInt64 code1, code2;
1004 pixel_format pf1, pf2;
1005 int category1, category2;
1007 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
1008 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
1009 pf1 = pixel_format_for_code(code1);
1010 pf2 = pixel_format_for_code(code2);
1011 category1 = pixel_format_category(pf1);
1012 category2 = pixel_format_category(pf2);
1014 if (category1 < category2)
1015 return kCFCompareLessThan;
1016 if (category1 > category2)
1017 return kCFCompareGreaterThan;
1019 /* Within a category, sort the "best" formats toward the front since that's
1020 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1021 matches at least one Windows 7 machine's behavior.
1023 /* Accelerated before unaccelerated. */
1024 if (pf1.accelerated && !pf2.accelerated)
1025 return kCFCompareLessThan;
1026 if (!pf1.accelerated && pf2.accelerated)
1027 return kCFCompareGreaterThan;
1029 /* Explicit color mode ordering. */
1030 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1031 return kCFCompareLessThan;
1032 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1033 return kCFCompareGreaterThan;
1035 /* Non-pbuffer-capable before pbuffer-capable. */
1036 if (!pf1.pbuffer && pf2.pbuffer)
1037 return kCFCompareLessThan;
1038 if (pf1.pbuffer && !pf2.pbuffer)
1039 return kCFCompareGreaterThan;
1041 /* Fewer samples before more samples. */
1042 if (pf1.samples < pf2.samples)
1043 return kCFCompareLessThan;
1044 if (pf1.samples > pf2.samples)
1045 return kCFCompareGreaterThan;
1047 /* Monoscopic before stereoscopic. (This is a guess.) */
1048 if (!pf1.stereo && pf2.stereo)
1049 return kCFCompareLessThan;
1050 if (pf1.stereo && !pf2.stereo)
1051 return kCFCompareGreaterThan;
1053 /* Single buffered before double buffered. */
1054 if (!pf1.double_buffer && pf2.double_buffer)
1055 return kCFCompareLessThan;
1056 if (pf1.double_buffer && !pf2.double_buffer)
1057 return kCFCompareGreaterThan;
1059 /* Possibly-optimized double buffering before backing-store-preserving
1060 double buffering. */
1061 if (!pf1.backing_store && pf2.backing_store)
1062 return kCFCompareLessThan;
1063 if (pf1.backing_store && !pf2.backing_store)
1064 return kCFCompareGreaterThan;
1066 /* Bigger depth buffer before smaller depth buffer. */
1067 if (pf1.depth_bits > pf2.depth_bits)
1068 return kCFCompareLessThan;
1069 if (pf1.depth_bits < pf2.depth_bits)
1070 return kCFCompareGreaterThan;
1072 /* Smaller stencil buffer before bigger stencil buffer. */
1073 if (pf1.stencil_bits < pf2.stencil_bits)
1074 return kCFCompareLessThan;
1075 if (pf1.stencil_bits > pf2.stencil_bits)
1076 return kCFCompareGreaterThan;
1078 /* Smaller alpha bits before larger alpha bits. */
1079 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1080 return kCFCompareLessThan;
1081 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1082 return kCFCompareGreaterThan;
1084 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1085 if (pf1.accum_mode)
1087 if (pf2.accum_mode)
1089 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1090 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1091 return kCFCompareLessThan;
1092 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1093 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1094 return kCFCompareGreaterThan;
1096 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1097 return kCFCompareLessThan;
1098 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1099 return kCFCompareGreaterThan;
1101 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1102 return kCFCompareLessThan;
1103 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1104 return kCFCompareGreaterThan;
1106 else
1107 return kCFCompareGreaterThan;
1109 else if (pf2.accum_mode)
1110 return kCFCompareLessThan;
1112 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1113 if (pf1.aux_buffers < pf2.aux_buffers)
1114 return kCFCompareLessThan;
1115 if (pf1.aux_buffers > pf2.aux_buffers)
1116 return kCFCompareGreaterThan;
1118 /* If we get here, arbitrarily sort based on code. */
1119 if (code1 < code2)
1120 return kCFCompareLessThan;
1121 if (code1 > code2)
1122 return kCFCompareGreaterThan;
1123 return kCFCompareEqualTo;
1127 static BOOL init_pixel_formats(void)
1129 BOOL ret = FALSE;
1130 CGLRendererInfoObj renderer_info;
1131 GLint rendererCount;
1132 CGLError err;
1133 CFMutableSetRef pixel_format_set;
1134 CFMutableArrayRef pixel_format_array;
1135 int i;
1136 CFRange range;
1138 TRACE("()\n");
1140 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1141 if (err)
1143 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1144 return FALSE;
1147 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1148 if (!pixel_format_set)
1150 WARN("CFSetCreateMutable failed\n");
1151 CGLDestroyRendererInfo(renderer_info);
1152 return FALSE;
1155 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1156 if (!pixel_format_array)
1158 WARN("CFArrayCreateMutable failed\n");
1159 CFRelease(pixel_format_set);
1160 CGLDestroyRendererInfo(renderer_info);
1161 return FALSE;
1164 for (i = 0; i < rendererCount; i++)
1166 renderer_properties renderer;
1168 get_renderer_properties(renderer_info, i, &renderer);
1169 if (TRACE_ON(wgl))
1171 TRACE("renderer_properties %d:\n", i);
1172 dump_renderer(&renderer);
1175 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1178 CFRelease(pixel_format_set);
1179 CGLDestroyRendererInfo(renderer_info);
1181 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1182 if (range.length)
1184 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1185 if (pixel_formats)
1187 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1188 for (i = 0; i < range.length; i++)
1190 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1191 UInt64 code;
1193 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1194 pixel_formats[i] = pixel_format_for_code(code);
1195 if (pixel_formats[i].window)
1196 nb_displayable_formats++;
1199 nb_formats = range.length;
1200 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1201 ret = TRUE;
1203 else
1204 WARN("failed to allocate pixel format list\n");
1206 else
1207 WARN("got no pixel formats\n");
1209 CFRelease(pixel_format_array);
1210 return ret;
1214 static inline BOOL is_valid_pixel_format(int format)
1216 return format > 0 && format <= nb_formats;
1220 static inline BOOL is_displayable_pixel_format(int format)
1222 return format > 0 && format <= nb_displayable_formats;
1226 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1228 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1229 * format in case of probing the number of pixel formats.
1231 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1233 TRACE("Returning format %d\n", format);
1234 return &pixel_formats[format - 1];
1236 return NULL;
1240 static BOOL init_gl_info(void)
1242 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1243 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1245 CGDirectDisplayID display = CGMainDisplayID();
1246 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1247 CGLPixelFormatAttribute attribs[] = {
1248 kCGLPFADisplayMask, displayMask,
1251 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1252 CGLPixelFormatAttribute core_attribs[] =
1254 kCGLPFADisplayMask, displayMask,
1255 kCGLPFAAccelerated,
1256 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1259 #endif
1260 CGLPixelFormatObj pix;
1261 GLint virtualScreens;
1262 CGLError err;
1263 CGLContextObj context;
1264 CGLContextObj old_context = CGLGetCurrentContext();
1265 const char *str;
1266 size_t length;
1268 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1269 if (err != kCGLNoError || !pix)
1271 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1272 return FALSE;
1275 err = CGLCreateContext(pix, NULL, &context);
1276 CGLReleasePixelFormat(pix);
1277 if (err != kCGLNoError || !context)
1279 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1280 return FALSE;
1283 err = CGLSetCurrentContext(context);
1284 if (err != kCGLNoError)
1286 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1287 CGLReleaseContext(context);
1288 return FALSE;
1291 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1292 length = strlen(str) + sizeof(legacy_extensions);
1293 if (allow_vsync)
1294 length += strlen(legacy_ext_swap_control);
1295 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1296 strcpy(gl_info.glExtensions, str);
1297 strcat(gl_info.glExtensions, legacy_extensions);
1298 if (allow_vsync)
1299 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1301 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1303 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1304 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1305 TRACE("GL version : %s\n", str);
1306 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1308 CGLSetCurrentContext(old_context);
1309 CGLReleaseContext(context);
1311 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1312 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1313 if (err != kCGLNoError || !pix)
1315 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1316 err, CGLErrorString(err));
1317 return TRUE;
1320 err = CGLCreateContext(pix, NULL, &context);
1321 CGLReleasePixelFormat(pix);
1322 if (err != kCGLNoError || !context)
1324 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1325 err, CGLErrorString(err));
1326 return TRUE;
1329 err = CGLSetCurrentContext(context);
1330 if (err != kCGLNoError)
1332 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1333 err, CGLErrorString(err));
1334 CGLReleaseContext(context);
1335 return TRUE;
1338 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1339 TRACE("Core context GL version: %s\n", str);
1340 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1341 CGLSetCurrentContext(old_context);
1342 CGLReleaseContext(context);
1343 #endif
1345 return TRUE;
1349 static int get_dc_pixel_format(HDC hdc)
1351 int format;
1352 HWND hwnd;
1354 if ((hwnd = WindowFromDC(hdc)))
1356 struct macdrv_win_data *data;
1358 if (!(data = get_win_data(hwnd)))
1360 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1361 return 0;
1364 format = data->pixel_format;
1365 release_win_data(data);
1367 else
1369 struct wgl_pbuffer *pbuffer;
1371 EnterCriticalSection(&dc_pbuffers_section);
1372 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1373 if (pbuffer)
1374 format = pbuffer->format;
1375 else
1377 WARN("no window or pbuffer for DC %p\n", hdc);
1378 format = 0;
1380 LeaveCriticalSection(&dc_pbuffers_section);
1383 return format;
1387 /**********************************************************************
1388 * create_context
1390 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1392 const pixel_format *pf;
1393 CGLPixelFormatAttribute attribs[64];
1394 int n = 0;
1395 CGLPixelFormatObj pix;
1396 GLint virtualScreens;
1397 CGLError err;
1398 BOOL core = major >= 3;
1400 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1401 if (core)
1403 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1404 return FALSE;
1406 #endif
1408 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1409 if (!pf)
1411 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1412 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1413 return FALSE;
1416 attribs[n++] = kCGLPFAMinimumPolicy;
1417 attribs[n++] = kCGLPFAClosestPolicy;
1419 if (context->renderer_id)
1421 attribs[n++] = kCGLPFARendererID;
1422 attribs[n++] = context->renderer_id;
1423 attribs[n++] = kCGLPFASingleRenderer;
1424 attribs[n++] = kCGLPFANoRecovery;
1427 if (pf->accelerated)
1429 attribs[n++] = kCGLPFAAccelerated;
1430 attribs[n++] = kCGLPFANoRecovery;
1432 else
1434 attribs[n++] = kCGLPFARendererID;
1435 attribs[n++] = kCGLRendererGenericFloatID;
1438 if (pf->double_buffer)
1439 attribs[n++] = kCGLPFADoubleBuffer;
1441 if (!core)
1443 attribs[n++] = kCGLPFAAuxBuffers;
1444 attribs[n++] = pf->aux_buffers;
1447 attribs[n++] = kCGLPFAColorSize;
1448 attribs[n++] = color_modes[pf->color_mode].color_bits;
1449 attribs[n++] = kCGLPFAAlphaSize;
1450 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1451 if (color_modes[pf->color_mode].is_float)
1452 attribs[n++] = kCGLPFAColorFloat;
1454 attribs[n++] = kCGLPFADepthSize;
1455 attribs[n++] = pf->depth_bits;
1457 attribs[n++] = kCGLPFAStencilSize;
1458 attribs[n++] = pf->stencil_bits;
1460 if (pf->stereo)
1461 attribs[n++] = kCGLPFAStereo;
1463 if (pf->accum_mode && !core)
1465 attribs[n++] = kCGLPFAAccumSize;
1466 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1469 if (pf->pbuffer && !core)
1470 attribs[n++] = kCGLPFAPBuffer;
1472 if (pf->sample_buffers && pf->samples)
1474 attribs[n++] = kCGLPFASampleBuffers;
1475 attribs[n++] = pf->sample_buffers;
1476 attribs[n++] = kCGLPFASamples;
1477 attribs[n++] = pf->samples;
1480 if (pf->backing_store)
1481 attribs[n++] = kCGLPFABackingStore;
1483 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1484 if (core)
1486 attribs[n++] = kCGLPFAOpenGLProfile;
1487 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1488 if (major == 3)
1489 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1490 else
1491 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1492 #else
1493 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1494 #endif
1496 #endif
1498 attribs[n] = 0;
1500 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1501 if (err != kCGLNoError || !pix)
1503 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1504 SetLastError(ERROR_INVALID_OPERATION);
1505 return FALSE;
1508 err = CGLCreateContext(pix, share, &context->cglcontext);
1509 CGLReleasePixelFormat(pix);
1510 if (err != kCGLNoError || !context->cglcontext)
1512 context->cglcontext = NULL;
1513 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1514 SetLastError(ERROR_INVALID_OPERATION);
1515 return FALSE;
1518 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1520 GLint opacity = 0;
1521 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1522 if (err != kCGLNoError)
1523 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1525 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1527 GLint order = -1;
1528 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1529 if (err != kCGLNoError)
1530 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1533 context->context = macdrv_create_opengl_context(context->cglcontext);
1534 CGLReleaseContext(context->cglcontext);
1535 if (!context->context)
1537 WARN("macdrv_create_opengl_context() failed\n");
1538 SetLastError(ERROR_INVALID_OPERATION);
1539 return FALSE;
1541 context->major = major;
1543 if (allow_vsync)
1544 InterlockedExchange(&context->update_swap_interval, TRUE);
1546 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1548 return TRUE;
1552 /**********************************************************************
1553 * set_pixel_format
1555 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1557 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1559 struct macdrv_win_data *data;
1560 const pixel_format *pf;
1561 HWND hwnd = WindowFromDC(hdc);
1562 BOOL ret = FALSE;
1564 TRACE("hdc %p format %d\n", hdc, fmt);
1566 if (!hwnd || hwnd == GetDesktopWindow())
1568 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1569 return FALSE;
1572 if (!(data = get_win_data(hwnd)))
1574 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1575 return FALSE;
1578 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1580 ret = (data->pixel_format == fmt);
1581 goto done;
1584 /* Check if fmt is in our list of supported formats to see if it is supported. */
1585 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1586 if (!pf)
1588 ERR("Invalid pixel format: %d\n", fmt);
1589 goto done;
1592 if (!pf->window)
1594 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1595 goto done;
1598 data->pixel_format = fmt;
1600 TRACE("pixel format:\n");
1601 TRACE(" window: %u\n", (unsigned int)pf->window);
1602 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1603 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1604 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1605 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1606 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1607 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1608 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1609 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1610 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1611 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1612 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1613 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1614 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1615 ret = TRUE;
1617 done:
1618 release_win_data(data);
1619 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
1620 return ret;
1624 /**********************************************************************
1625 * mark_contexts_for_moved_view
1627 static void mark_contexts_for_moved_view(macdrv_view view)
1629 struct wgl_context *context;
1631 EnterCriticalSection(&context_section);
1632 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1634 if (context->draw_view == view)
1635 InterlockedExchange(&context->view_moved, TRUE);
1637 LeaveCriticalSection(&context_section);
1641 /**********************************************************************
1642 * sync_context_rect
1644 static BOOL sync_context_rect(struct wgl_context *context)
1646 BOOL ret = FALSE;
1647 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1649 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1651 if (data && data->client_cocoa_view == context->draw_view)
1653 RECT rect = data->client_rect;
1654 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1655 if (!EqualRect(&context->draw_rect, &rect))
1657 context->draw_rect = rect;
1658 ret = TRUE;
1661 release_win_data(data);
1663 return ret;
1667 /**********************************************************************
1668 * make_context_current
1670 static void make_context_current(struct wgl_context *context, BOOL read)
1672 macdrv_view view;
1673 RECT view_rect;
1674 struct wgl_pbuffer *pbuffer;
1676 if (read)
1678 view = context->read_view;
1679 view_rect = context->read_rect;
1680 pbuffer = context->read_pbuffer;
1682 else
1684 sync_context_rect(context);
1686 view = context->draw_view;
1687 view_rect = context->draw_rect;
1688 pbuffer = context->draw_pbuffer;
1691 if (view || !pbuffer)
1692 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1693 else
1695 GLint enabled;
1697 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1698 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1699 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1700 pbuffer->level, 0);
1701 CGLSetCurrentContext(context->cglcontext);
1706 /**********************************************************************
1707 * sync_context
1709 static void sync_context(struct wgl_context *context)
1711 if (sync_context_rect(context))
1712 make_context_current(context, FALSE);
1716 /**********************************************************************
1717 * set_swap_interval
1719 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1721 CGLError err;
1723 /* In theory, for single-buffered contexts, there's no such thing as a swap
1724 so the swap interval shouldn't matter. But OS X will synchronize flushes
1725 of single-buffered contexts if the interval is set to non-zero. */
1726 if (interval && !pixel_formats[context->format - 1].double_buffer)
1727 interval = 0;
1729 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1730 if (err != kCGLNoError)
1731 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1733 return err == kCGLNoError;
1737 /**********************************************************************
1738 * sync_swap_interval
1740 static void sync_swap_interval(struct wgl_context *context)
1742 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1744 int interval;
1746 if (context->draw_hwnd)
1748 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1749 if (data)
1751 interval = data->swap_interval;
1752 release_win_data(data);
1754 else /* window was destroyed? */
1755 interval = 1;
1757 else /* pbuffer */
1758 interval = 0;
1760 set_swap_interval(context, interval);
1765 /**********************************************************************
1766 * get_iokit_display_property
1768 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1770 GLint accelerated;
1771 GLint display_mask;
1772 int i;
1774 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1776 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1777 return FALSE;
1780 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1782 WARN("failed to get kCGLRPDisplayMask\n");
1783 return FALSE;
1786 for (i = 0; i < sizeof(GLint) * 8; i++)
1788 GLint this_display_mask = (GLint)(1U << i);
1789 if (this_display_mask & display_mask)
1791 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1792 io_service_t service;
1793 CFDataRef data;
1794 uint32_t prop_value;
1796 if (!display_id)
1797 continue;
1798 service = CGDisplayIOServicePort(display_id);
1799 if (!service)
1801 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1802 continue;
1805 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1806 kIORegistryIterateRecursively | kIORegistryIterateParents);
1807 if (!data)
1809 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1810 continue;
1812 if (CFGetTypeID(data) != CFDataGetTypeID())
1814 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1815 CFRelease(data);
1816 continue;
1818 if (CFDataGetLength(data) != sizeof(prop_value))
1820 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1821 (unsigned long long)CFDataGetLength(data));
1822 CFRelease(data);
1823 continue;
1826 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1827 CFRelease(data);
1828 *value = prop_value;
1829 return TRUE;
1833 return FALSE;
1837 /**********************************************************************
1838 * create_pixel_format_for_renderer
1840 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1841 * responsible for releasing the pixel format object.
1843 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1845 GLint renderer_id;
1846 CGLPixelFormatAttribute attrs[] = {
1847 kCGLPFARendererID, 0,
1848 kCGLPFASingleRenderer,
1849 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1852 CGError err;
1853 CGLPixelFormatObj pixel_format;
1854 GLint virtual_screens;
1856 if (core)
1858 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1859 attrs[3] = kCGLPFAOpenGLProfile;
1860 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1861 #else
1862 return NULL;
1863 #endif
1866 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1867 return NULL;
1869 attrs[1] = renderer_id;
1870 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1871 if (err != kCGLNoError)
1872 pixel_format = NULL;
1873 return pixel_format;
1877 /**********************************************************************
1878 * map_renderer_index
1880 * We can't create pixel formats for all renderers listed. For example,
1881 * in a dual-GPU system, the integrated GPU is typically unavailable
1882 * when the discrete GPU is active.
1884 * This function conceptually creates a list of "good" renderers from the
1885 * list of all renderers. It treats the input "renderer" parameter as an
1886 * index into that list of good renderers and returns the corresponding
1887 * index into the list of all renderers.
1889 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1891 GLint good_count, i;
1893 good_count = 0;
1894 for (i = 0; i < renderer_count; i++)
1896 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1897 if (pix)
1899 CGLReleasePixelFormat(pix);
1900 good_count++;
1901 if (good_count > renderer)
1902 break;
1904 else
1905 TRACE("skipping bad renderer %d\n", i);
1908 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1909 return i;
1913 /**********************************************************************
1914 * get_gl_string
1916 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1918 const char* ret = NULL;
1919 CGLContextObj context, old_context;
1920 CGLError err;
1922 err = CGLCreateContext(pixel_format, NULL, &context);
1923 if (err == kCGLNoError && context)
1925 old_context = CGLGetCurrentContext();
1926 err = CGLSetCurrentContext(context);
1927 if (err == kCGLNoError)
1929 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1930 CGLSetCurrentContext(old_context);
1932 else
1933 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1934 CGLReleaseContext(context);
1936 else
1937 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1939 return ret;
1943 /**********************************************************************
1944 * get_fallback_renderer_version
1946 static void get_fallback_renderer_version(GLuint *value)
1948 BOOL got_it = FALSE;
1949 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1950 kCFURLPOSIXPathStyle, TRUE);
1951 if (url)
1953 CFBundleRef bundle = CFBundleCreate(NULL, url);
1954 CFRelease(url);
1955 if (bundle)
1957 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1958 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1960 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1961 char* buf = HeapAlloc(GetProcessHeap(), 0, len);
1962 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1964 unsigned int major, minor, bugfix;
1965 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1966 if (count >= 2)
1968 value[0] = major;
1969 value[1] = minor;
1970 if (count == 3)
1971 value[2] = bugfix;
1972 else
1973 value[2] = 0;
1974 got_it = TRUE;
1977 HeapFree(GetProcessHeap(), 0, buf);
1979 CFRelease(bundle);
1983 if (!got_it)
1985 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1986 earliest version that the Mac driver supports. */
1987 value[0] = 1;
1988 value[1] = 6;
1989 value[2] = 14;
1994 /**********************************************************************
1995 * parse_renderer_version
1997 * Get the renderer version from the OpenGL version string. Assumes
1998 * the string is of the form
1999 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2000 * where major, minor, and bugfix are what we're interested in. This
2001 * form for the vendor specific information is not generally applicable,
2002 * but seems reliable on OS X.
2004 static BOOL parse_renderer_version(const char* version, GLuint *value)
2006 const char* p = strchr(version, ' ');
2007 int count;
2008 unsigned int major, minor, bugfix;
2010 if (p) p = strchr(p + 1, '-');
2011 if (!p) return FALSE;
2013 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
2014 if (count < 2)
2015 return FALSE;
2017 value[0] = major;
2018 value[1] = minor;
2019 if (count == 3)
2020 value[2] = bugfix;
2021 else
2022 value[2] = 0;
2024 return TRUE;
2028 /**********************************************************************
2029 * query_renderer_integer
2031 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2033 BOOL ret = FALSE;
2034 CGLError err;
2036 if (TRACE_ON(wgl))
2038 GLint renderer_id;
2039 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2040 renderer_id = 0;
2041 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2044 switch (attribute)
2046 case WGL_RENDERER_ACCELERATED_WINE:
2047 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2048 break;
2049 *value = !!*value;
2050 ret = TRUE;
2051 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2052 break;
2054 case WGL_RENDERER_DEVICE_ID_WINE:
2055 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2056 if (!ret)
2058 *value = 0xffffffff;
2059 ret = TRUE;
2061 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2062 break;
2064 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2065 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2067 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2068 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2070 if (pixel_format)
2072 const char* version = get_gl_string(pixel_format, GL_VERSION);
2074 CGLReleasePixelFormat(pixel_format);
2075 if (version)
2077 unsigned int major, minor;
2079 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2081 value[0] = major;
2082 value[1] = minor;
2083 ret = TRUE;
2088 if (!ret)
2090 value[0] = value[1] = 0;
2091 ret = TRUE;
2093 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2094 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2095 break;
2098 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2100 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2102 if (pixel_format)
2104 CGLReleasePixelFormat(pixel_format);
2105 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2106 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2108 else
2110 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2111 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2113 ret = TRUE;
2114 break;
2117 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2118 /* FIXME: no API to query this */
2119 *value = 0;
2120 ret = TRUE;
2121 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2122 break;
2124 case WGL_RENDERER_VENDOR_ID_WINE:
2125 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2126 if (!ret)
2128 *value = 0xffffffff;
2129 ret = TRUE;
2131 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2132 break;
2134 case WGL_RENDERER_VERSION_WINE:
2136 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2138 if (!pixel_format)
2139 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2140 if (pixel_format)
2142 const char* version = get_gl_string(pixel_format, GL_VERSION);
2144 CGLReleasePixelFormat(pixel_format);
2145 if (version)
2146 ret = parse_renderer_version(version, value);
2149 if (!ret)
2151 get_fallback_renderer_version(value);
2152 ret = TRUE;
2154 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2155 break;
2158 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2159 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2160 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2161 if (err != kCGLNoError && err != kCGLBadProperty)
2162 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2163 if (err != kCGLNoError)
2164 #endif
2166 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2167 *value /= 1024 * 1024;
2168 else
2169 *value = 0;
2171 ret = TRUE;
2172 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2173 break;
2175 default:
2176 FIXME("unrecognized attribute 0x%04x\n", attribute);
2177 break;
2180 return ret;
2184 /**********************************************************************
2185 * macdrv_glCopyColorTable
2187 * Hook into glCopyColorTable as part of the implementation of
2188 * wglMakeContextCurrentARB. If the context has a separate readable,
2189 * temporarily make that current, do glCopyColorTable, and then set it
2190 * back to the drawable. This is modeled after what Mesa GLX's Apple
2191 * implementation does.
2193 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2194 GLsizei width)
2196 struct wgl_context *context = NtCurrentTeb()->glContext;
2198 if (context->read_view || context->read_pbuffer)
2199 make_context_current(context, TRUE);
2201 pglCopyColorTable(target, internalformat, x, y, width);
2203 if (context->read_view || context->read_pbuffer)
2204 make_context_current(context, FALSE);
2208 /**********************************************************************
2209 * macdrv_glCopyPixels
2211 * Hook into glCopyPixels as part of the implementation of
2212 * wglMakeContextCurrentARB. If the context has a separate readable,
2213 * temporarily make that current, do glCopyPixels, and then set it back
2214 * to the drawable. This is modeled after what Mesa GLX's Apple
2215 * implementation does.
2217 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2219 struct wgl_context *context = NtCurrentTeb()->glContext;
2221 if (context->read_view || context->read_pbuffer)
2222 make_context_current(context, TRUE);
2224 pglCopyPixels(x, y, width, height, type);
2226 if (context->read_view || context->read_pbuffer)
2227 make_context_current(context, FALSE);
2231 /**********************************************************************
2232 * macdrv_glFinish
2234 static void macdrv_glFinish(void)
2236 struct wgl_context *context = NtCurrentTeb()->glContext;
2238 sync_swap_interval(context);
2239 sync_context(context);
2240 pglFinish();
2244 /**********************************************************************
2245 * macdrv_glFlush
2247 static void macdrv_glFlush(void)
2249 struct wgl_context *context = NtCurrentTeb()->glContext;
2251 sync_swap_interval(context);
2252 sync_context(context);
2254 if (skip_single_buffer_flushes)
2256 const pixel_format *pf = &pixel_formats[context->format - 1];
2257 DWORD now = GetTickCount();
2259 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2260 context->last_flush_time, now);
2261 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2263 TRACE("calling glFlushRenderAPPLE()\n");
2264 pglFlushRenderAPPLE();
2265 return;
2267 else
2269 TRACE("calling glFlush()\n");
2270 context->last_flush_time = now;
2274 pglFlush();
2278 /**********************************************************************
2279 * macdrv_glGetString
2281 * Hook into glGetString in order to return some legacy WGL extensions
2282 * that couldn't be advertised via the standard
2283 * WGL_ARB_extensions_string mechanism. Some programs, especially
2284 * older ones, expect to find certain older extensions, such as
2285 * WGL_EXT_extensions_string itself, in the standard GL extensions
2286 * string, and won't query any other WGL extensions unless they find
2287 * that particular extension there.
2289 static const GLubyte *macdrv_glGetString(GLenum name)
2291 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2292 return (const GLubyte *)gl_info.glExtensions;
2293 else
2294 return pglGetString(name);
2298 /**********************************************************************
2299 * macdrv_glReadPixels
2301 * Hook into glReadPixels as part of the implementation of
2302 * wglMakeContextCurrentARB. If the context has a separate readable,
2303 * temporarily make that current, do glReadPixels, and then set it back
2304 * to the drawable. This is modeled after what Mesa GLX's Apple
2305 * implementation does.
2307 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2308 GLenum format, GLenum type, void *pixels)
2310 struct wgl_context *context = NtCurrentTeb()->glContext;
2312 if (context->read_view || context->read_pbuffer)
2313 make_context_current(context, TRUE);
2315 pglReadPixels(x, y, width, height, format, type, pixels);
2317 if (context->read_view || context->read_pbuffer)
2318 make_context_current(context, FALSE);
2322 /**********************************************************************
2323 * macdrv_glViewport
2325 * Hook into glViewport as an opportunity to update the OpenGL context
2326 * if necessary. This is modeled after what Mesa GLX's Apple
2327 * implementation does.
2329 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2331 struct wgl_context *context = NtCurrentTeb()->glContext;
2333 sync_context(context);
2334 macdrv_update_opengl_context(context->context);
2335 pglViewport(x, y, width, height);
2339 /***********************************************************************
2340 * macdrv_wglBindTexImageARB
2342 * WGL_ARB_render_texture: wglBindTexImageARB
2344 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2346 struct wgl_context *context = NtCurrentTeb()->glContext;
2347 GLenum source;
2348 CGLError err;
2350 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2352 if (pbuffer->no_texture)
2354 SetLastError(ERROR_INVALID_OPERATION);
2355 return GL_FALSE;
2358 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2359 opengl_funcs.gl.p_glFlush();
2361 switch (iBuffer)
2363 case WGL_FRONT_LEFT_ARB:
2364 if (pixel_formats[pbuffer->format - 1].stereo)
2365 source = GL_FRONT_LEFT;
2366 else
2367 source = GL_FRONT;
2368 break;
2369 case WGL_FRONT_RIGHT_ARB:
2370 source = GL_FRONT_RIGHT;
2371 break;
2372 case WGL_BACK_LEFT_ARB:
2373 if (pixel_formats[pbuffer->format - 1].stereo)
2374 source = GL_BACK_LEFT;
2375 else
2376 source = GL_BACK;
2377 break;
2378 case WGL_BACK_RIGHT_ARB:
2379 source = GL_BACK_RIGHT;
2380 break;
2381 case WGL_AUX0_ARB: source = GL_AUX0; break;
2382 case WGL_AUX1_ARB: source = GL_AUX1; break;
2383 case WGL_AUX2_ARB: source = GL_AUX2; break;
2384 case WGL_AUX3_ARB: source = GL_AUX3; break;
2386 case WGL_AUX4_ARB:
2387 case WGL_AUX5_ARB:
2388 case WGL_AUX6_ARB:
2389 case WGL_AUX7_ARB:
2390 case WGL_AUX8_ARB:
2391 case WGL_AUX9_ARB:
2392 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2393 SetLastError(ERROR_INVALID_DATA);
2394 return GL_FALSE;
2396 default:
2397 WARN("unknown source buffer 0x%x\n", iBuffer);
2398 SetLastError(ERROR_INVALID_DATA);
2399 return GL_FALSE;
2402 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2403 if (err != kCGLNoError)
2405 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2406 SetLastError(ERROR_INVALID_OPERATION);
2407 return GL_FALSE;
2410 return GL_TRUE;
2414 /***********************************************************************
2415 * macdrv_wglChoosePixelFormatARB
2417 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2419 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2420 const FLOAT *pfAttribFList, UINT nMaxFormats,
2421 int *piFormats, UINT *nNumFormats)
2423 pixel_format pf, valid;
2424 const int *iptr;
2425 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2426 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2427 int float_color;
2428 BOOL srgb;
2429 int i, found = 0;
2431 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2432 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2433 if (pfAttribFList)
2434 FIXME("unused pfAttribFList\n");
2436 memset(&pf, 0, sizeof(pf));
2437 memset(&valid, 0, sizeof(valid));
2438 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2439 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2440 float_color = -1;
2441 srgb = FALSE;
2443 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2445 int attr = iptr[0];
2446 int value = iptr[1];
2448 TRACE("%s\n", debugstr_attrib(attr, value));
2450 switch (attr)
2452 case WGL_DRAW_TO_WINDOW_ARB:
2453 if (valid.window && (!pf.window != !value)) goto cant_match;
2454 pf.window = (value != 0);
2455 valid.window = 1;
2456 break;
2458 case WGL_DRAW_TO_BITMAP_ARB:
2459 goto cant_match;
2461 case WGL_ACCELERATION_ARB:
2462 if (value == WGL_FULL_ACCELERATION_ARB)
2463 value = 1;
2464 else if (value == WGL_NO_ACCELERATION_ARB)
2465 value = 0;
2466 else
2467 goto cant_match;
2468 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2469 pf.accelerated = value;
2470 valid.accelerated = 1;
2471 break;
2473 case WGL_NEED_PALETTE_ARB:
2474 case WGL_NEED_SYSTEM_PALETTE_ARB:
2475 case WGL_SWAP_LAYER_BUFFERS_ARB:
2476 if (value) goto cant_match;
2477 break;
2479 case WGL_SWAP_METHOD_ARB:
2480 if (value == WGL_SWAP_COPY_ARB)
2481 value = 1;
2482 else if (value == WGL_SWAP_UNDEFINED_ARB)
2483 value = 0;
2484 else
2485 goto cant_match;
2486 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2487 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2488 pf.backing_store = value;
2489 valid.backing_store = 1;
2490 break;
2492 case WGL_NUMBER_OVERLAYS_ARB:
2493 case WGL_NUMBER_UNDERLAYS_ARB:
2494 if (value) goto cant_match;
2495 break;
2497 case WGL_SHARE_DEPTH_ARB:
2498 case WGL_SHARE_STENCIL_ARB:
2499 case WGL_SHARE_ACCUM_ARB:
2500 /* no effect */
2501 break;
2503 case WGL_SUPPORT_GDI_ARB:
2504 if (value) goto cant_match;
2505 break;
2507 case WGL_SUPPORT_OPENGL_ARB:
2508 if (!value) goto cant_match;
2509 break;
2511 case WGL_DOUBLE_BUFFER_ARB:
2512 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2513 pf.double_buffer = (value != 0);
2514 valid.double_buffer = 1;
2515 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2516 break;
2518 case WGL_STEREO_ARB:
2519 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2520 pf.stereo = (value != 0);
2521 valid.stereo = 1;
2522 break;
2524 case WGL_PIXEL_TYPE_ARB:
2525 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2526 value = 1;
2527 else if (value == WGL_TYPE_RGBA_ARB)
2528 value = 0;
2529 else
2531 /* Mac contexts don't support rendering to unsigned floating
2532 point formats, even if GL_EXT_packed_float is supported.
2533 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2534 goto cant_match;
2536 if (float_color != -1 && float_color != value) goto cant_match;
2537 if (srgb && value) goto cant_match;
2538 float_color = value;
2539 break;
2541 case WGL_COLOR_BITS_ARB:
2542 if (color_bits < value) color_bits = value;
2543 break;
2545 case WGL_RED_BITS_ARB:
2546 if (srgb && value > 8) goto cant_match;
2547 if (red_bits < value) red_bits = value;
2548 break;
2550 case WGL_GREEN_BITS_ARB:
2551 if (srgb && value > 8) goto cant_match;
2552 if (green_bits < value) green_bits = value;
2553 break;
2555 case WGL_BLUE_BITS_ARB:
2556 if (srgb && value > 8) goto cant_match;
2557 if (blue_bits < value) blue_bits = value;
2558 break;
2560 case WGL_ALPHA_BITS_ARB:
2561 if (alpha_bits < value) alpha_bits = value;
2562 break;
2564 case WGL_ACCUM_BITS_ARB:
2565 if (accum_bits < value) accum_bits = value;
2566 break;
2568 case WGL_ACCUM_RED_BITS_ARB:
2569 if (accum_red_bits < value) accum_red_bits = value;
2570 break;
2572 case WGL_ACCUM_GREEN_BITS_ARB:
2573 if (accum_green_bits < value) accum_green_bits = value;
2574 break;
2576 case WGL_ACCUM_BLUE_BITS_ARB:
2577 if (accum_blue_bits < value) accum_blue_bits = value;
2578 break;
2580 case WGL_ACCUM_ALPHA_BITS_ARB:
2581 if (accum_alpha_bits < value) accum_alpha_bits = value;
2582 break;
2584 case WGL_DEPTH_BITS_ARB:
2585 if (value > 255) goto cant_match;
2586 if (pf.depth_bits < value) pf.depth_bits = value;
2587 break;
2589 case WGL_STENCIL_BITS_ARB:
2590 if (value > 255) goto cant_match;
2591 if (pf.stencil_bits < value) pf.stencil_bits = value;
2592 break;
2594 case WGL_AUX_BUFFERS_ARB:
2595 if (value > 7) goto cant_match;
2596 if (pf.aux_buffers < value) pf.aux_buffers = value;
2597 break;
2599 case WGL_SAMPLE_BUFFERS_ARB:
2600 if (value > 1) goto cant_match;
2601 if (pf.sample_buffers < value) pf.sample_buffers = value;
2602 break;
2604 case WGL_SAMPLES_ARB:
2605 if (value > 31) goto cant_match;
2606 if (pf.samples < value) pf.samples = value;
2607 break;
2609 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2610 /* sRGB is only supported for 8-bit integer color components */
2611 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2612 goto cant_match;
2613 srgb = TRUE;
2614 break;
2616 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2617 case WGL_RED_SHIFT_ARB:
2618 case WGL_GREEN_SHIFT_ARB:
2619 case WGL_BLUE_SHIFT_ARB:
2620 case WGL_ALPHA_SHIFT_ARB:
2621 case WGL_TRANSPARENT_ARB:
2622 case WGL_TRANSPARENT_RED_VALUE_ARB:
2623 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2624 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2625 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2626 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2627 /* ignored */
2628 break;
2630 case WGL_DRAW_TO_PBUFFER_ARB:
2631 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2632 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2633 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2634 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2635 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2636 pf.pbuffer = (value != 0);
2637 valid.pbuffer = 1;
2638 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2639 !alpha_bits)
2640 alpha_bits = 1;
2641 break;
2643 default:
2644 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2645 return GL_FALSE;
2649 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",
2650 valid.window ? (pf.window ? "1" : "0") : "?",
2651 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2652 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2653 color_bits,
2654 float_color == -1 ? "?" : float_color ? "f" : "",
2655 red_bits,
2656 green_bits,
2657 blue_bits,
2658 alpha_bits,
2659 (int)srgb,
2660 accum_bits,
2661 accum_red_bits,
2662 accum_green_bits,
2663 accum_blue_bits,
2664 accum_alpha_bits,
2665 pf.depth_bits,
2666 pf.stencil_bits,
2667 pf.aux_buffers,
2668 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2669 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2670 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2671 pf.sample_buffers,
2672 pf.samples);
2674 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2676 const struct color_mode *mode;
2678 if (valid.window && pixel_formats[i].window != pf.window) continue;
2679 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2680 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2681 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2682 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2683 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2685 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2686 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2687 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2688 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2689 if (pixel_formats[i].samples < pf.samples) continue;
2691 mode = &color_modes[pixel_formats[i].color_mode];
2692 /* If the mode doesn't have alpha, check requested color bits against
2693 bits per pixel instead of the mode's color bits. On Windows, color
2694 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2695 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2696 expects that to match such a pixel format, we need to accommodate that. */
2697 if (mode->alpha_bits)
2699 if (mode->color_bits < color_bits)
2700 continue;
2702 else
2704 if (mode->bits_per_pixel < color_bits)
2705 continue;
2707 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2708 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2709 continue;
2710 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2711 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2712 continue;
2714 if (pixel_formats[i].accum_mode)
2716 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2717 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2718 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2719 mode->alpha_bits < accum_alpha_bits)
2720 continue;
2722 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2723 continue;
2725 piFormats[found++] = i + 1;
2726 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2729 cant_match:
2730 *nNumFormats = found;
2732 return TRUE;
2736 /***********************************************************************
2737 * macdrv_wglCreateContextAttribsARB
2739 * WGL_ARB_create_context: wglCreateContextAttribsARB
2741 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2742 struct wgl_context *share_context,
2743 const int *attrib_list)
2745 int format;
2746 struct wgl_context *context;
2747 const int *iptr;
2748 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2749 BOOL core = FALSE;
2750 GLint renderer_id = 0;
2752 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2754 format = get_dc_pixel_format(hdc);
2756 if (!is_valid_pixel_format(format))
2758 ERR("Invalid pixel format %d, expect problems!\n", format);
2759 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2760 return NULL;
2763 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2765 int attr = iptr[0];
2766 int value = iptr[1];
2768 TRACE("%s\n", debugstr_attrib(attr, value));
2770 switch (attr)
2772 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2773 major = value;
2774 break;
2776 case WGL_CONTEXT_MINOR_VERSION_ARB:
2777 minor = value;
2778 break;
2780 case WGL_CONTEXT_LAYER_PLANE_ARB:
2781 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2782 break;
2784 case WGL_CONTEXT_FLAGS_ARB:
2785 flags = value;
2786 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2787 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2788 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2789 break;
2791 case WGL_CONTEXT_PROFILE_MASK_ARB:
2792 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2793 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2795 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2796 SetLastError(ERROR_INVALID_PROFILE_ARB);
2797 return NULL;
2799 profile = value;
2800 break;
2802 case WGL_RENDERER_ID_WINE:
2804 CGLError err;
2805 CGLRendererInfoObj renderer_info;
2806 GLint renderer_count, temp;
2808 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2809 if (err != kCGLNoError)
2811 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2812 SetLastError(ERROR_GEN_FAILURE);
2813 return NULL;
2816 value = map_renderer_index(renderer_info, renderer_count, value);
2818 if (value >= renderer_count)
2820 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2821 CGLDestroyRendererInfo(renderer_info);
2822 SetLastError(ERROR_INVALID_PARAMETER);
2823 return NULL;
2826 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2828 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2829 CGLDestroyRendererInfo(renderer_info);
2830 SetLastError(ERROR_GEN_FAILURE);
2831 return NULL;
2834 CGLDestroyRendererInfo(renderer_info);
2836 if (renderer_id && temp != renderer_id)
2838 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2839 SetLastError(ERROR_INVALID_PARAMETER);
2840 return NULL;
2842 renderer_id = temp;
2843 break;
2846 default:
2847 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2848 SetLastError(ERROR_INVALID_PARAMETER);
2849 return NULL;
2853 if ((major == 3 && (minor == 2 || minor == 3)) ||
2854 (major == 4 && (minor == 0 || minor == 1)))
2856 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2858 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2859 SetLastError(ERROR_INVALID_VERSION_ARB);
2860 return NULL;
2862 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2864 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2865 SetLastError(ERROR_INVALID_PROFILE_ARB);
2866 return NULL;
2868 if (major > gl_info.max_major ||
2869 (major == gl_info.max_major && minor > gl_info.max_minor))
2871 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2872 major, minor);
2873 SetLastError(ERROR_INVALID_PROFILE_ARB);
2874 return NULL;
2876 core = TRUE;
2878 else if (major >= 3)
2880 WARN("Profile version %u.%u not supported\n", major, minor);
2881 SetLastError(ERROR_INVALID_VERSION_ARB);
2882 return NULL;
2884 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2885 (major == 2 && (minor < 0 || minor > 1)))
2887 WARN("Invalid GL version requested\n");
2888 SetLastError(ERROR_INVALID_VERSION_ARB);
2889 return NULL;
2891 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2893 WARN("Forward compatible context requested for GL version < 3\n");
2894 SetLastError(ERROR_INVALID_VERSION_ARB);
2895 return NULL;
2898 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2900 context->format = format;
2901 context->renderer_id = renderer_id;
2902 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2904 HeapFree(GetProcessHeap(), 0, context);
2905 return NULL;
2908 EnterCriticalSection(&context_section);
2909 list_add_tail(&context_list, &context->entry);
2910 LeaveCriticalSection(&context_section);
2912 return context;
2916 /**********************************************************************
2917 * macdrv_wglCreatePbufferARB
2919 * WGL_ARB_pbuffer: wglCreatePbufferARB
2921 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2922 const int *piAttribList)
2924 struct wgl_pbuffer* pbuffer;
2925 GLenum target = 0;
2926 GLenum internalFormat = 0;
2927 CGLError err;
2929 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2930 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2932 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2934 WARN("invalid pixel format %d\n", iPixelFormat);
2935 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2936 return NULL;
2939 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2940 pbuffer->format = iPixelFormat;
2942 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2944 int attr = piAttribList[0];
2945 int value = piAttribList[1];
2947 switch (attr)
2949 case WGL_PBUFFER_LARGEST_ARB:
2950 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2951 break;
2953 case WGL_TEXTURE_FORMAT_ARB:
2954 switch (value)
2956 case WGL_TEXTURE_RGBA_ARB:
2957 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2958 internalFormat = GL_RGBA;
2959 break;
2960 case WGL_TEXTURE_RGB_ARB:
2961 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2962 internalFormat = GL_RGB;
2963 break;
2964 case WGL_NO_TEXTURE_ARB:
2965 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2966 internalFormat = 0;
2967 break;
2968 default:
2969 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2970 SetLastError(ERROR_INVALID_DATA);
2971 goto done;
2973 break;
2975 case WGL_TEXTURE_TARGET_ARB:
2976 pbuffer->face = 0;
2977 switch (value)
2979 case WGL_NO_TEXTURE_ARB:
2980 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2981 target = 0;
2982 break;
2983 case WGL_TEXTURE_CUBE_MAP_ARB:
2984 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2985 target = GL_TEXTURE_CUBE_MAP;
2986 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2987 break;
2988 case WGL_TEXTURE_1D_ARB:
2989 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2990 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2991 goto done;
2992 case WGL_TEXTURE_2D_ARB:
2993 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2994 target = GL_TEXTURE_2D;
2995 break;
2996 case WGL_TEXTURE_RECTANGLE_NV:
2997 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2998 target = GL_TEXTURE_RECTANGLE;
2999 break;
3000 default:
3001 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
3002 SetLastError(ERROR_INVALID_DATA);
3003 goto done;
3005 break;
3007 case WGL_MIPMAP_TEXTURE_ARB:
3008 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
3009 pbuffer->max_level = 0;
3010 if (value)
3012 int size = min(iWidth, iHeight) / 2;
3013 while (size)
3015 pbuffer->max_level++;
3016 size /= 2;
3019 break;
3021 default:
3022 WARN("unknown attribute 0x%x\n", attr);
3023 SetLastError(ERROR_INVALID_DATA);
3024 goto done;
3028 if (!target || !internalFormat)
3030 pbuffer->no_texture = TRUE;
3031 /* no actual way to turn off ability to texture; use most permissive target */
3032 target = GL_TEXTURE_RECTANGLE;
3033 internalFormat = GL_RGB;
3036 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3037 if (err != kCGLNoError)
3039 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3040 pbuffer->pbuffer = NULL;
3041 if (err == kCGLBadAlloc)
3042 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3043 else
3044 SetLastError(ERROR_INVALID_DATA);
3047 done:
3048 if (!pbuffer->pbuffer)
3050 HeapFree(GetProcessHeap(), 0, pbuffer);
3051 return NULL;
3054 TRACE(" -> %p\n", pbuffer);
3055 return pbuffer;
3059 /**********************************************************************
3060 * macdrv_wglDestroyPbufferARB
3062 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3064 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3066 TRACE("pbuffer %p\n", pbuffer);
3067 if (pbuffer && pbuffer->pbuffer)
3068 CGLReleasePBuffer(pbuffer->pbuffer);
3069 HeapFree(GetProcessHeap(), 0, pbuffer);
3070 return GL_TRUE;
3074 /**********************************************************************
3075 * macdrv_wglGetExtensionsStringARB
3077 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3079 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3081 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3082 this can be specific to the CGL renderer like we're supposed to do. */
3083 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3084 return gl_info.wglExtensions;
3088 /**********************************************************************
3089 * macdrv_wglGetExtensionsStringEXT
3091 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3093 static const char *macdrv_wglGetExtensionsStringEXT(void)
3095 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3096 return gl_info.wglExtensions;
3100 /**********************************************************************
3101 * macdrv_wglGetPbufferDCARB
3103 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3105 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3107 HDC hdc;
3108 struct wgl_pbuffer *prev;
3110 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3111 if (!hdc) return 0;
3113 EnterCriticalSection(&dc_pbuffers_section);
3114 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3115 if (prev)
3117 CGLReleasePBuffer(prev->pbuffer);
3118 HeapFree(GetProcessHeap(), 0, prev);
3120 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3121 LeaveCriticalSection(&dc_pbuffers_section);
3123 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3124 return hdc;
3128 /**********************************************************************
3129 * macdrv_wglGetPixelFormatAttribivARB
3131 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3133 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3134 UINT nAttributes, const int *piAttributes, int *piValues)
3136 const pixel_format *pf;
3137 UINT i;
3139 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3140 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3142 if (!nAttributes) return GL_TRUE;
3144 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3146 piValues[0] = nb_formats;
3147 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3148 return GL_TRUE;
3151 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3152 if (!pf)
3154 WARN("invalid pixel format %d\n", iPixelFormat);
3155 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3156 return GL_FALSE;
3159 for (i = 0; i < nAttributes; ++i)
3161 switch (piAttributes[i])
3163 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3164 piValues[i] = nb_formats;
3165 break;
3167 case WGL_DRAW_TO_WINDOW_ARB:
3168 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3169 break;
3171 case WGL_DRAW_TO_BITMAP_ARB:
3172 piValues[i] = GL_FALSE;
3173 break;
3175 case WGL_ACCELERATION_ARB:
3176 if (iLayerPlane) goto invalid_layer;
3177 if (pf->accelerated)
3178 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3179 else
3180 piValues[i] = WGL_NO_ACCELERATION_ARB;
3181 break;
3183 case WGL_NEED_PALETTE_ARB:
3184 case WGL_NEED_SYSTEM_PALETTE_ARB:
3185 case WGL_SWAP_LAYER_BUFFERS_ARB:
3186 piValues[i] = GL_FALSE;
3187 break;
3189 case WGL_SWAP_METHOD_ARB:
3190 if (pf->double_buffer && pf->backing_store)
3191 piValues[i] = WGL_SWAP_COPY_ARB;
3192 else
3193 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3194 break;
3196 case WGL_NUMBER_OVERLAYS_ARB:
3197 case WGL_NUMBER_UNDERLAYS_ARB:
3198 piValues[i] = 0;
3199 break;
3201 case WGL_TRANSPARENT_ARB:
3202 if (iLayerPlane) goto invalid_layer;
3203 piValues[i] = GL_FALSE;
3204 break;
3206 case WGL_TRANSPARENT_RED_VALUE_ARB:
3207 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3208 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3209 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3210 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3211 if (iLayerPlane) goto invalid_layer;
3212 piValues[i] = 0;
3213 break;
3215 case WGL_SHARE_DEPTH_ARB:
3216 case WGL_SHARE_STENCIL_ARB:
3217 case WGL_SHARE_ACCUM_ARB:
3218 if (iLayerPlane) goto invalid_layer;
3219 piValues[i] = GL_TRUE;
3220 break;
3222 case WGL_SUPPORT_GDI_ARB:
3223 if (iLayerPlane) goto invalid_layer;
3224 piValues[i] = GL_FALSE;
3225 break;
3227 case WGL_SUPPORT_OPENGL_ARB:
3228 if (iLayerPlane) goto invalid_layer;
3229 piValues[i] = GL_TRUE;
3230 break;
3232 case WGL_DOUBLE_BUFFER_ARB:
3233 if (iLayerPlane) goto invalid_layer;
3234 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3235 break;
3237 case WGL_STEREO_ARB:
3238 if (iLayerPlane) goto invalid_layer;
3239 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3240 break;
3242 case WGL_PIXEL_TYPE_ARB:
3243 if (iLayerPlane) goto invalid_layer;
3244 if (color_modes[pf->color_mode].is_float)
3245 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3246 else
3247 piValues[i] = WGL_TYPE_RGBA_ARB;
3248 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3249 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3250 However, Mac contexts don't support rendering to unsigned floating-point
3251 formats, even when GL_EXT_packed_float is supported. */
3252 break;
3254 case WGL_COLOR_BITS_ARB:
3255 if (iLayerPlane) goto invalid_layer;
3256 /* If the mode doesn't have alpha, return bits per pixel instead
3257 of color bits. On Windows, color bits sometimes exceeds r+g+b
3258 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3259 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3260 pixel format, we need to accommodate that. */
3261 if (color_modes[pf->color_mode].alpha_bits)
3262 piValues[i] = color_modes[pf->color_mode].color_bits;
3263 else
3264 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3265 break;
3267 case WGL_RED_BITS_ARB:
3268 if (iLayerPlane) goto invalid_layer;
3269 piValues[i] = color_modes[pf->color_mode].red_bits;
3270 break;
3272 case WGL_RED_SHIFT_ARB:
3273 if (iLayerPlane) goto invalid_layer;
3274 piValues[i] = color_modes[pf->color_mode].red_shift;
3275 break;
3277 case WGL_GREEN_BITS_ARB:
3278 if (iLayerPlane) goto invalid_layer;
3279 piValues[i] = color_modes[pf->color_mode].green_bits;
3280 break;
3282 case WGL_GREEN_SHIFT_ARB:
3283 if (iLayerPlane) goto invalid_layer;
3284 piValues[i] = color_modes[pf->color_mode].green_shift;
3285 break;
3287 case WGL_BLUE_BITS_ARB:
3288 if (iLayerPlane) goto invalid_layer;
3289 piValues[i] = color_modes[pf->color_mode].blue_bits;
3290 break;
3292 case WGL_BLUE_SHIFT_ARB:
3293 if (iLayerPlane) goto invalid_layer;
3294 piValues[i] = color_modes[pf->color_mode].blue_shift;
3295 break;
3297 case WGL_ALPHA_BITS_ARB:
3298 if (iLayerPlane) goto invalid_layer;
3299 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3300 break;
3302 case WGL_ALPHA_SHIFT_ARB:
3303 if (iLayerPlane) goto invalid_layer;
3304 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3305 break;
3307 case WGL_ACCUM_BITS_ARB:
3308 if (iLayerPlane) goto invalid_layer;
3309 if (pf->accum_mode)
3310 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3311 else
3312 piValues[i] = 0;
3313 break;
3315 case WGL_ACCUM_RED_BITS_ARB:
3316 if (iLayerPlane) goto invalid_layer;
3317 if (pf->accum_mode)
3318 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3319 else
3320 piValues[i] = 0;
3321 break;
3323 case WGL_ACCUM_GREEN_BITS_ARB:
3324 if (iLayerPlane) goto invalid_layer;
3325 if (pf->accum_mode)
3326 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3327 else
3328 piValues[i] = 0;
3329 break;
3331 case WGL_ACCUM_BLUE_BITS_ARB:
3332 if (iLayerPlane) goto invalid_layer;
3333 if (pf->accum_mode)
3334 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3335 else
3336 piValues[i] = 0;
3337 break;
3339 case WGL_ACCUM_ALPHA_BITS_ARB:
3340 if (iLayerPlane) goto invalid_layer;
3341 if (pf->accum_mode)
3342 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3343 else
3344 piValues[i] = 0;
3345 break;
3347 case WGL_DEPTH_BITS_ARB:
3348 if (iLayerPlane) goto invalid_layer;
3349 piValues[i] = pf->depth_bits;
3350 break;
3352 case WGL_STENCIL_BITS_ARB:
3353 if (iLayerPlane) goto invalid_layer;
3354 piValues[i] = pf->stencil_bits;
3355 break;
3357 case WGL_AUX_BUFFERS_ARB:
3358 if (iLayerPlane) goto invalid_layer;
3359 piValues[i] = pf->aux_buffers;
3360 break;
3362 case WGL_SAMPLE_BUFFERS_ARB:
3363 if (iLayerPlane) goto invalid_layer;
3364 piValues[i] = pf->sample_buffers;
3365 break;
3367 case WGL_SAMPLES_ARB:
3368 if (iLayerPlane) goto invalid_layer;
3369 piValues[i] = pf->samples;
3370 break;
3372 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3373 if (iLayerPlane) goto invalid_layer;
3374 /* sRGB is only supported for 8-bit integer color components */
3375 if (color_modes[pf->color_mode].red_bits == 8 &&
3376 color_modes[pf->color_mode].green_bits == 8 &&
3377 color_modes[pf->color_mode].blue_bits == 8 &&
3378 !color_modes[pf->color_mode].is_float)
3379 piValues[i] = GL_TRUE;
3380 else
3381 piValues[i] = GL_FALSE;
3382 break;
3384 case WGL_DRAW_TO_PBUFFER_ARB:
3385 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3386 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3387 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3388 break;
3390 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3391 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3392 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3393 break;
3395 case WGL_MAX_PBUFFER_WIDTH_ARB:
3396 piValues[i] = gl_info.max_viewport_dims[0];
3397 break;
3399 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3400 piValues[i] = gl_info.max_viewport_dims[1];
3401 break;
3403 case WGL_MAX_PBUFFER_PIXELS_ARB:
3404 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3405 break;
3407 default:
3408 WARN("invalid attribute %x\n", piAttributes[i]);
3409 return GL_FALSE;
3412 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3415 return GL_TRUE;
3417 invalid_layer:
3418 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3419 return GL_FALSE;
3423 /**********************************************************************
3424 * macdrv_wglGetPixelFormatAttribfvARB
3426 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3428 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3429 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3431 int *attr;
3432 int ret;
3434 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3435 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3437 /* Allocate a temporary array to store integer values */
3438 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
3439 if (!attr)
3441 ERR("couldn't allocate %d array\n", nAttributes);
3442 return GL_FALSE;
3445 /* Piggy-back on wglGetPixelFormatAttribivARB */
3446 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3447 if (ret)
3449 UINT i;
3451 /* Convert integer values to float. Should also check for attributes
3452 that can give decimal values here */
3453 for (i = 0; i < nAttributes; i++)
3454 pfValues[i] = attr[i];
3457 HeapFree(GetProcessHeap(), 0, attr);
3458 return ret;
3462 /**********************************************************************
3463 * macdrv_wglGetSwapIntervalEXT
3465 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3467 static int macdrv_wglGetSwapIntervalEXT(void)
3469 struct wgl_context *context = NtCurrentTeb()->glContext;
3470 struct macdrv_win_data *data;
3471 long value;
3472 CGLError err;
3474 TRACE("\n");
3476 if ((data = get_win_data(context->draw_hwnd)))
3478 value = data->swap_interval;
3479 release_win_data(data);
3481 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3482 set_swap_interval(context, value);
3484 else
3486 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3487 if (err != kCGLNoError)
3489 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3490 err, CGLErrorString(err));
3491 value = 1;
3495 return value;
3499 /***********************************************************************
3500 * macdrv_wglMakeContextCurrentARB
3502 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3504 * This is not supported directly by OpenGL on the Mac. We emulate it
3505 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3506 * temporarily swap the drawable. This follows the technique used in
3507 * the implementation of Mesa GLX for Apple.
3509 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3511 struct macdrv_win_data *data;
3512 HWND hwnd;
3514 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3515 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3517 if (!context)
3519 macdrv_make_context_current(NULL, NULL, CGRectNull);
3520 NtCurrentTeb()->glContext = NULL;
3521 return TRUE;
3524 if ((hwnd = WindowFromDC(draw_hdc)))
3526 if (!(data = get_win_data(hwnd)))
3528 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3529 return FALSE;
3532 if (!data->pixel_format)
3534 WARN("no pixel format set\n");
3535 release_win_data(data);
3536 SetLastError(ERROR_INVALID_HANDLE);
3537 return FALSE;
3539 if (context->format != data->pixel_format)
3541 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3542 release_win_data(data);
3543 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3544 return FALSE;
3547 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3548 set_swap_interval(context, data->swap_interval);
3550 context->draw_hwnd = hwnd;
3551 context->draw_view = data->client_cocoa_view;
3552 context->draw_rect = data->client_rect;
3553 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3554 context->draw_pbuffer = NULL;
3555 release_win_data(data);
3557 else
3559 struct wgl_pbuffer *pbuffer;
3561 EnterCriticalSection(&dc_pbuffers_section);
3562 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3563 if (pbuffer)
3565 if (context->format != pbuffer->format)
3567 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3568 LeaveCriticalSection(&dc_pbuffers_section);
3569 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3570 return FALSE;
3573 if (allow_vsync &&
3574 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3575 set_swap_interval(context, 0);
3577 else
3579 WARN("no window or pbuffer for DC\n");
3580 LeaveCriticalSection(&dc_pbuffers_section);
3581 SetLastError(ERROR_INVALID_HANDLE);
3582 return FALSE;
3585 context->draw_hwnd = NULL;
3586 context->draw_view = NULL;
3587 context->draw_pbuffer = pbuffer;
3588 LeaveCriticalSection(&dc_pbuffers_section);
3591 context->read_view = NULL;
3592 context->read_pbuffer = NULL;
3593 if (read_hdc && read_hdc != draw_hdc)
3595 if ((hwnd = WindowFromDC(read_hdc)))
3597 if ((data = get_win_data(hwnd)))
3599 if (data->client_cocoa_view != context->draw_view)
3601 context->read_view = data->client_cocoa_view;
3602 context->read_rect = data->client_rect;
3603 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3605 release_win_data(data);
3608 else
3610 EnterCriticalSection(&dc_pbuffers_section);
3611 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3612 LeaveCriticalSection(&dc_pbuffers_section);
3616 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3617 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3618 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3620 make_context_current(context, FALSE);
3621 context->has_been_current = TRUE;
3622 NtCurrentTeb()->glContext = context;
3624 return TRUE;
3628 /**********************************************************************
3629 * macdrv_wglQueryCurrentRendererIntegerWINE
3631 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3633 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3635 BOOL ret = FALSE;
3636 struct wgl_context *context = NtCurrentTeb()->glContext;
3637 CGLPixelFormatObj pixel_format;
3638 CGLError err;
3639 GLint virtual_screen;
3640 GLint display_mask;
3641 GLint pf_renderer_id;
3642 CGLRendererInfoObj renderer_info;
3643 GLint renderer_count;
3644 GLint renderer;
3646 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3647 (context ? context->cglcontext : NULL), attribute, value);
3649 if (attribute == WGL_RENDERER_VERSION_WINE)
3651 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3652 get_fallback_renderer_version(value);
3653 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3654 return TRUE;
3657 pixel_format = CGLGetPixelFormat(context->cglcontext);
3658 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3659 if (err != kCGLNoError)
3661 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3662 return FALSE;
3665 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3666 if (err != kCGLNoError)
3668 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3669 return FALSE;
3672 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3673 if (err != kCGLNoError)
3675 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3676 return FALSE;
3679 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3680 if (err != kCGLNoError)
3682 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3683 return FALSE;
3686 for (renderer = 0; renderer < renderer_count; renderer++)
3688 GLint renderer_id;
3690 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3691 continue;
3693 if (renderer_id == pf_renderer_id)
3695 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3696 break;
3700 if (renderer >= renderer_count)
3701 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3703 CGLDestroyRendererInfo(renderer_info);
3704 return ret;
3708 /**********************************************************************
3709 * macdrv_wglQueryCurrentRendererStringWINE
3711 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3713 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3715 const char* ret = NULL;
3716 struct wgl_context *context = NtCurrentTeb()->glContext;
3718 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3719 (context ? context->cglcontext : NULL), attribute);
3721 switch (attribute)
3723 case WGL_RENDERER_DEVICE_ID_WINE:
3725 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3726 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3727 break;
3730 case WGL_RENDERER_VENDOR_ID_WINE:
3732 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3733 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3734 break;
3737 default:
3738 FIXME("unrecognized attribute 0x%04x\n", attribute);
3739 break;
3742 return ret;
3746 /**********************************************************************
3747 * macdrv_wglQueryPbufferARB
3749 * WGL_ARB_pbuffer: wglQueryPbufferARB
3751 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3753 CGLError err;
3754 GLsizei width;
3755 GLsizei height;
3756 GLenum target;
3757 GLenum internalFormat;
3758 GLint mipmap;
3760 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3762 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3763 if (err != kCGLNoError)
3765 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3766 SetLastError(ERROR_INVALID_HANDLE);
3767 return GL_FALSE;
3770 switch (iAttribute)
3772 case WGL_PBUFFER_WIDTH_ARB:
3773 *piValue = width;
3774 break;
3775 case WGL_PBUFFER_HEIGHT_ARB:
3776 *piValue = height;
3777 break;
3778 case WGL_PBUFFER_LOST_ARB:
3779 /* Mac PBuffers can't be lost */
3780 *piValue = GL_FALSE;
3781 break;
3782 case WGL_TEXTURE_FORMAT_ARB:
3783 if (pbuffer->no_texture)
3784 *piValue = WGL_NO_TEXTURE_ARB;
3785 else switch (internalFormat)
3787 case GL_RGBA:
3788 *piValue = WGL_TEXTURE_RGBA_ARB;
3789 break;
3790 case GL_RGB:
3791 default:
3792 *piValue = WGL_TEXTURE_RGB_ARB;
3793 break;
3795 break;
3796 case WGL_TEXTURE_TARGET_ARB:
3797 if (pbuffer->no_texture)
3798 *piValue = WGL_NO_TEXTURE_ARB;
3799 else switch (target)
3801 case GL_TEXTURE_CUBE_MAP:
3802 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3803 break;
3804 case GL_TEXTURE_2D:
3805 *piValue = WGL_TEXTURE_2D_ARB;
3806 break;
3807 case GL_TEXTURE_RECTANGLE:
3808 default:
3809 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3810 break;
3812 break;
3813 case WGL_MIPMAP_TEXTURE_ARB:
3814 *piValue = (pbuffer->max_level > 0);
3815 break;
3816 case WGL_MIPMAP_LEVEL_ARB:
3817 *piValue = pbuffer->level;
3818 break;
3819 case WGL_CUBE_MAP_FACE_ARB:
3820 switch (pbuffer->face)
3822 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3823 default:
3824 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3825 break;
3826 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3827 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3828 break;
3829 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3830 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3831 break;
3832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3833 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3834 break;
3835 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3836 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3837 break;
3838 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3839 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3840 break;
3842 break;
3843 default:
3844 WARN("invalid attribute 0x%x\n", iAttribute);
3845 SetLastError(ERROR_INVALID_DATA);
3846 return GL_FALSE;
3849 return GL_TRUE;
3853 /**********************************************************************
3854 * macdrv_wglQueryRendererIntegerWINE
3856 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3858 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3860 BOOL ret = FALSE;
3861 CGLRendererInfoObj renderer_info;
3862 GLint renderer_count;
3863 CGLError err;
3865 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
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)
3877 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3878 else
3879 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3881 CGLDestroyRendererInfo(renderer_info);
3882 return ret;
3886 /**********************************************************************
3887 * macdrv_wglQueryRendererStringWINE
3889 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3891 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3893 const char* ret = NULL;
3894 CGLRendererInfoObj renderer_info;
3895 GLint renderer_count;
3896 CGLError err;
3898 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3900 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3901 if (err != kCGLNoError)
3903 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3904 return FALSE;
3907 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3909 if (renderer >= renderer_count)
3911 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3912 goto done;
3915 switch (attribute)
3917 case WGL_RENDERER_DEVICE_ID_WINE:
3918 case WGL_RENDERER_VENDOR_ID_WINE:
3920 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3921 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3923 if (!pixel_format)
3924 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3925 if (pixel_format)
3927 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3928 CGLReleasePixelFormat(pixel_format);
3931 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3932 break;
3935 default:
3936 FIXME("unrecognized attribute 0x%04x\n", attribute);
3937 break;
3940 done:
3941 CGLDestroyRendererInfo(renderer_info);
3942 return ret;
3946 /**********************************************************************
3947 * macdrv_wglReleasePbufferDCARB
3949 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3951 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3953 struct wgl_pbuffer *prev;
3955 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3957 EnterCriticalSection(&dc_pbuffers_section);
3959 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3960 if (prev)
3962 if (prev != pbuffer)
3963 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3964 CGLReleasePBuffer(prev->pbuffer);
3965 HeapFree(GetProcessHeap(), 0, prev);
3966 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3968 else hdc = 0;
3970 LeaveCriticalSection(&dc_pbuffers_section);
3972 return hdc && DeleteDC(hdc);
3976 /**********************************************************************
3977 * macdrv_wglReleaseTexImageARB
3979 * WGL_ARB_render_texture: wglReleaseTexImageARB
3981 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3983 struct wgl_context *context = NtCurrentTeb()->glContext;
3984 CGLError err;
3986 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3988 if (pbuffer->no_texture)
3990 SetLastError(ERROR_INVALID_OPERATION);
3991 return GL_FALSE;
3994 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3995 if (err != kCGLNoError)
3997 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3998 SetLastError(ERROR_INVALID_OPERATION);
3999 return GL_FALSE;
4002 return GL_TRUE;
4006 /**********************************************************************
4007 * macdrv_wglSetPbufferAttribARB
4009 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4011 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
4013 struct wgl_context *context = NtCurrentTeb()->glContext;
4015 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
4017 for ( ; piAttribList && *piAttribList; piAttribList += 2)
4019 int attr = piAttribList[0];
4020 int value = piAttribList[1];
4021 switch (attr)
4023 case WGL_MIPMAP_LEVEL_ARB:
4024 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
4025 pbuffer->level = value;
4026 break;
4027 case WGL_CUBE_MAP_FACE_ARB:
4028 switch (value)
4030 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
4031 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4032 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4033 break;
4034 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4035 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4036 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4037 break;
4038 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4039 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4040 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4041 break;
4042 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4043 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4044 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4045 break;
4046 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4047 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4048 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4049 break;
4050 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4051 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4052 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4053 break;
4054 default:
4055 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4056 SetLastError(ERROR_INVALID_DATA);
4057 return GL_FALSE;
4059 break;
4060 default:
4061 WARN("invalid attribute 0x%x\n", attr);
4062 SetLastError(ERROR_INVALID_DATA);
4063 return GL_FALSE;
4067 if (context && context->draw_pbuffer == pbuffer)
4068 make_context_current(context, FALSE);
4070 return GL_TRUE;
4074 /**********************************************************************
4075 * macdrv_wglSetPixelFormatWINE
4077 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4079 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4081 return set_pixel_format(hdc, fmt, TRUE);
4085 /**********************************************************************
4086 * macdrv_wglSwapIntervalEXT
4088 * WGL_EXT_swap_control: wglSwapIntervalEXT
4090 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4092 struct wgl_context *context = NtCurrentTeb()->glContext;
4093 BOOL changed = FALSE;
4095 TRACE("interval %d\n", interval);
4097 if (interval < 0)
4099 SetLastError(ERROR_INVALID_DATA);
4100 return FALSE;
4102 if (interval > 1)
4103 interval = 1;
4105 if (context->draw_hwnd)
4107 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4108 if (data)
4110 changed = data->swap_interval != interval;
4111 if (changed)
4112 data->swap_interval = interval;
4113 release_win_data(data);
4116 else /* pbuffer */
4117 interval = 0;
4119 InterlockedExchange(&context->update_swap_interval, FALSE);
4120 if (!set_swap_interval(context, interval))
4122 SetLastError(ERROR_GEN_FAILURE);
4123 return FALSE;
4126 if (changed)
4128 struct wgl_context *ctx;
4130 EnterCriticalSection(&context_section);
4131 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4133 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4134 InterlockedExchange(&context->update_swap_interval, TRUE);
4136 LeaveCriticalSection(&context_section);
4139 return TRUE;
4143 static void register_extension(const char *ext)
4145 if (gl_info.wglExtensions[0])
4146 strcat(gl_info.wglExtensions, " ");
4147 strcat(gl_info.wglExtensions, ext);
4149 TRACE("'%s'\n", ext);
4152 static void load_extensions(void)
4155 * ARB Extensions
4157 register_extension("WGL_ARB_extensions_string");
4158 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4160 register_extension("WGL_ARB_make_current_read");
4161 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4162 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4164 register_extension("WGL_ARB_pixel_format");
4165 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4166 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4167 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4169 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4171 register_extension("WGL_ARB_pixel_format_float");
4172 register_extension("WGL_ATI_pixel_format_float");
4175 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4176 register_extension("WGL_ARB_multisample");
4178 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4179 register_extension("WGL_ARB_framebuffer_sRGB");
4181 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4183 register_extension("WGL_ARB_pbuffer");
4184 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4185 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4186 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4187 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4188 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4190 register_extension("WGL_ARB_render_texture");
4191 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4192 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4193 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4195 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4196 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4197 register_extension("WGL_NV_render_texture_rectangle");
4200 register_extension("WGL_ARB_create_context");
4201 register_extension("WGL_ARB_create_context_profile");
4202 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4205 * EXT Extensions
4207 register_extension("WGL_EXT_extensions_string");
4208 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4210 if (allow_vsync)
4212 register_extension("WGL_EXT_swap_control");
4213 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4214 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4217 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4218 check for either, so register them separately. */
4219 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4220 register_extension("WGL_EXT_framebuffer_sRGB");
4222 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4223 register_extension("WGL_EXT_pixel_format_packed_float");
4226 * WINE-specific WGL Extensions
4229 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4230 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4232 register_extension("WGL_WINE_pixel_format_passthrough");
4233 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4235 register_extension("WGL_WINE_query_renderer");
4236 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4237 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4238 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4239 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4243 static BOOL init_opengl(void)
4245 static BOOL init_done = FALSE;
4246 unsigned int i;
4247 char buffer[200];
4249 if (init_done) return (opengl_handle != NULL);
4250 init_done = TRUE;
4252 TRACE("()\n");
4254 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4255 if (!dc_pbuffers)
4257 WARN("CFDictionaryCreateMutable failed\n");
4258 return FALSE;
4261 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
4262 if (!opengl_handle)
4264 ERR("Failed to load OpenGL: %s\n", buffer);
4265 ERR("OpenGL support is disabled.\n");
4266 return FALSE;
4269 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
4271 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
4273 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4274 goto failed;
4278 /* redirect some standard OpenGL functions */
4279 #define REDIRECT(func) \
4280 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4281 REDIRECT(glCopyPixels);
4282 REDIRECT(glGetString);
4283 REDIRECT(glReadPixels);
4284 REDIRECT(glViewport);
4285 if (skip_single_buffer_flushes || allow_vsync)
4286 REDIRECT(glFlush);
4287 if (allow_vsync)
4288 REDIRECT(glFinish);
4289 #undef REDIRECT
4291 /* redirect some OpenGL extension functions */
4292 #define REDIRECT(func) \
4293 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4294 REDIRECT(glCopyColorTable);
4295 #undef REDIRECT
4297 if (!init_gl_info())
4298 goto failed;
4300 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4301 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
4303 load_extensions();
4304 if (!init_pixel_formats())
4305 goto failed;
4307 return TRUE;
4309 failed:
4310 wine_dlclose(opengl_handle, NULL, 0);
4311 opengl_handle = NULL;
4312 return FALSE;
4316 /***********************************************************************
4317 * sync_gl_view
4319 * Synchronize the Mac GL view position with the Windows child window
4320 * position.
4322 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4324 if (data->client_cocoa_view && data->pixel_format)
4326 RECT old = *old_client_rect, new = data->client_rect;
4328 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4329 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4330 if (!EqualRect(&old, &new))
4332 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4333 mark_contexts_for_moved_view(data->client_cocoa_view);
4339 /**********************************************************************
4340 * macdrv_wglDescribePixelFormat
4342 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4344 const pixel_format *pf;
4345 const struct color_mode *mode;
4347 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4349 if (!descr) return nb_displayable_formats;
4350 if (size < sizeof(*descr)) return 0;
4352 if (!(pf = get_pixel_format(fmt, FALSE)))
4353 return 0;
4355 memset(descr, 0, sizeof(*descr));
4356 descr->nSize = sizeof(*descr);
4357 descr->nVersion = 1;
4359 descr->dwFlags = PFD_SUPPORT_OPENGL;
4360 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4361 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4362 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4363 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4364 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4366 descr->iPixelType = PFD_TYPE_RGBA;
4368 mode = &color_modes[pf->color_mode];
4369 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4370 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4371 R8G8B8A0 pixel format). If an app depends on that and expects that
4372 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4373 if (mode->alpha_bits)
4374 descr->cColorBits = mode->color_bits;
4375 else
4376 descr->cColorBits = mode->bits_per_pixel;
4377 descr->cRedBits = mode->red_bits;
4378 descr->cRedShift = mode->red_shift;
4379 descr->cGreenBits = mode->green_bits;
4380 descr->cGreenShift = mode->green_shift;
4381 descr->cBlueBits = mode->blue_bits;
4382 descr->cBlueShift = mode->blue_shift;
4383 descr->cAlphaBits = mode->alpha_bits;
4384 descr->cAlphaShift = mode->alpha_shift;
4386 if (pf->accum_mode)
4388 mode = &color_modes[pf->accum_mode - 1];
4389 descr->cAccumBits = mode->color_bits;
4390 descr->cAccumRedBits = mode->red_bits;
4391 descr->cAccumGreenBits = mode->green_bits;
4392 descr->cAccumBlueBits = mode->blue_bits;
4393 descr->cAccumAlphaBits = mode->alpha_bits;
4396 descr->cDepthBits = pf->depth_bits;
4397 descr->cStencilBits = pf->stencil_bits;
4398 descr->cAuxBuffers = pf->aux_buffers;
4399 descr->iLayerType = PFD_MAIN_PLANE;
4401 TRACE("%s\n", debugstr_pf(pf));
4402 return nb_displayable_formats;
4405 /***********************************************************************
4406 * macdrv_wglCopyContext
4408 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4410 CGLError err;
4412 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4414 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4415 if (err != kCGLNoError)
4416 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4417 return (err == kCGLNoError);
4420 /***********************************************************************
4421 * macdrv_wglCreateContext
4423 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
4425 struct wgl_context *context;
4427 TRACE("hdc %p\n", hdc);
4429 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4431 return context;
4434 /***********************************************************************
4435 * macdrv_wglDeleteContext
4437 static void macdrv_wglDeleteContext(struct wgl_context *context)
4439 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4441 EnterCriticalSection(&context_section);
4442 list_remove(&context->entry);
4443 LeaveCriticalSection(&context_section);
4445 macdrv_dispose_opengl_context(context->context);
4446 HeapFree(GetProcessHeap(), 0, context);
4449 /***********************************************************************
4450 * macdrv_wglGetPixelFormat
4452 static int macdrv_wglGetPixelFormat(HDC hdc)
4454 int format;
4456 format = get_dc_pixel_format(hdc);
4458 if (!is_valid_pixel_format(format)) /* not set yet */
4459 format = 0;
4460 else if (!is_displayable_pixel_format(format))
4462 /* Non-displayable formats can't be used with traditional WGL calls.
4463 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4464 format = 1;
4467 TRACE(" hdc %p -> %d\n", hdc, format);
4468 return format;
4471 /***********************************************************************
4472 * macdrv_wglGetProcAddress
4474 static PROC macdrv_wglGetProcAddress(const char *proc)
4476 void *ret;
4478 if (!strncmp(proc, "wgl", 3)) return NULL;
4479 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
4480 if (ret)
4482 if (TRACE_ON(wgl))
4484 Dl_info info;
4485 if (dladdr(ret, &info))
4486 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4487 else
4488 TRACE("%s -> %p (no library info)\n", proc, ret);
4491 else
4492 WARN("failed to find proc %s\n", debugstr_a(proc));
4493 return ret;
4496 /***********************************************************************
4497 * macdrv_wglMakeCurrent
4499 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4501 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4502 (context ? context->cglcontext : NULL));
4504 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4507 /**********************************************************************
4508 * macdrv_wglSetPixelFormat
4510 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4512 return set_pixel_format(hdc, fmt, FALSE);
4515 /***********************************************************************
4516 * macdrv_wglShareLists
4518 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4520 macdrv_opengl_context saved_context;
4521 CGLContextObj saved_cglcontext;
4523 TRACE("org %p dest %p\n", org, dest);
4525 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4526 * at context creation time but in case of WGL it is done using wglShareLists.
4528 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4529 * and when a program requests sharing we recreate the destination context if it hasn't been made
4530 * current or when it hasn't shared display lists before.
4533 if (dest->has_been_current)
4535 WARN("could not share display lists, the destination context has been current already\n");
4536 return FALSE;
4538 else if (dest->sharing)
4540 WARN("could not share display lists because dest has already shared lists before\n");
4541 return FALSE;
4544 /* Re-create the Mac context and share display lists */
4545 saved_context = dest->context;
4546 saved_cglcontext = dest->cglcontext;
4547 dest->context = NULL;
4548 dest->cglcontext = NULL;
4549 if (!create_context(dest, org->cglcontext, dest->major))
4551 dest->context = saved_context;
4552 dest->cglcontext = saved_cglcontext;
4553 return FALSE;
4556 /* Implicitly disposes of saved_cglcontext. */
4557 macdrv_dispose_opengl_context(saved_context);
4559 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4560 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4562 org->sharing = TRUE;
4563 dest->sharing = TRUE;
4565 return TRUE;
4568 /**********************************************************************
4569 * macdrv_wglSwapBuffers
4571 static BOOL macdrv_wglSwapBuffers(HDC hdc)
4573 struct wgl_context *context = NtCurrentTeb()->glContext;
4574 BOOL match = FALSE;
4575 HWND hwnd;
4577 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4578 (context ? context->cglcontext : NULL));
4580 if (context)
4582 sync_swap_interval(context);
4583 sync_context(context);
4586 if ((hwnd = WindowFromDC(hdc)))
4588 struct macdrv_win_data *data;
4590 if (!(data = get_win_data(hwnd)))
4592 SetLastError(ERROR_INVALID_HANDLE);
4593 return FALSE;
4596 if (context && context->draw_view == data->client_cocoa_view)
4597 match = TRUE;
4599 release_win_data(data);
4601 else
4603 struct wgl_pbuffer *pbuffer;
4605 EnterCriticalSection(&dc_pbuffers_section);
4606 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4607 LeaveCriticalSection(&dc_pbuffers_section);
4609 if (!pbuffer)
4611 SetLastError(ERROR_INVALID_HANDLE);
4612 return FALSE;
4615 if (context && context->draw_pbuffer == pbuffer)
4616 match = TRUE;
4619 if (match)
4620 macdrv_flush_opengl_context(context->context);
4621 else
4623 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4625 /* If there is a current context, then wglSwapBuffers should do an implicit
4626 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4627 in the other branch, but we have to do it explicitly here. */
4628 if (context)
4629 pglFlush();
4632 return TRUE;
4635 static struct opengl_funcs opengl_funcs =
4638 macdrv_wglCopyContext, /* p_wglCopyContext */
4639 macdrv_wglCreateContext, /* p_wglCreateContext */
4640 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4641 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4642 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4643 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4644 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4645 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4646 macdrv_wglShareLists, /* p_wglShareLists */
4647 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4651 /**********************************************************************
4652 * macdrv_wine_get_wgl_driver
4654 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
4656 if (version != WINE_WGL_DRIVER_VERSION)
4658 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4659 return NULL;
4662 if (!init_opengl()) return (void *)-1;
4664 return &opengl_funcs;