winemac: Add function macdrv_set_view_superview().
[wine.git] / dlls / winemac.drv / opengl.c
blob0039f0ab26a921f3705393c72ca8ddfd456c7041
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 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1554 BOOL ret = TRUE;
1555 *rect = data->client_rect;
1557 if (data->cocoa_window)
1559 if (window)
1560 *window = data->cocoa_window;
1561 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1563 else
1565 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1566 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1567 struct macdrv_win_data *top_data = get_win_data(top);
1569 if (top_data && top_data->cocoa_window)
1571 if (window)
1572 *window = top_data->cocoa_window;
1573 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1574 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1576 else
1577 ret = FALSE;
1579 release_win_data(top_data);
1582 return ret;
1586 /***********************************************************************
1587 * set_win_format
1589 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1591 TRACE("hwnd %p format %d\n", data->hwnd, format);
1593 if (!data->gl_view)
1595 macdrv_window cocoa_window;
1597 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1599 ERR("no top-level parent with Cocoa window in this process\n");
1600 return FALSE;
1603 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1604 if (!data->gl_view)
1606 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1607 return FALSE;
1610 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1611 wine_dbgstr_rect(&data->gl_rect));
1614 data->pixel_format = format;
1616 return TRUE;
1620 /**********************************************************************
1621 * set_pixel_format
1623 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1625 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1627 struct macdrv_win_data *data;
1628 const pixel_format *pf;
1629 HWND hwnd = WindowFromDC(hdc);
1630 BOOL ret = FALSE;
1632 TRACE("hdc %p format %d\n", hdc, fmt);
1634 if (!hwnd || hwnd == GetDesktopWindow())
1636 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1637 return FALSE;
1640 if (!(data = get_win_data(hwnd)))
1642 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1643 return FALSE;
1646 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1648 ret = (data->pixel_format == fmt);
1649 goto done;
1652 /* Check if fmt is in our list of supported formats to see if it is supported. */
1653 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1654 if (!pf)
1656 ERR("Invalid pixel format: %d\n", fmt);
1657 goto done;
1660 if (!pf->window)
1662 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1663 goto done;
1666 if (!set_win_format(data, fmt))
1668 WARN("Couldn't set format of the window, returning failure\n");
1669 goto done;
1672 TRACE("pixel format:\n");
1673 TRACE(" window: %u\n", (unsigned int)pf->window);
1674 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1675 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1676 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1677 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1678 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1679 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1680 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1681 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1682 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1683 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1684 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1685 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1686 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1687 ret = TRUE;
1689 done:
1690 release_win_data(data);
1691 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
1692 return ret;
1696 /**********************************************************************
1697 * mark_contexts_for_moved_view
1699 static void mark_contexts_for_moved_view(macdrv_view view)
1701 struct wgl_context *context;
1703 EnterCriticalSection(&context_section);
1704 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1706 if (context->draw_view == view)
1707 InterlockedExchange(&context->view_moved, TRUE);
1709 LeaveCriticalSection(&context_section);
1713 /**********************************************************************
1714 * set_gl_view_parent
1716 void set_gl_view_parent(HWND hwnd, HWND parent)
1718 struct macdrv_win_data *data;
1720 if (!(data = get_win_data(hwnd))) return;
1722 if (data->gl_view)
1724 macdrv_window cocoa_window;
1726 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1728 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1730 ERR("no top-level parent with Cocoa window in this process\n");
1731 macdrv_dispose_view(data->gl_view);
1732 data->gl_view = NULL;
1733 release_win_data(data);
1734 __wine_set_pixel_format( hwnd, 0 );
1735 return;
1738 macdrv_set_view_superview(data->gl_view, NULL, cocoa_window, NULL, NULL);
1739 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(data->gl_rect));
1740 mark_contexts_for_moved_view(data->gl_view);
1743 release_win_data(data);
1747 /**********************************************************************
1748 * sync_context_rect
1750 static BOOL sync_context_rect(struct wgl_context *context)
1752 BOOL ret = FALSE;
1753 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1755 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1757 if (data && data->gl_view && data->gl_view == context->draw_view &&
1758 memcmp(&context->draw_rect, &data->gl_rect, sizeof(context->draw_rect)))
1760 context->draw_rect = data->gl_rect;
1761 ret = TRUE;
1763 release_win_data(data);
1765 return ret;
1769 /**********************************************************************
1770 * make_context_current
1772 static void make_context_current(struct wgl_context *context, BOOL read)
1774 macdrv_view view;
1775 RECT view_rect;
1776 struct wgl_pbuffer *pbuffer;
1778 if (read)
1780 view = context->read_view;
1781 view_rect = context->read_rect;
1782 pbuffer = context->read_pbuffer;
1784 else
1786 sync_context_rect(context);
1788 view = context->draw_view;
1789 view_rect = context->draw_rect;
1790 pbuffer = context->draw_pbuffer;
1793 if (view || !pbuffer)
1794 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1795 else
1797 GLint enabled;
1799 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1800 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1801 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1802 pbuffer->level, 0);
1803 CGLSetCurrentContext(context->cglcontext);
1808 /**********************************************************************
1809 * sync_context
1811 static void sync_context(struct wgl_context *context)
1813 if (sync_context_rect(context))
1814 make_context_current(context, FALSE);
1818 /**********************************************************************
1819 * set_swap_interval
1821 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1823 CGLError err;
1825 /* In theory, for single-buffered contexts, there's no such thing as a swap
1826 so the swap interval shouldn't matter. But OS X will synchronize flushes
1827 of single-buffered contexts if the interval is set to non-zero. */
1828 if (interval && !pixel_formats[context->format - 1].double_buffer)
1829 interval = 0;
1831 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1832 if (err != kCGLNoError)
1833 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1835 return err == kCGLNoError;
1839 /**********************************************************************
1840 * sync_swap_interval
1842 static void sync_swap_interval(struct wgl_context *context)
1844 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1846 int interval;
1848 if (context->draw_hwnd)
1850 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1851 if (data)
1853 interval = data->swap_interval;
1854 release_win_data(data);
1856 else /* window was destroyed? */
1857 interval = 1;
1859 else /* pbuffer */
1860 interval = 0;
1862 set_swap_interval(context, interval);
1867 /**********************************************************************
1868 * get_iokit_display_property
1870 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1872 GLint accelerated;
1873 GLint display_mask;
1874 int i;
1876 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1878 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1879 return FALSE;
1882 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1884 WARN("failed to get kCGLRPDisplayMask\n");
1885 return FALSE;
1888 for (i = 0; i < sizeof(GLint) * 8; i++)
1890 GLint this_display_mask = (GLint)(1U << i);
1891 if (this_display_mask & display_mask)
1893 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1894 io_service_t service;
1895 CFDataRef data;
1896 uint32_t prop_value;
1898 if (!display_id)
1899 continue;
1900 service = CGDisplayIOServicePort(display_id);
1901 if (!service)
1903 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1904 continue;
1907 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1908 kIORegistryIterateRecursively | kIORegistryIterateParents);
1909 if (!data)
1911 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1912 continue;
1914 if (CFGetTypeID(data) != CFDataGetTypeID())
1916 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1917 CFRelease(data);
1918 continue;
1920 if (CFDataGetLength(data) != sizeof(prop_value))
1922 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1923 (unsigned long long)CFDataGetLength(data));
1924 CFRelease(data);
1925 continue;
1928 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1929 CFRelease(data);
1930 *value = prop_value;
1931 return TRUE;
1935 return FALSE;
1939 /**********************************************************************
1940 * create_pixel_format_for_renderer
1942 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1943 * responsible for releasing the pixel format object.
1945 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1947 GLint renderer_id;
1948 CGLPixelFormatAttribute attrs[] = {
1949 kCGLPFARendererID, 0,
1950 kCGLPFASingleRenderer,
1951 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1954 CGError err;
1955 CGLPixelFormatObj pixel_format;
1956 GLint virtual_screens;
1958 if (core)
1960 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1961 attrs[3] = kCGLPFAOpenGLProfile;
1962 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1963 #else
1964 return NULL;
1965 #endif
1968 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1969 return NULL;
1971 attrs[1] = renderer_id;
1972 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1973 if (err != kCGLNoError)
1974 pixel_format = NULL;
1975 return pixel_format;
1979 /**********************************************************************
1980 * map_renderer_index
1982 * We can't create pixel formats for all renderers listed. For example,
1983 * in a dual-GPU system, the integrated GPU is typically unavailable
1984 * when the discrete GPU is active.
1986 * This function conceptually creates a list of "good" renderers from the
1987 * list of all renderers. It treats the input "renderer" parameter as an
1988 * index into that list of good renderers and returns the corresponding
1989 * index into the list of all renderers.
1991 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1993 GLint good_count, i;
1995 good_count = 0;
1996 for (i = 0; i < renderer_count; i++)
1998 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1999 if (pix)
2001 CGLReleasePixelFormat(pix);
2002 good_count++;
2003 if (good_count > renderer)
2004 break;
2006 else
2007 TRACE("skipping bad renderer %d\n", i);
2010 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
2011 return i;
2015 /**********************************************************************
2016 * get_gl_string
2018 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
2020 const char* ret = NULL;
2021 CGLContextObj context, old_context;
2022 CGLError err;
2024 err = CGLCreateContext(pixel_format, NULL, &context);
2025 if (err == kCGLNoError && context)
2027 old_context = CGLGetCurrentContext();
2028 err = CGLSetCurrentContext(context);
2029 if (err == kCGLNoError)
2031 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
2032 CGLSetCurrentContext(old_context);
2034 else
2035 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
2036 CGLReleaseContext(context);
2038 else
2039 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
2041 return ret;
2045 /**********************************************************************
2046 * get_fallback_renderer_version
2048 static void get_fallback_renderer_version(GLuint *value)
2050 BOOL got_it = FALSE;
2051 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
2052 kCFURLPOSIXPathStyle, TRUE);
2053 if (url)
2055 CFBundleRef bundle = CFBundleCreate(NULL, url);
2056 CFRelease(url);
2057 if (bundle)
2059 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
2060 if (version && CFGetTypeID(version) == CFStringGetTypeID())
2062 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
2063 char* buf = HeapAlloc(GetProcessHeap(), 0, len);
2064 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
2066 unsigned int major, minor, bugfix;
2067 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
2068 if (count >= 2)
2070 value[0] = major;
2071 value[1] = minor;
2072 if (count == 3)
2073 value[2] = bugfix;
2074 else
2075 value[2] = 0;
2076 got_it = TRUE;
2079 HeapFree(GetProcessHeap(), 0, buf);
2081 CFRelease(bundle);
2085 if (!got_it)
2087 /* Use the version of the OpenGL framework from OS X 10.6, which is the
2088 earliest version that the Mac driver supports. */
2089 value[0] = 1;
2090 value[1] = 6;
2091 value[2] = 14;
2096 /**********************************************************************
2097 * parse_renderer_version
2099 * Get the renderer version from the OpenGL version string. Assumes
2100 * the string is of the form
2101 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2102 * where major, minor, and bugfix are what we're interested in. This
2103 * form for the vendor specific information is not generally applicable,
2104 * but seems reliable on OS X.
2106 static BOOL parse_renderer_version(const char* version, GLuint *value)
2108 const char* p = strchr(version, ' ');
2109 int count;
2110 unsigned int major, minor, bugfix;
2112 if (p) p = strchr(p + 1, '-');
2113 if (!p) return FALSE;
2115 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
2116 if (count < 2)
2117 return FALSE;
2119 value[0] = major;
2120 value[1] = minor;
2121 if (count == 3)
2122 value[2] = bugfix;
2123 else
2124 value[2] = 0;
2126 return TRUE;
2130 /**********************************************************************
2131 * query_renderer_integer
2133 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2135 BOOL ret = FALSE;
2136 CGLError err;
2138 if (TRACE_ON(wgl))
2140 GLint renderer_id;
2141 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2142 renderer_id = 0;
2143 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2146 switch (attribute)
2148 case WGL_RENDERER_ACCELERATED_WINE:
2149 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2150 break;
2151 *value = !!*value;
2152 ret = TRUE;
2153 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2154 break;
2156 case WGL_RENDERER_DEVICE_ID_WINE:
2157 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2158 if (!ret)
2160 *value = 0xffffffff;
2161 ret = TRUE;
2163 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2164 break;
2166 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2167 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2169 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2170 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2172 if (pixel_format)
2174 const char* version = get_gl_string(pixel_format, GL_VERSION);
2176 CGLReleasePixelFormat(pixel_format);
2177 if (version)
2179 unsigned int major, minor;
2181 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2183 value[0] = major;
2184 value[1] = minor;
2185 ret = TRUE;
2190 if (!ret)
2192 value[0] = value[1] = 0;
2193 ret = TRUE;
2195 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2196 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2197 break;
2200 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2202 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2204 if (pixel_format)
2206 CGLReleasePixelFormat(pixel_format);
2207 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2208 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2210 else
2212 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2213 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2215 ret = TRUE;
2216 break;
2219 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2220 /* FIXME: no API to query this */
2221 *value = 0;
2222 ret = TRUE;
2223 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2224 break;
2226 case WGL_RENDERER_VENDOR_ID_WINE:
2227 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2228 if (!ret)
2230 *value = 0xffffffff;
2231 ret = TRUE;
2233 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2234 break;
2236 case WGL_RENDERER_VERSION_WINE:
2238 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2240 if (!pixel_format)
2241 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2242 if (pixel_format)
2244 const char* version = get_gl_string(pixel_format, GL_VERSION);
2246 CGLReleasePixelFormat(pixel_format);
2247 if (version)
2248 ret = parse_renderer_version(version, value);
2251 if (!ret)
2253 get_fallback_renderer_version(value);
2254 ret = TRUE;
2256 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2257 break;
2260 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2261 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2262 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2263 if (err != kCGLNoError && err != kCGLBadProperty)
2264 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2265 if (err != kCGLNoError)
2266 #endif
2268 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2269 *value /= 1024 * 1024;
2270 else
2271 *value = 0;
2273 ret = TRUE;
2274 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2275 break;
2277 default:
2278 FIXME("unrecognized attribute 0x%04x\n", attribute);
2279 break;
2282 return ret;
2286 /**********************************************************************
2287 * macdrv_glCopyColorTable
2289 * Hook into glCopyColorTable as part of the implementation of
2290 * wglMakeContextCurrentARB. If the context has a separate readable,
2291 * temporarily make that current, do glCopyColorTable, and then set it
2292 * back to the drawable. This is modeled after what Mesa GLX's Apple
2293 * implementation does.
2295 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2296 GLsizei width)
2298 struct wgl_context *context = NtCurrentTeb()->glContext;
2300 if (context->read_view || context->read_pbuffer)
2301 make_context_current(context, TRUE);
2303 pglCopyColorTable(target, internalformat, x, y, width);
2305 if (context->read_view || context->read_pbuffer)
2306 make_context_current(context, FALSE);
2310 /**********************************************************************
2311 * macdrv_glCopyPixels
2313 * Hook into glCopyPixels as part of the implementation of
2314 * wglMakeContextCurrentARB. If the context has a separate readable,
2315 * temporarily make that current, do glCopyPixels, and then set it back
2316 * to the drawable. This is modeled after what Mesa GLX's Apple
2317 * implementation does.
2319 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2321 struct wgl_context *context = NtCurrentTeb()->glContext;
2323 if (context->read_view || context->read_pbuffer)
2324 make_context_current(context, TRUE);
2326 pglCopyPixels(x, y, width, height, type);
2328 if (context->read_view || context->read_pbuffer)
2329 make_context_current(context, FALSE);
2333 /**********************************************************************
2334 * macdrv_glFinish
2336 static void macdrv_glFinish(void)
2338 struct wgl_context *context = NtCurrentTeb()->glContext;
2340 sync_swap_interval(context);
2341 sync_context(context);
2342 pglFinish();
2346 /**********************************************************************
2347 * macdrv_glFlush
2349 static void macdrv_glFlush(void)
2351 struct wgl_context *context = NtCurrentTeb()->glContext;
2353 sync_swap_interval(context);
2354 sync_context(context);
2356 if (skip_single_buffer_flushes)
2358 const pixel_format *pf = &pixel_formats[context->format - 1];
2359 DWORD now = GetTickCount();
2361 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2362 context->last_flush_time, now);
2363 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2365 TRACE("calling glFlushRenderAPPLE()\n");
2366 pglFlushRenderAPPLE();
2367 return;
2369 else
2371 TRACE("calling glFlush()\n");
2372 context->last_flush_time = now;
2376 pglFlush();
2380 /**********************************************************************
2381 * macdrv_glGetString
2383 * Hook into glGetString in order to return some legacy WGL extensions
2384 * that couldn't be advertised via the standard
2385 * WGL_ARB_extensions_string mechanism. Some programs, especially
2386 * older ones, expect to find certain older extensions, such as
2387 * WGL_EXT_extensions_string itself, in the standard GL extensions
2388 * string, and won't query any other WGL extensions unless they find
2389 * that particular extension there.
2391 static const GLubyte *macdrv_glGetString(GLenum name)
2393 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2394 return (const GLubyte *)gl_info.glExtensions;
2395 else
2396 return pglGetString(name);
2400 /**********************************************************************
2401 * macdrv_glReadPixels
2403 * Hook into glReadPixels as part of the implementation of
2404 * wglMakeContextCurrentARB. If the context has a separate readable,
2405 * temporarily make that current, do glReadPixels, and then set it back
2406 * to the drawable. This is modeled after what Mesa GLX's Apple
2407 * implementation does.
2409 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2410 GLenum format, GLenum type, void *pixels)
2412 struct wgl_context *context = NtCurrentTeb()->glContext;
2414 if (context->read_view || context->read_pbuffer)
2415 make_context_current(context, TRUE);
2417 pglReadPixels(x, y, width, height, format, type, pixels);
2419 if (context->read_view || context->read_pbuffer)
2420 make_context_current(context, FALSE);
2424 /**********************************************************************
2425 * macdrv_glViewport
2427 * Hook into glViewport as an opportunity to update the OpenGL context
2428 * if necessary. This is modeled after what Mesa GLX's Apple
2429 * implementation does.
2431 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2433 struct wgl_context *context = NtCurrentTeb()->glContext;
2435 sync_context(context);
2436 macdrv_update_opengl_context(context->context);
2437 pglViewport(x, y, width, height);
2441 /***********************************************************************
2442 * macdrv_wglBindTexImageARB
2444 * WGL_ARB_render_texture: wglBindTexImageARB
2446 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2448 struct wgl_context *context = NtCurrentTeb()->glContext;
2449 GLenum source;
2450 CGLError err;
2452 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2454 if (pbuffer->no_texture)
2456 SetLastError(ERROR_INVALID_OPERATION);
2457 return GL_FALSE;
2460 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2461 opengl_funcs.gl.p_glFlush();
2463 switch (iBuffer)
2465 case WGL_FRONT_LEFT_ARB:
2466 if (pixel_formats[pbuffer->format - 1].stereo)
2467 source = GL_FRONT_LEFT;
2468 else
2469 source = GL_FRONT;
2470 break;
2471 case WGL_FRONT_RIGHT_ARB:
2472 source = GL_FRONT_RIGHT;
2473 break;
2474 case WGL_BACK_LEFT_ARB:
2475 if (pixel_formats[pbuffer->format - 1].stereo)
2476 source = GL_BACK_LEFT;
2477 else
2478 source = GL_BACK;
2479 break;
2480 case WGL_BACK_RIGHT_ARB:
2481 source = GL_BACK_RIGHT;
2482 break;
2483 case WGL_AUX0_ARB: source = GL_AUX0; break;
2484 case WGL_AUX1_ARB: source = GL_AUX1; break;
2485 case WGL_AUX2_ARB: source = GL_AUX2; break;
2486 case WGL_AUX3_ARB: source = GL_AUX3; break;
2488 case WGL_AUX4_ARB:
2489 case WGL_AUX5_ARB:
2490 case WGL_AUX6_ARB:
2491 case WGL_AUX7_ARB:
2492 case WGL_AUX8_ARB:
2493 case WGL_AUX9_ARB:
2494 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2495 SetLastError(ERROR_INVALID_DATA);
2496 return GL_FALSE;
2498 default:
2499 WARN("unknown source buffer 0x%x\n", iBuffer);
2500 SetLastError(ERROR_INVALID_DATA);
2501 return GL_FALSE;
2504 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2505 if (err != kCGLNoError)
2507 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2508 SetLastError(ERROR_INVALID_OPERATION);
2509 return GL_FALSE;
2512 return GL_TRUE;
2516 /***********************************************************************
2517 * macdrv_wglChoosePixelFormatARB
2519 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2521 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2522 const FLOAT *pfAttribFList, UINT nMaxFormats,
2523 int *piFormats, UINT *nNumFormats)
2525 pixel_format pf, valid;
2526 const int *iptr;
2527 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2528 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2529 int float_color;
2530 BOOL srgb;
2531 int i, found = 0;
2533 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2534 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2535 if (pfAttribFList)
2536 FIXME("unused pfAttribFList\n");
2538 memset(&pf, 0, sizeof(pf));
2539 memset(&valid, 0, sizeof(valid));
2540 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2541 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2542 float_color = -1;
2543 srgb = FALSE;
2545 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2547 int attr = iptr[0];
2548 int value = iptr[1];
2550 TRACE("%s\n", debugstr_attrib(attr, value));
2552 switch (attr)
2554 case WGL_DRAW_TO_WINDOW_ARB:
2555 if (valid.window && (!pf.window != !value)) goto cant_match;
2556 pf.window = (value != 0);
2557 valid.window = 1;
2558 break;
2560 case WGL_DRAW_TO_BITMAP_ARB:
2561 goto cant_match;
2563 case WGL_ACCELERATION_ARB:
2564 if (value == WGL_FULL_ACCELERATION_ARB)
2565 value = 1;
2566 else if (value == WGL_NO_ACCELERATION_ARB)
2567 value = 0;
2568 else
2569 goto cant_match;
2570 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2571 pf.accelerated = value;
2572 valid.accelerated = 1;
2573 break;
2575 case WGL_NEED_PALETTE_ARB:
2576 case WGL_NEED_SYSTEM_PALETTE_ARB:
2577 case WGL_SWAP_LAYER_BUFFERS_ARB:
2578 if (value) goto cant_match;
2579 break;
2581 case WGL_SWAP_METHOD_ARB:
2582 if (value == WGL_SWAP_COPY_ARB)
2583 value = 1;
2584 else if (value == WGL_SWAP_UNDEFINED_ARB)
2585 value = 0;
2586 else
2587 goto cant_match;
2588 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2589 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2590 pf.backing_store = value;
2591 valid.backing_store = 1;
2592 break;
2594 case WGL_NUMBER_OVERLAYS_ARB:
2595 case WGL_NUMBER_UNDERLAYS_ARB:
2596 if (value) goto cant_match;
2597 break;
2599 case WGL_SHARE_DEPTH_ARB:
2600 case WGL_SHARE_STENCIL_ARB:
2601 case WGL_SHARE_ACCUM_ARB:
2602 /* no effect */
2603 break;
2605 case WGL_SUPPORT_GDI_ARB:
2606 if (value) goto cant_match;
2607 break;
2609 case WGL_SUPPORT_OPENGL_ARB:
2610 if (!value) goto cant_match;
2611 break;
2613 case WGL_DOUBLE_BUFFER_ARB:
2614 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2615 pf.double_buffer = (value != 0);
2616 valid.double_buffer = 1;
2617 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2618 break;
2620 case WGL_STEREO_ARB:
2621 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2622 pf.stereo = (value != 0);
2623 valid.stereo = 1;
2624 break;
2626 case WGL_PIXEL_TYPE_ARB:
2627 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2628 value = 1;
2629 else if (value == WGL_TYPE_RGBA_ARB)
2630 value = 0;
2631 else
2633 /* Mac contexts don't support rendering to unsigned floating
2634 point formats, even if GL_EXT_packed_float is supported.
2635 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2636 goto cant_match;
2638 if (float_color != -1 && float_color != value) goto cant_match;
2639 if (srgb && value) goto cant_match;
2640 float_color = value;
2641 break;
2643 case WGL_COLOR_BITS_ARB:
2644 if (color_bits < value) color_bits = value;
2645 break;
2647 case WGL_RED_BITS_ARB:
2648 if (srgb && value > 8) goto cant_match;
2649 if (red_bits < value) red_bits = value;
2650 break;
2652 case WGL_GREEN_BITS_ARB:
2653 if (srgb && value > 8) goto cant_match;
2654 if (green_bits < value) green_bits = value;
2655 break;
2657 case WGL_BLUE_BITS_ARB:
2658 if (srgb && value > 8) goto cant_match;
2659 if (blue_bits < value) blue_bits = value;
2660 break;
2662 case WGL_ALPHA_BITS_ARB:
2663 if (alpha_bits < value) alpha_bits = value;
2664 break;
2666 case WGL_ACCUM_BITS_ARB:
2667 if (accum_bits < value) accum_bits = value;
2668 break;
2670 case WGL_ACCUM_RED_BITS_ARB:
2671 if (accum_red_bits < value) accum_red_bits = value;
2672 break;
2674 case WGL_ACCUM_GREEN_BITS_ARB:
2675 if (accum_green_bits < value) accum_green_bits = value;
2676 break;
2678 case WGL_ACCUM_BLUE_BITS_ARB:
2679 if (accum_blue_bits < value) accum_blue_bits = value;
2680 break;
2682 case WGL_ACCUM_ALPHA_BITS_ARB:
2683 if (accum_alpha_bits < value) accum_alpha_bits = value;
2684 break;
2686 case WGL_DEPTH_BITS_ARB:
2687 if (value > 255) goto cant_match;
2688 if (pf.depth_bits < value) pf.depth_bits = value;
2689 break;
2691 case WGL_STENCIL_BITS_ARB:
2692 if (value > 255) goto cant_match;
2693 if (pf.stencil_bits < value) pf.stencil_bits = value;
2694 break;
2696 case WGL_AUX_BUFFERS_ARB:
2697 if (value > 7) goto cant_match;
2698 if (pf.aux_buffers < value) pf.aux_buffers = value;
2699 break;
2701 case WGL_SAMPLE_BUFFERS_ARB:
2702 if (value > 1) goto cant_match;
2703 if (pf.sample_buffers < value) pf.sample_buffers = value;
2704 break;
2706 case WGL_SAMPLES_ARB:
2707 if (value > 31) goto cant_match;
2708 if (pf.samples < value) pf.samples = value;
2709 break;
2711 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2712 /* sRGB is only supported for 8-bit integer color components */
2713 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2714 goto cant_match;
2715 srgb = TRUE;
2716 break;
2718 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2719 case WGL_RED_SHIFT_ARB:
2720 case WGL_GREEN_SHIFT_ARB:
2721 case WGL_BLUE_SHIFT_ARB:
2722 case WGL_ALPHA_SHIFT_ARB:
2723 case WGL_TRANSPARENT_ARB:
2724 case WGL_TRANSPARENT_RED_VALUE_ARB:
2725 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2726 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2727 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2728 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2729 /* ignored */
2730 break;
2732 case WGL_DRAW_TO_PBUFFER_ARB:
2733 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2734 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2735 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2736 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2737 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2738 pf.pbuffer = (value != 0);
2739 valid.pbuffer = 1;
2740 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2741 !alpha_bits)
2742 alpha_bits = 1;
2743 break;
2745 default:
2746 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2747 return GL_FALSE;
2751 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",
2752 valid.window ? (pf.window ? "1" : "0") : "?",
2753 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2754 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2755 color_bits,
2756 float_color == -1 ? "?" : float_color ? "f" : "",
2757 red_bits,
2758 green_bits,
2759 blue_bits,
2760 alpha_bits,
2761 (int)srgb,
2762 accum_bits,
2763 accum_red_bits,
2764 accum_green_bits,
2765 accum_blue_bits,
2766 accum_alpha_bits,
2767 pf.depth_bits,
2768 pf.stencil_bits,
2769 pf.aux_buffers,
2770 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2771 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2772 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2773 pf.sample_buffers,
2774 pf.samples);
2776 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2778 const struct color_mode *mode;
2780 if (valid.window && pixel_formats[i].window != pf.window) continue;
2781 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2782 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2783 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2784 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2785 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2787 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2788 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2789 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2790 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2791 if (pixel_formats[i].samples < pf.samples) continue;
2793 mode = &color_modes[pixel_formats[i].color_mode];
2794 /* If the mode doesn't have alpha, check requested color bits against
2795 bits per pixel instead of the mode's color bits. On Windows, color
2796 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2797 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2798 expects that to match such a pixel format, we need to accommodate that. */
2799 if (mode->alpha_bits)
2801 if (mode->color_bits < color_bits)
2802 continue;
2804 else
2806 if (mode->bits_per_pixel < color_bits)
2807 continue;
2809 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2810 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2811 continue;
2812 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2813 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2814 continue;
2816 if (pixel_formats[i].accum_mode)
2818 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2819 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2820 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2821 mode->alpha_bits < accum_alpha_bits)
2822 continue;
2824 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2825 continue;
2827 piFormats[found++] = i + 1;
2828 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2831 cant_match:
2832 *nNumFormats = found;
2834 return TRUE;
2838 /***********************************************************************
2839 * macdrv_wglCreateContextAttribsARB
2841 * WGL_ARB_create_context: wglCreateContextAttribsARB
2843 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2844 struct wgl_context *share_context,
2845 const int *attrib_list)
2847 int format;
2848 struct wgl_context *context;
2849 const int *iptr;
2850 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2851 BOOL core = FALSE;
2852 GLint renderer_id = 0;
2854 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2856 format = get_dc_pixel_format(hdc);
2858 if (!is_valid_pixel_format(format))
2860 ERR("Invalid pixel format %d, expect problems!\n", format);
2861 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2862 return NULL;
2865 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2867 int attr = iptr[0];
2868 int value = iptr[1];
2870 TRACE("%s\n", debugstr_attrib(attr, value));
2872 switch (attr)
2874 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2875 major = value;
2876 break;
2878 case WGL_CONTEXT_MINOR_VERSION_ARB:
2879 minor = value;
2880 break;
2882 case WGL_CONTEXT_LAYER_PLANE_ARB:
2883 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2884 break;
2886 case WGL_CONTEXT_FLAGS_ARB:
2887 flags = value;
2888 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2889 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2890 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2891 break;
2893 case WGL_CONTEXT_PROFILE_MASK_ARB:
2894 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2895 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2897 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2898 SetLastError(ERROR_INVALID_PROFILE_ARB);
2899 return NULL;
2901 profile = value;
2902 break;
2904 case WGL_RENDERER_ID_WINE:
2906 CGLError err;
2907 CGLRendererInfoObj renderer_info;
2908 GLint renderer_count, temp;
2910 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2911 if (err != kCGLNoError)
2913 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2914 SetLastError(ERROR_GEN_FAILURE);
2915 return NULL;
2918 value = map_renderer_index(renderer_info, renderer_count, value);
2920 if (value >= renderer_count)
2922 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2923 CGLDestroyRendererInfo(renderer_info);
2924 SetLastError(ERROR_INVALID_PARAMETER);
2925 return NULL;
2928 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2930 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2931 CGLDestroyRendererInfo(renderer_info);
2932 SetLastError(ERROR_GEN_FAILURE);
2933 return NULL;
2936 CGLDestroyRendererInfo(renderer_info);
2938 if (renderer_id && temp != renderer_id)
2940 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2941 SetLastError(ERROR_INVALID_PARAMETER);
2942 return NULL;
2944 renderer_id = temp;
2945 break;
2948 default:
2949 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2950 SetLastError(ERROR_INVALID_PARAMETER);
2951 return NULL;
2955 if ((major == 3 && (minor == 2 || minor == 3)) ||
2956 (major == 4 && (minor == 0 || minor == 1)))
2958 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2960 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2961 SetLastError(ERROR_INVALID_VERSION_ARB);
2962 return NULL;
2964 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2966 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2967 SetLastError(ERROR_INVALID_PROFILE_ARB);
2968 return NULL;
2970 if (major > gl_info.max_major ||
2971 (major == gl_info.max_major && minor > gl_info.max_minor))
2973 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2974 major, minor);
2975 SetLastError(ERROR_INVALID_PROFILE_ARB);
2976 return NULL;
2978 core = TRUE;
2980 else if (major >= 3)
2982 WARN("Profile version %u.%u not supported\n", major, minor);
2983 SetLastError(ERROR_INVALID_VERSION_ARB);
2984 return NULL;
2986 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2987 (major == 2 && (minor < 0 || minor > 1)))
2989 WARN("Invalid GL version requested\n");
2990 SetLastError(ERROR_INVALID_VERSION_ARB);
2991 return NULL;
2993 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2995 WARN("Forward compatible context requested for GL version < 3\n");
2996 SetLastError(ERROR_INVALID_VERSION_ARB);
2997 return NULL;
3000 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3002 context->format = format;
3003 context->renderer_id = renderer_id;
3004 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
3006 HeapFree(GetProcessHeap(), 0, context);
3007 return NULL;
3010 EnterCriticalSection(&context_section);
3011 list_add_tail(&context_list, &context->entry);
3012 LeaveCriticalSection(&context_section);
3014 return context;
3018 /**********************************************************************
3019 * macdrv_wglCreatePbufferARB
3021 * WGL_ARB_pbuffer: wglCreatePbufferARB
3023 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
3024 const int *piAttribList)
3026 struct wgl_pbuffer* pbuffer;
3027 GLenum target = 0;
3028 GLenum internalFormat = 0;
3029 CGLError err;
3031 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
3032 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
3034 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
3036 WARN("invalid pixel format %d\n", iPixelFormat);
3037 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3038 return NULL;
3041 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
3042 pbuffer->format = iPixelFormat;
3044 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3046 int attr = piAttribList[0];
3047 int value = piAttribList[1];
3049 switch (attr)
3051 case WGL_PBUFFER_LARGEST_ARB:
3052 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
3053 break;
3055 case WGL_TEXTURE_FORMAT_ARB:
3056 switch (value)
3058 case WGL_TEXTURE_RGBA_ARB:
3059 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
3060 internalFormat = GL_RGBA;
3061 break;
3062 case WGL_TEXTURE_RGB_ARB:
3063 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
3064 internalFormat = GL_RGB;
3065 break;
3066 case WGL_NO_TEXTURE_ARB:
3067 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
3068 internalFormat = 0;
3069 break;
3070 default:
3071 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
3072 SetLastError(ERROR_INVALID_DATA);
3073 goto done;
3075 break;
3077 case WGL_TEXTURE_TARGET_ARB:
3078 pbuffer->face = 0;
3079 switch (value)
3081 case WGL_NO_TEXTURE_ARB:
3082 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
3083 target = 0;
3084 break;
3085 case WGL_TEXTURE_CUBE_MAP_ARB:
3086 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
3087 target = GL_TEXTURE_CUBE_MAP;
3088 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3089 break;
3090 case WGL_TEXTURE_1D_ARB:
3091 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
3092 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3093 goto done;
3094 case WGL_TEXTURE_2D_ARB:
3095 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
3096 target = GL_TEXTURE_2D;
3097 break;
3098 case WGL_TEXTURE_RECTANGLE_NV:
3099 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
3100 target = GL_TEXTURE_RECTANGLE;
3101 break;
3102 default:
3103 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
3104 SetLastError(ERROR_INVALID_DATA);
3105 goto done;
3107 break;
3109 case WGL_MIPMAP_TEXTURE_ARB:
3110 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
3111 pbuffer->max_level = 0;
3112 if (value)
3114 int size = min(iWidth, iHeight) / 2;
3115 while (size)
3117 pbuffer->max_level++;
3118 size /= 2;
3121 break;
3123 default:
3124 WARN("unknown attribute 0x%x\n", attr);
3125 SetLastError(ERROR_INVALID_DATA);
3126 goto done;
3130 if (!target || !internalFormat)
3132 pbuffer->no_texture = TRUE;
3133 /* no actual way to turn off ability to texture; use most permissive target */
3134 target = GL_TEXTURE_RECTANGLE;
3135 internalFormat = GL_RGB;
3138 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3139 if (err != kCGLNoError)
3141 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3142 pbuffer->pbuffer = NULL;
3143 if (err == kCGLBadAlloc)
3144 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3145 else
3146 SetLastError(ERROR_INVALID_DATA);
3149 done:
3150 if (!pbuffer->pbuffer)
3152 HeapFree(GetProcessHeap(), 0, pbuffer);
3153 return NULL;
3156 TRACE(" -> %p\n", pbuffer);
3157 return pbuffer;
3161 /**********************************************************************
3162 * macdrv_wglDestroyPbufferARB
3164 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3166 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3168 TRACE("pbuffer %p\n", pbuffer);
3169 if (pbuffer && pbuffer->pbuffer)
3170 CGLReleasePBuffer(pbuffer->pbuffer);
3171 HeapFree(GetProcessHeap(), 0, pbuffer);
3172 return GL_TRUE;
3176 /**********************************************************************
3177 * macdrv_wglGetExtensionsStringARB
3179 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3181 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3183 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3184 this can be specific to the CGL renderer like we're supposed to do. */
3185 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3186 return gl_info.wglExtensions;
3190 /**********************************************************************
3191 * macdrv_wglGetExtensionsStringEXT
3193 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3195 static const char *macdrv_wglGetExtensionsStringEXT(void)
3197 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3198 return gl_info.wglExtensions;
3202 /**********************************************************************
3203 * macdrv_wglGetPbufferDCARB
3205 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3207 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3209 HDC hdc;
3210 struct wgl_pbuffer *prev;
3212 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3213 if (!hdc) return 0;
3215 EnterCriticalSection(&dc_pbuffers_section);
3216 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3217 if (prev)
3219 CGLReleasePBuffer(prev->pbuffer);
3220 HeapFree(GetProcessHeap(), 0, prev);
3222 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3223 LeaveCriticalSection(&dc_pbuffers_section);
3225 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3226 return hdc;
3230 /**********************************************************************
3231 * macdrv_wglGetPixelFormatAttribivARB
3233 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3235 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3236 UINT nAttributes, const int *piAttributes, int *piValues)
3238 const pixel_format *pf;
3239 UINT i;
3241 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3242 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3244 if (!nAttributes) return GL_TRUE;
3246 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3248 piValues[0] = nb_formats;
3249 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3250 return GL_TRUE;
3253 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3254 if (!pf)
3256 WARN("invalid pixel format %d\n", iPixelFormat);
3257 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3258 return GL_FALSE;
3261 for (i = 0; i < nAttributes; ++i)
3263 switch (piAttributes[i])
3265 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3266 piValues[i] = nb_formats;
3267 break;
3269 case WGL_DRAW_TO_WINDOW_ARB:
3270 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3271 break;
3273 case WGL_DRAW_TO_BITMAP_ARB:
3274 piValues[i] = GL_FALSE;
3275 break;
3277 case WGL_ACCELERATION_ARB:
3278 if (iLayerPlane) goto invalid_layer;
3279 if (pf->accelerated)
3280 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3281 else
3282 piValues[i] = WGL_NO_ACCELERATION_ARB;
3283 break;
3285 case WGL_NEED_PALETTE_ARB:
3286 case WGL_NEED_SYSTEM_PALETTE_ARB:
3287 case WGL_SWAP_LAYER_BUFFERS_ARB:
3288 piValues[i] = GL_FALSE;
3289 break;
3291 case WGL_SWAP_METHOD_ARB:
3292 if (pf->double_buffer && pf->backing_store)
3293 piValues[i] = WGL_SWAP_COPY_ARB;
3294 else
3295 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3296 break;
3298 case WGL_NUMBER_OVERLAYS_ARB:
3299 case WGL_NUMBER_UNDERLAYS_ARB:
3300 piValues[i] = 0;
3301 break;
3303 case WGL_TRANSPARENT_ARB:
3304 if (iLayerPlane) goto invalid_layer;
3305 piValues[i] = GL_FALSE;
3306 break;
3308 case WGL_TRANSPARENT_RED_VALUE_ARB:
3309 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3310 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3311 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3312 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3313 if (iLayerPlane) goto invalid_layer;
3314 piValues[i] = 0;
3315 break;
3317 case WGL_SHARE_DEPTH_ARB:
3318 case WGL_SHARE_STENCIL_ARB:
3319 case WGL_SHARE_ACCUM_ARB:
3320 if (iLayerPlane) goto invalid_layer;
3321 piValues[i] = GL_TRUE;
3322 break;
3324 case WGL_SUPPORT_GDI_ARB:
3325 if (iLayerPlane) goto invalid_layer;
3326 piValues[i] = GL_FALSE;
3327 break;
3329 case WGL_SUPPORT_OPENGL_ARB:
3330 if (iLayerPlane) goto invalid_layer;
3331 piValues[i] = GL_TRUE;
3332 break;
3334 case WGL_DOUBLE_BUFFER_ARB:
3335 if (iLayerPlane) goto invalid_layer;
3336 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3337 break;
3339 case WGL_STEREO_ARB:
3340 if (iLayerPlane) goto invalid_layer;
3341 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3342 break;
3344 case WGL_PIXEL_TYPE_ARB:
3345 if (iLayerPlane) goto invalid_layer;
3346 if (color_modes[pf->color_mode].is_float)
3347 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3348 else
3349 piValues[i] = WGL_TYPE_RGBA_ARB;
3350 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3351 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3352 However, Mac contexts don't support rendering to unsigned floating-point
3353 formats, even when GL_EXT_packed_float is supported. */
3354 break;
3356 case WGL_COLOR_BITS_ARB:
3357 if (iLayerPlane) goto invalid_layer;
3358 /* If the mode doesn't have alpha, return bits per pixel instead
3359 of color bits. On Windows, color bits sometimes exceeds r+g+b
3360 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3361 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3362 pixel format, we need to accommodate that. */
3363 if (color_modes[pf->color_mode].alpha_bits)
3364 piValues[i] = color_modes[pf->color_mode].color_bits;
3365 else
3366 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3367 break;
3369 case WGL_RED_BITS_ARB:
3370 if (iLayerPlane) goto invalid_layer;
3371 piValues[i] = color_modes[pf->color_mode].red_bits;
3372 break;
3374 case WGL_RED_SHIFT_ARB:
3375 if (iLayerPlane) goto invalid_layer;
3376 piValues[i] = color_modes[pf->color_mode].red_shift;
3377 break;
3379 case WGL_GREEN_BITS_ARB:
3380 if (iLayerPlane) goto invalid_layer;
3381 piValues[i] = color_modes[pf->color_mode].green_bits;
3382 break;
3384 case WGL_GREEN_SHIFT_ARB:
3385 if (iLayerPlane) goto invalid_layer;
3386 piValues[i] = color_modes[pf->color_mode].green_shift;
3387 break;
3389 case WGL_BLUE_BITS_ARB:
3390 if (iLayerPlane) goto invalid_layer;
3391 piValues[i] = color_modes[pf->color_mode].blue_bits;
3392 break;
3394 case WGL_BLUE_SHIFT_ARB:
3395 if (iLayerPlane) goto invalid_layer;
3396 piValues[i] = color_modes[pf->color_mode].blue_shift;
3397 break;
3399 case WGL_ALPHA_BITS_ARB:
3400 if (iLayerPlane) goto invalid_layer;
3401 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3402 break;
3404 case WGL_ALPHA_SHIFT_ARB:
3405 if (iLayerPlane) goto invalid_layer;
3406 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3407 break;
3409 case WGL_ACCUM_BITS_ARB:
3410 if (iLayerPlane) goto invalid_layer;
3411 if (pf->accum_mode)
3412 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3413 else
3414 piValues[i] = 0;
3415 break;
3417 case WGL_ACCUM_RED_BITS_ARB:
3418 if (iLayerPlane) goto invalid_layer;
3419 if (pf->accum_mode)
3420 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3421 else
3422 piValues[i] = 0;
3423 break;
3425 case WGL_ACCUM_GREEN_BITS_ARB:
3426 if (iLayerPlane) goto invalid_layer;
3427 if (pf->accum_mode)
3428 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3429 else
3430 piValues[i] = 0;
3431 break;
3433 case WGL_ACCUM_BLUE_BITS_ARB:
3434 if (iLayerPlane) goto invalid_layer;
3435 if (pf->accum_mode)
3436 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3437 else
3438 piValues[i] = 0;
3439 break;
3441 case WGL_ACCUM_ALPHA_BITS_ARB:
3442 if (iLayerPlane) goto invalid_layer;
3443 if (pf->accum_mode)
3444 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3445 else
3446 piValues[i] = 0;
3447 break;
3449 case WGL_DEPTH_BITS_ARB:
3450 if (iLayerPlane) goto invalid_layer;
3451 piValues[i] = pf->depth_bits;
3452 break;
3454 case WGL_STENCIL_BITS_ARB:
3455 if (iLayerPlane) goto invalid_layer;
3456 piValues[i] = pf->stencil_bits;
3457 break;
3459 case WGL_AUX_BUFFERS_ARB:
3460 if (iLayerPlane) goto invalid_layer;
3461 piValues[i] = pf->aux_buffers;
3462 break;
3464 case WGL_SAMPLE_BUFFERS_ARB:
3465 if (iLayerPlane) goto invalid_layer;
3466 piValues[i] = pf->sample_buffers;
3467 break;
3469 case WGL_SAMPLES_ARB:
3470 if (iLayerPlane) goto invalid_layer;
3471 piValues[i] = pf->samples;
3472 break;
3474 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3475 if (iLayerPlane) goto invalid_layer;
3476 /* sRGB is only supported for 8-bit integer color components */
3477 if (color_modes[pf->color_mode].red_bits == 8 &&
3478 color_modes[pf->color_mode].green_bits == 8 &&
3479 color_modes[pf->color_mode].blue_bits == 8 &&
3480 !color_modes[pf->color_mode].is_float)
3481 piValues[i] = GL_TRUE;
3482 else
3483 piValues[i] = GL_FALSE;
3484 break;
3486 case WGL_DRAW_TO_PBUFFER_ARB:
3487 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3488 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3489 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3490 break;
3492 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3493 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3494 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3495 break;
3497 case WGL_MAX_PBUFFER_WIDTH_ARB:
3498 piValues[i] = gl_info.max_viewport_dims[0];
3499 break;
3501 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3502 piValues[i] = gl_info.max_viewport_dims[1];
3503 break;
3505 case WGL_MAX_PBUFFER_PIXELS_ARB:
3506 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3507 break;
3509 default:
3510 WARN("invalid attribute %x\n", piAttributes[i]);
3511 return GL_FALSE;
3514 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3517 return GL_TRUE;
3519 invalid_layer:
3520 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3521 return GL_FALSE;
3525 /**********************************************************************
3526 * macdrv_wglGetPixelFormatAttribfvARB
3528 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3530 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3531 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3533 int *attr;
3534 int ret;
3536 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3537 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3539 /* Allocate a temporary array to store integer values */
3540 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
3541 if (!attr)
3543 ERR("couldn't allocate %d array\n", nAttributes);
3544 return GL_FALSE;
3547 /* Piggy-back on wglGetPixelFormatAttribivARB */
3548 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3549 if (ret)
3551 UINT i;
3553 /* Convert integer values to float. Should also check for attributes
3554 that can give decimal values here */
3555 for (i = 0; i < nAttributes; i++)
3556 pfValues[i] = attr[i];
3559 HeapFree(GetProcessHeap(), 0, attr);
3560 return ret;
3564 /**********************************************************************
3565 * macdrv_wglGetSwapIntervalEXT
3567 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3569 static int macdrv_wglGetSwapIntervalEXT(void)
3571 struct wgl_context *context = NtCurrentTeb()->glContext;
3572 struct macdrv_win_data *data;
3573 long value;
3574 CGLError err;
3576 TRACE("\n");
3578 if ((data = get_win_data(context->draw_hwnd)))
3580 value = data->swap_interval;
3581 release_win_data(data);
3583 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3584 set_swap_interval(context, value);
3586 else
3588 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3589 if (err != kCGLNoError)
3591 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3592 err, CGLErrorString(err));
3593 value = 1;
3597 return value;
3601 /***********************************************************************
3602 * macdrv_wglMakeContextCurrentARB
3604 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3606 * This is not supported directly by OpenGL on the Mac. We emulate it
3607 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3608 * temporarily swap the drawable. This follows the technique used in
3609 * the implementation of Mesa GLX for Apple.
3611 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3613 struct macdrv_win_data *data;
3614 HWND hwnd;
3616 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3617 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3619 if (!context)
3621 macdrv_make_context_current(NULL, NULL, CGRectNull);
3622 NtCurrentTeb()->glContext = NULL;
3623 return TRUE;
3626 if ((hwnd = WindowFromDC(draw_hdc)))
3628 if (!(data = get_win_data(hwnd)))
3630 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3631 return FALSE;
3634 if (!data->pixel_format)
3636 WARN("no pixel format set\n");
3637 release_win_data(data);
3638 SetLastError(ERROR_INVALID_HANDLE);
3639 return FALSE;
3641 if (context->format != data->pixel_format)
3643 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3644 release_win_data(data);
3645 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3646 return FALSE;
3649 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3650 set_swap_interval(context, data->swap_interval);
3652 context->draw_hwnd = hwnd;
3653 context->draw_view = data->gl_view;
3654 context->draw_rect = data->gl_rect;
3655 context->draw_pbuffer = NULL;
3656 release_win_data(data);
3658 else
3660 struct wgl_pbuffer *pbuffer;
3662 EnterCriticalSection(&dc_pbuffers_section);
3663 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3664 if (pbuffer)
3666 if (context->format != pbuffer->format)
3668 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3669 LeaveCriticalSection(&dc_pbuffers_section);
3670 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3671 return FALSE;
3674 if (allow_vsync &&
3675 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3676 set_swap_interval(context, 0);
3678 else
3680 WARN("no window or pbuffer for DC\n");
3681 LeaveCriticalSection(&dc_pbuffers_section);
3682 SetLastError(ERROR_INVALID_HANDLE);
3683 return FALSE;
3686 context->draw_hwnd = NULL;
3687 context->draw_view = NULL;
3688 context->draw_pbuffer = pbuffer;
3689 LeaveCriticalSection(&dc_pbuffers_section);
3692 context->read_view = NULL;
3693 context->read_pbuffer = NULL;
3694 if (read_hdc && read_hdc != draw_hdc)
3696 if ((hwnd = WindowFromDC(read_hdc)))
3698 if ((data = get_win_data(hwnd)))
3700 if (data->gl_view != context->draw_view)
3702 context->read_view = data->gl_view;
3703 context->read_rect = data->gl_rect;
3705 release_win_data(data);
3708 else
3710 EnterCriticalSection(&dc_pbuffers_section);
3711 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3712 LeaveCriticalSection(&dc_pbuffers_section);
3716 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3717 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3718 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3720 make_context_current(context, FALSE);
3721 context->has_been_current = TRUE;
3722 NtCurrentTeb()->glContext = context;
3724 return TRUE;
3728 /**********************************************************************
3729 * macdrv_wglQueryCurrentRendererIntegerWINE
3731 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3733 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3735 BOOL ret = FALSE;
3736 struct wgl_context *context = NtCurrentTeb()->glContext;
3737 CGLPixelFormatObj pixel_format;
3738 CGLError err;
3739 GLint virtual_screen;
3740 GLint display_mask;
3741 GLint pf_renderer_id;
3742 CGLRendererInfoObj renderer_info;
3743 GLint renderer_count;
3744 GLint renderer;
3746 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3747 (context ? context->cglcontext : NULL), attribute, value);
3749 if (attribute == WGL_RENDERER_VERSION_WINE)
3751 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3752 get_fallback_renderer_version(value);
3753 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3754 return TRUE;
3757 pixel_format = CGLGetPixelFormat(context->cglcontext);
3758 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3759 if (err != kCGLNoError)
3761 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3762 return FALSE;
3765 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3766 if (err != kCGLNoError)
3768 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3769 return FALSE;
3772 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3773 if (err != kCGLNoError)
3775 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3776 return FALSE;
3779 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3780 if (err != kCGLNoError)
3782 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3783 return FALSE;
3786 for (renderer = 0; renderer < renderer_count; renderer++)
3788 GLint renderer_id;
3790 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3791 continue;
3793 if (renderer_id == pf_renderer_id)
3795 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3796 break;
3800 if (renderer >= renderer_count)
3801 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3803 CGLDestroyRendererInfo(renderer_info);
3804 return ret;
3808 /**********************************************************************
3809 * macdrv_wglQueryCurrentRendererStringWINE
3811 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3813 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3815 const char* ret = NULL;
3816 struct wgl_context *context = NtCurrentTeb()->glContext;
3818 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3819 (context ? context->cglcontext : NULL), attribute);
3821 switch (attribute)
3823 case WGL_RENDERER_DEVICE_ID_WINE:
3825 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3826 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3827 break;
3830 case WGL_RENDERER_VENDOR_ID_WINE:
3832 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3833 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3834 break;
3837 default:
3838 FIXME("unrecognized attribute 0x%04x\n", attribute);
3839 break;
3842 return ret;
3846 /**********************************************************************
3847 * macdrv_wglQueryPbufferARB
3849 * WGL_ARB_pbuffer: wglQueryPbufferARB
3851 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3853 CGLError err;
3854 GLsizei width;
3855 GLsizei height;
3856 GLenum target;
3857 GLenum internalFormat;
3858 GLint mipmap;
3860 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3862 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3863 if (err != kCGLNoError)
3865 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3866 SetLastError(ERROR_INVALID_HANDLE);
3867 return GL_FALSE;
3870 switch (iAttribute)
3872 case WGL_PBUFFER_WIDTH_ARB:
3873 *piValue = width;
3874 break;
3875 case WGL_PBUFFER_HEIGHT_ARB:
3876 *piValue = height;
3877 break;
3878 case WGL_PBUFFER_LOST_ARB:
3879 /* Mac PBuffers can't be lost */
3880 *piValue = GL_FALSE;
3881 break;
3882 case WGL_TEXTURE_FORMAT_ARB:
3883 if (pbuffer->no_texture)
3884 *piValue = WGL_NO_TEXTURE_ARB;
3885 else switch (internalFormat)
3887 case GL_RGBA:
3888 *piValue = WGL_TEXTURE_RGBA_ARB;
3889 break;
3890 case GL_RGB:
3891 default:
3892 *piValue = WGL_TEXTURE_RGB_ARB;
3893 break;
3895 break;
3896 case WGL_TEXTURE_TARGET_ARB:
3897 if (pbuffer->no_texture)
3898 *piValue = WGL_NO_TEXTURE_ARB;
3899 else switch (target)
3901 case GL_TEXTURE_CUBE_MAP:
3902 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3903 break;
3904 case GL_TEXTURE_2D:
3905 *piValue = WGL_TEXTURE_2D_ARB;
3906 break;
3907 case GL_TEXTURE_RECTANGLE:
3908 default:
3909 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3910 break;
3912 break;
3913 case WGL_MIPMAP_TEXTURE_ARB:
3914 *piValue = (pbuffer->max_level > 0);
3915 break;
3916 case WGL_MIPMAP_LEVEL_ARB:
3917 *piValue = pbuffer->level;
3918 break;
3919 case WGL_CUBE_MAP_FACE_ARB:
3920 switch (pbuffer->face)
3922 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3923 default:
3924 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3925 break;
3926 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3927 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3928 break;
3929 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3930 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3931 break;
3932 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3933 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3934 break;
3935 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3936 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3937 break;
3938 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3939 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3940 break;
3942 break;
3943 default:
3944 WARN("invalid attribute 0x%x\n", iAttribute);
3945 SetLastError(ERROR_INVALID_DATA);
3946 return GL_FALSE;
3949 return GL_TRUE;
3953 /**********************************************************************
3954 * macdrv_wglQueryRendererIntegerWINE
3956 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3958 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3960 BOOL ret = FALSE;
3961 CGLRendererInfoObj renderer_info;
3962 GLint renderer_count;
3963 CGLError err;
3965 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3967 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3968 if (err != kCGLNoError)
3970 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3971 return FALSE;
3974 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3976 if (renderer < renderer_count)
3977 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3978 else
3979 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3981 CGLDestroyRendererInfo(renderer_info);
3982 return ret;
3986 /**********************************************************************
3987 * macdrv_wglQueryRendererStringWINE
3989 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3991 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3993 const char* ret = NULL;
3994 CGLRendererInfoObj renderer_info;
3995 GLint renderer_count;
3996 CGLError err;
3998 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
4000 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
4001 if (err != kCGLNoError)
4003 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
4004 return FALSE;
4007 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
4009 if (renderer >= renderer_count)
4011 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
4012 goto done;
4015 switch (attribute)
4017 case WGL_RENDERER_DEVICE_ID_WINE:
4018 case WGL_RENDERER_VENDOR_ID_WINE:
4020 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
4021 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
4023 if (!pixel_format)
4024 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
4025 if (pixel_format)
4027 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
4028 CGLReleasePixelFormat(pixel_format);
4031 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
4032 break;
4035 default:
4036 FIXME("unrecognized attribute 0x%04x\n", attribute);
4037 break;
4040 done:
4041 CGLDestroyRendererInfo(renderer_info);
4042 return ret;
4046 /**********************************************************************
4047 * macdrv_wglReleasePbufferDCARB
4049 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
4051 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
4053 struct wgl_pbuffer *prev;
4055 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
4057 EnterCriticalSection(&dc_pbuffers_section);
4059 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4060 if (prev)
4062 if (prev != pbuffer)
4063 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
4064 CGLReleasePBuffer(prev->pbuffer);
4065 HeapFree(GetProcessHeap(), 0, prev);
4066 CFDictionaryRemoveValue(dc_pbuffers, hdc);
4068 else hdc = 0;
4070 LeaveCriticalSection(&dc_pbuffers_section);
4072 return hdc && DeleteDC(hdc);
4076 /**********************************************************************
4077 * macdrv_wglReleaseTexImageARB
4079 * WGL_ARB_render_texture: wglReleaseTexImageARB
4081 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
4083 struct wgl_context *context = NtCurrentTeb()->glContext;
4084 CGLError err;
4086 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
4088 if (pbuffer->no_texture)
4090 SetLastError(ERROR_INVALID_OPERATION);
4091 return GL_FALSE;
4094 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
4095 if (err != kCGLNoError)
4097 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
4098 SetLastError(ERROR_INVALID_OPERATION);
4099 return GL_FALSE;
4102 return GL_TRUE;
4106 /**********************************************************************
4107 * macdrv_wglSetPbufferAttribARB
4109 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4111 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
4113 struct wgl_context *context = NtCurrentTeb()->glContext;
4115 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
4117 for ( ; piAttribList && *piAttribList; piAttribList += 2)
4119 int attr = piAttribList[0];
4120 int value = piAttribList[1];
4121 switch (attr)
4123 case WGL_MIPMAP_LEVEL_ARB:
4124 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
4125 pbuffer->level = value;
4126 break;
4127 case WGL_CUBE_MAP_FACE_ARB:
4128 switch (value)
4130 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
4131 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4132 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4133 break;
4134 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4135 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4136 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4137 break;
4138 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4139 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4140 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4141 break;
4142 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4143 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4144 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4145 break;
4146 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4147 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4148 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4149 break;
4150 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4151 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4152 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4153 break;
4154 default:
4155 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4156 SetLastError(ERROR_INVALID_DATA);
4157 return GL_FALSE;
4159 break;
4160 default:
4161 WARN("invalide attribute 0x%x\n", attr);
4162 SetLastError(ERROR_INVALID_DATA);
4163 return GL_FALSE;
4167 if (context && context->draw_pbuffer == pbuffer)
4168 make_context_current(context, FALSE);
4170 return GL_TRUE;
4174 /**********************************************************************
4175 * macdrv_wglSetPixelFormatWINE
4177 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4179 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4181 return set_pixel_format(hdc, fmt, TRUE);
4185 /**********************************************************************
4186 * macdrv_wglSwapIntervalEXT
4188 * WGL_EXT_swap_control: wglSwapIntervalEXT
4190 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4192 struct wgl_context *context = NtCurrentTeb()->glContext;
4193 BOOL changed = FALSE;
4195 TRACE("interval %d\n", interval);
4197 if (interval < 0)
4199 SetLastError(ERROR_INVALID_DATA);
4200 return FALSE;
4202 if (interval > 1)
4203 interval = 1;
4205 if (context->draw_hwnd)
4207 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4208 if (data)
4210 changed = data->swap_interval != interval;
4211 if (changed)
4212 data->swap_interval = interval;
4213 release_win_data(data);
4216 else /* pbuffer */
4217 interval = 0;
4219 InterlockedExchange(&context->update_swap_interval, FALSE);
4220 if (!set_swap_interval(context, interval))
4222 SetLastError(ERROR_GEN_FAILURE);
4223 return FALSE;
4226 if (changed)
4228 struct wgl_context *ctx;
4230 EnterCriticalSection(&context_section);
4231 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4233 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4234 InterlockedExchange(&context->update_swap_interval, TRUE);
4236 LeaveCriticalSection(&context_section);
4239 return TRUE;
4243 static void register_extension(const char *ext)
4245 if (gl_info.wglExtensions[0])
4246 strcat(gl_info.wglExtensions, " ");
4247 strcat(gl_info.wglExtensions, ext);
4249 TRACE("'%s'\n", ext);
4252 static void load_extensions(void)
4255 * ARB Extensions
4257 register_extension("WGL_ARB_extensions_string");
4258 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4260 register_extension("WGL_ARB_make_current_read");
4261 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4262 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4264 register_extension("WGL_ARB_pixel_format");
4265 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4266 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4267 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4269 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4271 register_extension("WGL_ARB_pixel_format_float");
4272 register_extension("WGL_ATI_pixel_format_float");
4275 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4276 register_extension("WGL_ARB_multisample");
4278 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4279 register_extension("WGL_ARB_framebuffer_sRGB");
4281 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4283 register_extension("WGL_ARB_pbuffer");
4284 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4285 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4286 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4287 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4288 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4290 register_extension("WGL_ARB_render_texture");
4291 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4292 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4293 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4295 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4296 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4297 register_extension("WGL_NV_render_texture_rectangle");
4300 register_extension("WGL_ARB_create_context");
4301 register_extension("WGL_ARB_create_context_profile");
4302 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4305 * EXT Extensions
4307 register_extension("WGL_EXT_extensions_string");
4308 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4310 if (allow_vsync)
4312 register_extension("WGL_EXT_swap_control");
4313 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4314 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4317 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4318 check for either, so register them separately. */
4319 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4320 register_extension("WGL_EXT_framebuffer_sRGB");
4322 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4323 register_extension("WGL_EXT_pixel_format_packed_float");
4326 * WINE-specific WGL Extensions
4329 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4330 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4332 register_extension("WGL_WINE_pixel_format_passthrough");
4333 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4335 register_extension("WGL_WINE_query_renderer");
4336 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4337 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4338 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4339 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4343 static BOOL init_opengl(void)
4345 static BOOL init_done = FALSE;
4346 unsigned int i;
4347 char buffer[200];
4349 if (init_done) return (opengl_handle != NULL);
4350 init_done = TRUE;
4352 TRACE("()\n");
4354 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4355 if (!dc_pbuffers)
4357 WARN("CFDictionaryCreateMutable failed\n");
4358 return FALSE;
4361 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
4362 if (!opengl_handle)
4364 ERR("Failed to load OpenGL: %s\n", buffer);
4365 ERR("OpenGL support is disabled.\n");
4366 return FALSE;
4369 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
4371 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
4373 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4374 goto failed;
4378 /* redirect some standard OpenGL functions */
4379 #define REDIRECT(func) \
4380 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4381 REDIRECT(glCopyPixels);
4382 REDIRECT(glGetString);
4383 REDIRECT(glReadPixels);
4384 REDIRECT(glViewport);
4385 if (skip_single_buffer_flushes || allow_vsync)
4386 REDIRECT(glFlush);
4387 if (allow_vsync)
4388 REDIRECT(glFinish);
4389 #undef REDIRECT
4391 /* redirect some OpenGL extension functions */
4392 #define REDIRECT(func) \
4393 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4394 REDIRECT(glCopyColorTable);
4395 #undef REDIRECT
4397 if (!init_gl_info())
4398 goto failed;
4400 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4401 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
4403 load_extensions();
4404 if (!init_pixel_formats())
4405 goto failed;
4407 return TRUE;
4409 failed:
4410 wine_dlclose(opengl_handle, NULL, 0);
4411 opengl_handle = NULL;
4412 return FALSE;
4416 /***********************************************************************
4417 * sync_gl_view
4419 * Synchronize the Mac GL view position with the Windows child window
4420 * position.
4422 void sync_gl_view(struct macdrv_win_data *data)
4424 RECT rect;
4426 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
4428 if (!data->gl_view) return;
4430 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
4432 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
4433 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
4434 data->gl_rect = rect;
4435 mark_contexts_for_moved_view(data->gl_view);
4440 /**********************************************************************
4441 * macdrv_wglDescribePixelFormat
4443 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4445 const pixel_format *pf;
4446 const struct color_mode *mode;
4448 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4450 if (!descr) return nb_displayable_formats;
4451 if (size < sizeof(*descr)) return 0;
4453 if (!(pf = get_pixel_format(fmt, FALSE)))
4454 return 0;
4456 memset(descr, 0, sizeof(*descr));
4457 descr->nSize = sizeof(*descr);
4458 descr->nVersion = 1;
4460 descr->dwFlags = PFD_SUPPORT_OPENGL;
4461 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4462 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4463 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4464 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4465 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4467 descr->iPixelType = PFD_TYPE_RGBA;
4469 mode = &color_modes[pf->color_mode];
4470 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4471 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4472 R8G8B8A0 pixel format). If an app depends on that and expects that
4473 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4474 if (mode->alpha_bits)
4475 descr->cColorBits = mode->color_bits;
4476 else
4477 descr->cColorBits = mode->bits_per_pixel;
4478 descr->cRedBits = mode->red_bits;
4479 descr->cRedShift = mode->red_shift;
4480 descr->cGreenBits = mode->green_bits;
4481 descr->cGreenShift = mode->green_shift;
4482 descr->cBlueBits = mode->blue_bits;
4483 descr->cBlueShift = mode->blue_shift;
4484 descr->cAlphaBits = mode->alpha_bits;
4485 descr->cAlphaShift = mode->alpha_shift;
4487 if (pf->accum_mode)
4489 mode = &color_modes[pf->accum_mode - 1];
4490 descr->cAccumBits = mode->color_bits;
4491 descr->cAccumRedBits = mode->red_bits;
4492 descr->cAccumGreenBits = mode->green_bits;
4493 descr->cAccumBlueBits = mode->blue_bits;
4494 descr->cAccumAlphaBits = mode->alpha_bits;
4497 descr->cDepthBits = pf->depth_bits;
4498 descr->cStencilBits = pf->stencil_bits;
4499 descr->cAuxBuffers = pf->aux_buffers;
4500 descr->iLayerType = PFD_MAIN_PLANE;
4502 TRACE("%s\n", debugstr_pf(pf));
4503 return nb_displayable_formats;
4506 /***********************************************************************
4507 * macdrv_wglCopyContext
4509 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4511 CGLError err;
4513 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4515 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4516 if (err != kCGLNoError)
4517 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4518 return (err == kCGLNoError);
4521 /***********************************************************************
4522 * macdrv_wglCreateContext
4524 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
4526 struct wgl_context *context;
4528 TRACE("hdc %p\n", hdc);
4530 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4532 return context;
4535 /***********************************************************************
4536 * macdrv_wglDeleteContext
4538 static void macdrv_wglDeleteContext(struct wgl_context *context)
4540 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4542 EnterCriticalSection(&context_section);
4543 list_remove(&context->entry);
4544 LeaveCriticalSection(&context_section);
4546 macdrv_dispose_opengl_context(context->context);
4547 HeapFree(GetProcessHeap(), 0, context);
4550 /***********************************************************************
4551 * macdrv_wglGetPixelFormat
4553 static int macdrv_wglGetPixelFormat(HDC hdc)
4555 int format;
4557 format = get_dc_pixel_format(hdc);
4559 if (!is_valid_pixel_format(format)) /* not set yet */
4560 format = 0;
4561 else if (!is_displayable_pixel_format(format))
4563 /* Non-displayable formats can't be used with traditional WGL calls.
4564 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4565 format = 1;
4568 TRACE(" hdc %p -> %d\n", hdc, format);
4569 return format;
4572 /***********************************************************************
4573 * macdrv_wglGetProcAddress
4575 static PROC macdrv_wglGetProcAddress(const char *proc)
4577 void *ret;
4579 if (!strncmp(proc, "wgl", 3)) return NULL;
4580 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
4581 if (ret)
4583 if (TRACE_ON(wgl))
4585 Dl_info info;
4586 if (dladdr(ret, &info))
4587 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4588 else
4589 TRACE("%s -> %p (no library info)\n", proc, ret);
4592 else
4593 WARN("failed to find proc %s\n", debugstr_a(proc));
4594 return ret;
4597 /***********************************************************************
4598 * macdrv_wglMakeCurrent
4600 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4602 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4603 (context ? context->cglcontext : NULL));
4605 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4608 /**********************************************************************
4609 * macdrv_wglSetPixelFormat
4611 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4613 return set_pixel_format(hdc, fmt, FALSE);
4616 /***********************************************************************
4617 * macdrv_wglShareLists
4619 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4621 macdrv_opengl_context saved_context;
4622 CGLContextObj saved_cglcontext;
4624 TRACE("org %p dest %p\n", org, dest);
4626 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4627 * at context creation time but in case of WGL it is done using wglShareLists.
4629 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4630 * and when a program requests sharing we recreate the destination context if it hasn't been made
4631 * current or when it hasn't shared display lists before.
4634 if (dest->has_been_current)
4636 WARN("could not share display lists, the destination context has been current already\n");
4637 return FALSE;
4639 else if (dest->sharing)
4641 WARN("could not share display lists because dest has already shared lists before\n");
4642 return FALSE;
4645 /* Re-create the Mac context and share display lists */
4646 saved_context = dest->context;
4647 saved_cglcontext = dest->cglcontext;
4648 dest->context = NULL;
4649 dest->cglcontext = NULL;
4650 if (!create_context(dest, org->cglcontext, dest->major))
4652 dest->context = saved_context;
4653 dest->cglcontext = saved_cglcontext;
4654 return FALSE;
4657 /* Implicitly disposes of saved_cglcontext. */
4658 macdrv_dispose_opengl_context(saved_context);
4660 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4661 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4663 org->sharing = TRUE;
4664 dest->sharing = TRUE;
4666 return TRUE;
4669 /**********************************************************************
4670 * macdrv_wglSwapBuffers
4672 static BOOL macdrv_wglSwapBuffers(HDC hdc)
4674 struct wgl_context *context = NtCurrentTeb()->glContext;
4675 BOOL match = FALSE;
4676 HWND hwnd;
4678 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4679 (context ? context->cglcontext : NULL));
4681 if (context)
4683 sync_swap_interval(context);
4684 sync_context(context);
4687 if ((hwnd = WindowFromDC(hdc)))
4689 struct macdrv_win_data *data;
4691 if (!(data = get_win_data(hwnd)))
4693 SetLastError(ERROR_INVALID_HANDLE);
4694 return FALSE;
4697 if (context && context->draw_view == data->gl_view)
4698 match = TRUE;
4700 release_win_data(data);
4702 else
4704 struct wgl_pbuffer *pbuffer;
4706 EnterCriticalSection(&dc_pbuffers_section);
4707 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4708 LeaveCriticalSection(&dc_pbuffers_section);
4710 if (!pbuffer)
4712 SetLastError(ERROR_INVALID_HANDLE);
4713 return FALSE;
4716 if (context && context->draw_pbuffer == pbuffer)
4717 match = TRUE;
4720 if (match)
4721 macdrv_flush_opengl_context(context->context);
4722 else
4724 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4726 /* If there is a current context, then wglSwapBuffers should do an implicit
4727 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4728 in the other branch, but we have to do it explicitly here. */
4729 if (context)
4730 pglFlush();
4733 return TRUE;
4736 static struct opengl_funcs opengl_funcs =
4739 macdrv_wglCopyContext, /* p_wglCopyContext */
4740 macdrv_wglCreateContext, /* p_wglCreateContext */
4741 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4742 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4743 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4744 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4745 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4746 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4747 macdrv_wglShareLists, /* p_wglShareLists */
4748 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4752 /**********************************************************************
4753 * macdrv_wine_get_wgl_driver
4755 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
4757 if (version != WINE_WGL_DRIVER_VERSION)
4759 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4760 return NULL;
4763 if (!init_opengl()) return (void *)-1;
4765 return &opengl_funcs;