d2d1: Add D2D1Crop.
[wine.git] / dlls / winemac.drv / opengl.c
blob9f02e93d376967adf144812a3cbf1b18d4568259
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/debug.h"
31 #include "wine/wgl.h"
32 #include "wine/wgl_driver.h"
34 #define GL_SILENCE_DEPRECATION
35 #define __gl_h_
36 #define __gltypes_h_
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
40 #include <dlfcn.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
45 struct gl_info {
46 char *glExtensions;
48 char wglExtensions[4096];
50 GLint max_viewport_dims[2];
52 unsigned int max_major, max_minor;
55 static struct gl_info gl_info;
58 struct wgl_context
60 struct list entry;
61 int format;
62 GLint renderer_id;
63 macdrv_opengl_context context;
64 CGLContextObj cglcontext;
65 HWND draw_hwnd;
66 macdrv_view draw_view;
67 RECT draw_rect;
68 struct wgl_pbuffer *draw_pbuffer;
69 macdrv_view read_view;
70 RECT read_rect;
71 struct wgl_pbuffer *read_pbuffer;
72 BOOL has_been_current;
73 BOOL sharing;
74 LONG update_swap_interval;
75 LONG view_moved;
76 DWORD last_flush_time;
77 UINT major;
80 static struct list context_list = LIST_INIT(context_list);
82 static CRITICAL_SECTION context_section;
83 static CRITICAL_SECTION_DEBUG critsect_debug =
85 0, 0, &context_section,
86 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
87 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
89 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
92 struct wgl_pbuffer
94 CGLPBufferObj pbuffer;
95 int format;
96 BOOL no_texture;
97 int max_level;
98 GLint level;
99 GLenum face;
102 static CFMutableDictionaryRef dc_pbuffers;
104 static CRITICAL_SECTION dc_pbuffers_section;
105 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
107 0, 0, &dc_pbuffers_section,
108 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
109 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
111 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
114 static struct opengl_funcs opengl_funcs;
116 #define USE_GL_FUNC(name) #name,
117 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
118 #undef USE_GL_FUNC
121 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
122 GLsizei width);
123 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
124 static void (*pglFinish)(void);
125 static void (*pglFlush)(void);
126 static void (*pglFlushRenderAPPLE)(void);
127 static const GLubyte *(*pglGetString)(GLenum name);
128 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
129 GLenum format, GLenum type, void *pixels);
130 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
133 struct color_mode {
134 GLint mode;
135 int bits_per_pixel;
136 GLint color_bits; /* including alpha_bits */
137 int red_bits, red_shift;
138 int green_bits, green_shift;
139 int blue_bits, blue_shift;
140 GLint alpha_bits, alpha_shift;
141 BOOL is_float;
142 int color_ordering;
145 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
146 observations of the behavior of Windows systems, but also subjective judgments
147 about what color formats are more "normal" than others.
149 On at least some Windows systems, integer color formats are listed before
150 floating-point formats. Within the integer formats, higher color bits were
151 usually listed before lower color bits, while for floating-point formats it
152 was the reverse. However, that leads D3D to select 64-bit integer formats in
153 preference to 32-bit formats when the latter would be sufficient. It seems
154 that a 32-bit format is much more likely to be normally used in that case.
156 Also, there are certain odd color formats supported on the Mac which seem like
157 they would be less appropriate than more common ones. For instance, the color
158 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
159 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
160 components.
162 For two color formats which differ only in whether or not they have alpha bits,
163 we use the same ordering. pixel_format_comparator() gives alpha bits a
164 different weight than color formats.
166 static const struct color_mode color_modes[] = {
167 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
168 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
169 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
170 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
171 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
172 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
173 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
174 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
175 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
176 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
177 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
178 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
179 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
180 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
181 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
182 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
183 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
184 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
185 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
186 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
187 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
188 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
189 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
190 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
194 static const struct {
195 GLint mode;
196 int bits;
197 } depth_stencil_modes[] = {
198 { kCGL0Bit, 0 },
199 { kCGL1Bit, 1 },
200 { kCGL2Bit, 2 },
201 { kCGL3Bit, 3 },
202 { kCGL4Bit, 4 },
203 { kCGL5Bit, 5 },
204 { kCGL6Bit, 6 },
205 { kCGL8Bit, 8 },
206 { kCGL10Bit, 10 },
207 { kCGL12Bit, 12 },
208 { kCGL16Bit, 16 },
209 { kCGL24Bit, 24 },
210 { kCGL32Bit, 32 },
211 { kCGL48Bit, 48 },
212 { kCGL64Bit, 64 },
213 { kCGL96Bit, 96 },
214 { kCGL128Bit, 128 },
218 typedef struct {
219 GLint renderer_id;
220 GLint buffer_modes;
221 GLint color_modes;
222 GLint accum_modes;
223 GLint depth_modes;
224 GLint stencil_modes;
225 GLint max_aux_buffers;
226 GLint max_sample_buffers;
227 GLint max_samples;
228 BOOL offscreen;
229 BOOL accelerated;
230 BOOL backing_store;
231 BOOL window;
232 BOOL online;
233 } renderer_properties;
236 typedef struct {
237 unsigned int window:1;
238 unsigned int pbuffer:1;
239 unsigned int accelerated:1;
240 unsigned int color_mode:5; /* index into color_modes table */
241 unsigned int aux_buffers:3;
242 unsigned int depth_bits:8;
243 unsigned int stencil_bits:8;
244 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
245 unsigned int double_buffer:1;
246 unsigned int stereo:1;
247 unsigned int sample_buffers:1;
248 unsigned int samples:5;
249 unsigned int backing_store:1;
250 } pixel_format;
253 typedef union
255 pixel_format format;
256 UInt64 code;
257 } pixel_format_or_code;
258 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
261 static pixel_format *pixel_formats;
262 static int nb_formats, nb_displayable_formats;
265 static void *opengl_handle;
268 static const char* debugstr_attrib(int attrib, int value)
270 static const struct {
271 int attrib;
272 const char *name;
273 } attrib_names[] = {
274 #define ATTRIB(a) { a, #a }
275 ATTRIB(WGL_ACCELERATION_ARB),
276 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
277 ATTRIB(WGL_ACCUM_BITS_ARB),
278 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
279 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
280 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
281 ATTRIB(WGL_ALPHA_BITS_ARB),
282 ATTRIB(WGL_ALPHA_SHIFT_ARB),
283 ATTRIB(WGL_AUX_BUFFERS_ARB),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
286 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
287 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
288 ATTRIB(WGL_BLUE_BITS_ARB),
289 ATTRIB(WGL_BLUE_SHIFT_ARB),
290 ATTRIB(WGL_COLOR_BITS_ARB),
291 ATTRIB(WGL_DEPTH_BITS_ARB),
292 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
293 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
294 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
295 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
296 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
297 ATTRIB(WGL_GREEN_BITS_ARB),
298 ATTRIB(WGL_GREEN_SHIFT_ARB),
299 ATTRIB(WGL_NEED_PALETTE_ARB),
300 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
301 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
302 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
303 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
304 ATTRIB(WGL_PIXEL_TYPE_ARB),
305 ATTRIB(WGL_RED_BITS_ARB),
306 ATTRIB(WGL_RED_SHIFT_ARB),
307 ATTRIB(WGL_RENDERER_ID_WINE),
308 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
309 ATTRIB(WGL_SAMPLES_ARB),
310 ATTRIB(WGL_SHARE_ACCUM_ARB),
311 ATTRIB(WGL_SHARE_DEPTH_ARB),
312 ATTRIB(WGL_SHARE_STENCIL_ARB),
313 ATTRIB(WGL_STENCIL_BITS_ARB),
314 ATTRIB(WGL_STEREO_ARB),
315 ATTRIB(WGL_SUPPORT_GDI_ARB),
316 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
317 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
318 ATTRIB(WGL_SWAP_METHOD_ARB),
319 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
320 ATTRIB(WGL_TRANSPARENT_ARB),
321 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
322 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
323 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
324 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
325 #undef ATTRIB
327 int i;
328 const char *attrib_name = NULL;
329 const char *value_name = NULL;
331 for (i = 0; i < ARRAY_SIZE(attrib_names); i++)
333 if (attrib_names[i].attrib == attrib)
335 attrib_name = attrib_names[i].name;
336 break;
340 if (!attrib_name)
341 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
343 switch (attrib)
345 case WGL_ACCELERATION_ARB:
346 switch (value)
348 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
349 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
350 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
352 break;
353 case WGL_PIXEL_TYPE_ARB:
354 switch (value)
356 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
357 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
358 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
359 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
361 break;
362 case WGL_SWAP_METHOD_ARB:
363 switch (value)
365 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
366 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
367 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
369 break;
372 if (!value_name)
373 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
375 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
379 /**********************************************************************
380 * active_displays_mask
382 static CGOpenGLDisplayMask active_displays_mask(void)
384 CGError err;
385 CGDirectDisplayID displays[32];
386 uint32_t count, i;
387 CGOpenGLDisplayMask mask;
389 err = CGGetActiveDisplayList(ARRAY_SIZE(displays), displays, &count);
390 if (err != kCGErrorSuccess)
392 displays[0] = CGMainDisplayID();
393 count = 1;
396 mask = 0;
397 for (i = 0; i < count; i++)
398 mask |= CGDisplayIDToOpenGLDisplayMask(displays[i]);
400 return mask;
404 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
405 CGLRendererProperty property, GLint *value)
407 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
408 if (err != kCGLNoError)
409 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
410 return (err == kCGLNoError);
414 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
416 GLint value;
418 memset(properties, 0, sizeof(*properties));
420 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
421 properties->renderer_id = value & kCGLRendererIDMatchingMask;
423 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
424 properties->buffer_modes = value;
426 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
427 properties->color_modes = value;
429 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
430 properties->accum_modes = value;
432 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
433 properties->depth_modes = value;
435 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
436 properties->stencil_modes = value;
438 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
439 properties->max_aux_buffers = value;
441 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
442 properties->max_sample_buffers = value;
444 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
445 properties->max_samples = value;
447 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
448 properties->offscreen = (value != 0);
450 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
451 properties->accelerated = (value != 0);
453 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
454 properties->backing_store = (value != 0);
456 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
457 properties->window = (value != 0);
459 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
460 properties->online = (value != 0);
464 static void dump_renderer(const renderer_properties* renderer)
466 int i;
468 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
469 TRACE("Buffer modes:\n");
470 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
471 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
472 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
473 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
475 TRACE("Color buffer modes:\n");
476 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
478 if (renderer->color_modes & color_modes[i].mode)
480 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
481 if (color_modes[i].is_float)
482 TRACE(", Float");
483 TRACE("\n");
487 TRACE("Accumulation buffer sizes: { ");
488 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
490 if (renderer->accum_modes & color_modes[i].mode)
491 TRACE("%d, ", color_modes[i].color_bits);
493 TRACE("}\n");
495 TRACE("Depth buffer sizes: { ");
496 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
498 if (renderer->depth_modes & depth_stencil_modes[i].mode)
499 TRACE("%d, ", depth_stencil_modes[i].bits);
501 TRACE("}\n");
503 TRACE("Stencil buffer sizes: { ");
504 for (i = 0; i < ARRAY_SIZE(depth_stencil_modes); i++)
506 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
507 TRACE("%d, ", depth_stencil_modes[i].bits);
509 TRACE("}\n");
511 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
512 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
513 TRACE("Max. Samples: %d\n", renderer->max_samples);
514 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
515 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
516 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
517 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
518 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
522 static inline UInt64 code_for_pixel_format(const pixel_format* format)
524 pixel_format_or_code pfc;
526 pfc.code = 0;
527 pfc.format = *format;
528 return pfc.code;
532 static inline pixel_format pixel_format_for_code(UInt64 code)
534 pixel_format_or_code pfc;
536 pfc.code = code;
537 return pfc.format;
541 static const char *debugstr_pf(const pixel_format *pf)
543 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",
544 pf->window,
545 pf->pbuffer,
546 pf->accelerated,
547 color_modes[pf->color_mode].color_bits,
548 (color_modes[pf->color_mode].is_float ? "f" : ""),
549 color_modes[pf->color_mode].alpha_bits,
550 pf->depth_bits,
551 pf->stencil_bits,
552 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
553 pf->aux_buffers,
554 pf->backing_store,
555 pf->double_buffer,
556 pf->stereo,
557 pf->sample_buffers,
558 pf->samples,
559 code_for_pixel_format(pf));
563 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
565 int best = -1;
566 int i;
568 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
570 if ((modes & color_modes[i].mode) &&
571 color_modes[i].color_bits >= color_size &&
572 color_modes[i].alpha_bits >= alpha_size &&
573 !color_modes[i].is_float == !color_float)
575 if (best < 0) /* no existing best choice */
576 best = i;
577 else if (color_modes[i].color_bits == color_size &&
578 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
580 /* prefer it over a best which isn't exact or which has a higher bpp */
581 if (color_modes[best].color_bits != color_size ||
582 color_modes[best].alpha_bits != alpha_size ||
583 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
584 best = i;
586 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
587 (color_modes[i].color_bits == color_modes[best].color_bits &&
588 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
589 best = i;
593 if (best < 0)
595 /* Couldn't find a match. Return first one that renderer supports. */
596 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
598 if (modes & color_modes[i].mode)
599 return i;
603 return best;
607 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
609 int best = -1;
610 int i;
612 for (i = 0; i < ARRAY_SIZE(color_modes); i++)
614 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
616 /* Prefer the fewest color bits, then prefer more alpha bits, then
617 prefer more bits per pixel. */
618 if (best < 0)
619 best = i;
620 else if (color_modes[i].color_bits < color_modes[best].color_bits)
621 best = i;
622 else if (color_modes[i].color_bits == color_modes[best].color_bits)
624 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
625 best = i;
626 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
627 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
628 best = i;
633 if (best < 0)
635 /* Couldn't find a match. Return last one that renderer supports. */
636 for (i = ARRAY_SIZE(color_modes) - 1; i >= 0; i--)
638 if (modes & color_modes[i].mode)
639 return i;
643 return best;
647 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
648 CFMutableSetRef pixel_format_set)
650 CGLPixelFormatAttribute attribs[64] = {
651 kCGLPFAMinimumPolicy,
652 kCGLPFAClosestPolicy,
653 kCGLPFARendererID, renderer.renderer_id,
654 kCGLPFASingleRenderer,
656 int n = 5, n_stack[16], n_stack_idx = -1;
657 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
658 new_pixel_formats = 0;
659 pixel_format request;
660 unsigned int double_buffer;
661 unsigned int accelerated = renderer.accelerated;
663 if (accelerated)
665 attribs[n++] = kCGLPFAAccelerated;
666 attribs[n++] = kCGLPFANoRecovery;
668 else if (!allow_software_rendering)
670 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
671 return;
674 n_stack[++n_stack_idx] = n;
675 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
677 unsigned int aux;
679 n = n_stack[n_stack_idx];
681 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
682 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
683 continue;
685 if (double_buffer)
686 attribs[n++] = kCGLPFADoubleBuffer;
687 memset(&request, 0, sizeof(request));
688 request.accelerated = accelerated;
689 request.double_buffer = double_buffer;
691 /* Don't bother with in-between aux buffers values: either 0 or max. */
692 n_stack[++n_stack_idx] = n;
693 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
695 unsigned int color_mode;
697 n = n_stack[n_stack_idx];
699 attribs[n++] = kCGLPFAAuxBuffers;
700 attribs[n++] = aux;
701 request.aux_buffers = aux;
703 n_stack[++n_stack_idx] = n;
704 for (color_mode = 0; color_mode < ARRAY_SIZE(color_modes); color_mode++)
706 unsigned int depth_mode;
708 n = n_stack[n_stack_idx];
710 if (!(renderer.color_modes & color_modes[color_mode].mode))
711 continue;
713 attribs[n++] = kCGLPFAColorSize;
714 attribs[n++] = color_modes[color_mode].color_bits;
715 attribs[n++] = kCGLPFAAlphaSize;
716 attribs[n++] = color_modes[color_mode].alpha_bits;
717 if (color_modes[color_mode].is_float)
718 attribs[n++] = kCGLPFAColorFloat;
719 request.color_mode = color_mode;
721 n_stack[++n_stack_idx] = n;
722 for (depth_mode = 0; depth_mode < ARRAY_SIZE(depth_stencil_modes); depth_mode++)
724 unsigned int stencil_mode;
726 n = n_stack[n_stack_idx];
728 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
729 continue;
731 attribs[n++] = kCGLPFADepthSize;
732 attribs[n++] = depth_stencil_modes[depth_mode].bits;
733 request.depth_bits = depth_stencil_modes[depth_mode].bits;
735 n_stack[++n_stack_idx] = n;
736 for (stencil_mode = 0; stencil_mode < ARRAY_SIZE(depth_stencil_modes); stencil_mode++)
738 unsigned int stereo;
740 n = n_stack[n_stack_idx];
742 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
743 continue;
744 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 &&
745 depth_stencil_modes[depth_mode].bits != 32 && 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) ARRAY_SIZE(color_modes); 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 InterlockedExchange(&context->update_swap_interval, TRUE);
1545 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1547 return TRUE;
1551 /**********************************************************************
1552 * set_pixel_format
1554 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1556 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1558 struct macdrv_win_data *data;
1559 const pixel_format *pf;
1560 HWND hwnd = WindowFromDC(hdc);
1561 BOOL ret = FALSE;
1563 TRACE("hdc %p format %d\n", hdc, fmt);
1565 if (!hwnd || hwnd == GetDesktopWindow())
1567 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1568 return FALSE;
1571 if (!(data = get_win_data(hwnd)))
1573 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1574 return FALSE;
1577 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1579 ret = (data->pixel_format == fmt);
1580 goto done;
1583 /* Check if fmt is in our list of supported formats to see if it is supported. */
1584 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1585 if (!pf)
1587 ERR("Invalid pixel format: %d\n", fmt);
1588 goto done;
1591 if (!pf->window)
1593 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1594 goto done;
1597 data->pixel_format = fmt;
1599 TRACE("pixel format:\n");
1600 TRACE(" window: %u\n", (unsigned int)pf->window);
1601 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1602 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1603 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1604 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1605 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1606 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1607 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1608 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1609 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1610 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1611 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1612 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1613 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1614 ret = TRUE;
1616 done:
1617 release_win_data(data);
1618 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
1619 return ret;
1623 /**********************************************************************
1624 * mark_contexts_for_moved_view
1626 static void mark_contexts_for_moved_view(macdrv_view view)
1628 struct wgl_context *context;
1630 EnterCriticalSection(&context_section);
1631 LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
1633 if (context->draw_view == view)
1634 InterlockedExchange(&context->view_moved, TRUE);
1636 LeaveCriticalSection(&context_section);
1640 /**********************************************************************
1641 * sync_context_rect
1643 static BOOL sync_context_rect(struct wgl_context *context)
1645 BOOL ret = FALSE;
1646 if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
1648 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1650 if (data && data->client_cocoa_view == context->draw_view)
1652 RECT rect = data->client_rect;
1653 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1654 if (!EqualRect(&context->draw_rect, &rect))
1656 context->draw_rect = rect;
1657 ret = TRUE;
1660 release_win_data(data);
1662 return ret;
1666 /**********************************************************************
1667 * make_context_current
1669 static void make_context_current(struct wgl_context *context, BOOL read)
1671 macdrv_view view;
1672 RECT view_rect;
1673 struct wgl_pbuffer *pbuffer;
1675 if (read)
1677 view = context->read_view;
1678 view_rect = context->read_rect;
1679 pbuffer = context->read_pbuffer;
1681 else
1683 sync_context_rect(context);
1685 view = context->draw_view;
1686 view_rect = context->draw_rect;
1687 pbuffer = context->draw_pbuffer;
1690 if (view || !pbuffer)
1691 macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
1692 else
1694 GLint enabled;
1696 if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
1697 CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
1698 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1699 pbuffer->level, 0);
1700 CGLSetCurrentContext(context->cglcontext);
1705 /**********************************************************************
1706 * sync_context
1708 static void sync_context(struct wgl_context *context)
1710 if (sync_context_rect(context))
1711 make_context_current(context, FALSE);
1715 /**********************************************************************
1716 * set_swap_interval
1718 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1720 CGLError err;
1722 /* In theory, for single-buffered contexts, there's no such thing as a swap
1723 so the swap interval shouldn't matter. But OS X will synchronize flushes
1724 of single-buffered contexts if the interval is set to non-zero. */
1725 if (interval && !pixel_formats[context->format - 1].double_buffer)
1726 interval = 0;
1728 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1729 if (err != kCGLNoError)
1730 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1732 return err == kCGLNoError;
1736 /**********************************************************************
1737 * sync_swap_interval
1739 static void sync_swap_interval(struct wgl_context *context)
1741 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1743 int interval;
1745 if (!allow_vsync)
1746 interval = 0;
1747 else if (context->draw_hwnd)
1749 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1750 if (data)
1752 interval = data->swap_interval;
1753 release_win_data(data);
1755 else /* window was destroyed? */
1756 interval = 1;
1758 else /* pbuffer */
1759 interval = 0;
1761 set_swap_interval(context, interval);
1766 /**********************************************************************
1767 * get_iokit_display_property
1769 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1771 GLint accelerated;
1772 GLint display_mask;
1773 int i;
1775 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1777 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1778 return FALSE;
1781 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1783 WARN("failed to get kCGLRPDisplayMask\n");
1784 return FALSE;
1787 for (i = 0; i < sizeof(GLint) * 8; i++)
1789 GLint this_display_mask = (GLint)(1U << i);
1790 if (this_display_mask & display_mask)
1792 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1793 io_service_t service;
1794 CFDataRef data;
1795 uint32_t prop_value;
1797 if (!display_id)
1798 continue;
1799 service = CGDisplayIOServicePort(display_id);
1800 if (!service)
1802 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1803 continue;
1806 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1807 kIORegistryIterateRecursively | kIORegistryIterateParents);
1808 if (!data)
1810 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1811 continue;
1813 if (CFGetTypeID(data) != CFDataGetTypeID())
1815 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1816 CFRelease(data);
1817 continue;
1819 if (CFDataGetLength(data) != sizeof(prop_value))
1821 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1822 (unsigned long long)CFDataGetLength(data));
1823 CFRelease(data);
1824 continue;
1827 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1828 CFRelease(data);
1829 *value = prop_value;
1830 return TRUE;
1834 return FALSE;
1838 /**********************************************************************
1839 * create_pixel_format_for_renderer
1841 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1842 * responsible for releasing the pixel format object.
1844 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1846 GLint renderer_id;
1847 CGLPixelFormatAttribute attrs[] = {
1848 kCGLPFARendererID, 0,
1849 kCGLPFASingleRenderer,
1850 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1853 CGError err;
1854 CGLPixelFormatObj pixel_format;
1855 GLint virtual_screens;
1857 if (core)
1859 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1860 attrs[3] = kCGLPFAOpenGLProfile;
1861 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1862 #else
1863 return NULL;
1864 #endif
1867 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1868 return NULL;
1870 attrs[1] = renderer_id;
1871 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1872 if (err != kCGLNoError)
1873 pixel_format = NULL;
1874 return pixel_format;
1878 /**********************************************************************
1879 * map_renderer_index
1881 * We can't create pixel formats for all renderers listed. For example,
1882 * in a dual-GPU system, the integrated GPU is typically unavailable
1883 * when the discrete GPU is active.
1885 * This function conceptually creates a list of "good" renderers from the
1886 * list of all renderers. It treats the input "renderer" parameter as an
1887 * index into that list of good renderers and returns the corresponding
1888 * index into the list of all renderers.
1890 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1892 GLint good_count, i;
1894 good_count = 0;
1895 for (i = 0; i < renderer_count; i++)
1897 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1898 if (pix)
1900 CGLReleasePixelFormat(pix);
1901 good_count++;
1902 if (good_count > renderer)
1903 break;
1905 else
1906 TRACE("skipping bad renderer %d\n", i);
1909 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1910 return i;
1914 /**********************************************************************
1915 * get_gl_string
1917 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1919 const char* ret = NULL;
1920 CGLContextObj context, old_context;
1921 CGLError err;
1923 err = CGLCreateContext(pixel_format, NULL, &context);
1924 if (err == kCGLNoError && context)
1926 old_context = CGLGetCurrentContext();
1927 err = CGLSetCurrentContext(context);
1928 if (err == kCGLNoError)
1930 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1931 CGLSetCurrentContext(old_context);
1933 else
1934 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1935 CGLReleaseContext(context);
1937 else
1938 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1940 return ret;
1944 /**********************************************************************
1945 * get_fallback_renderer_version
1947 static void get_fallback_renderer_version(GLuint *value)
1949 BOOL got_it = FALSE;
1950 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1951 kCFURLPOSIXPathStyle, TRUE);
1952 if (url)
1954 CFBundleRef bundle = CFBundleCreate(NULL, url);
1955 CFRelease(url);
1956 if (bundle)
1958 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1959 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1961 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1962 char* buf = HeapAlloc(GetProcessHeap(), 0, len);
1963 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1965 unsigned int major, minor, bugfix;
1966 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1967 if (count >= 2)
1969 value[0] = major;
1970 value[1] = minor;
1971 if (count == 3)
1972 value[2] = bugfix;
1973 else
1974 value[2] = 0;
1975 got_it = TRUE;
1978 HeapFree(GetProcessHeap(), 0, buf);
1980 CFRelease(bundle);
1984 if (!got_it)
1986 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1987 earliest version that the Mac driver supports. */
1988 value[0] = 1;
1989 value[1] = 6;
1990 value[2] = 14;
1995 /**********************************************************************
1996 * parse_renderer_version
1998 * Get the renderer version from the OpenGL version string. Assumes
1999 * the string is of the form
2000 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2001 * where major, minor, and bugfix are what we're interested in. This
2002 * form for the vendor specific information is not generally applicable,
2003 * but seems reliable on OS X.
2005 static BOOL parse_renderer_version(const char* version, GLuint *value)
2007 const char* p = strchr(version, ' ');
2008 int count;
2009 unsigned int major, minor, bugfix;
2011 if (p) p = strchr(p + 1, '-');
2012 if (!p) return FALSE;
2014 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
2015 if (count < 2)
2016 return FALSE;
2018 value[0] = major;
2019 value[1] = minor;
2020 if (count == 3)
2021 value[2] = bugfix;
2022 else
2023 value[2] = 0;
2025 return TRUE;
2029 /**********************************************************************
2030 * query_renderer_integer
2032 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2034 BOOL ret = FALSE;
2035 CGLError err;
2037 if (TRACE_ON(wgl))
2039 GLint renderer_id;
2040 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2041 renderer_id = 0;
2042 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2045 switch (attribute)
2047 case WGL_RENDERER_ACCELERATED_WINE:
2048 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2049 break;
2050 *value = !!*value;
2051 ret = TRUE;
2052 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2053 break;
2055 case WGL_RENDERER_DEVICE_ID_WINE:
2056 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2057 if (!ret)
2059 *value = 0xffffffff;
2060 ret = TRUE;
2062 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2063 break;
2065 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2066 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2068 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2069 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2071 if (pixel_format)
2073 const char* version = get_gl_string(pixel_format, GL_VERSION);
2075 CGLReleasePixelFormat(pixel_format);
2076 if (version)
2078 unsigned int major, minor;
2080 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2082 value[0] = major;
2083 value[1] = minor;
2084 ret = TRUE;
2089 if (!ret)
2091 value[0] = value[1] = 0;
2092 ret = TRUE;
2094 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2095 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2096 break;
2099 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2101 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2103 if (pixel_format)
2105 CGLReleasePixelFormat(pixel_format);
2106 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2107 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2109 else
2111 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2112 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2114 ret = TRUE;
2115 break;
2118 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2119 /* FIXME: no API to query this */
2120 *value = 0;
2121 ret = TRUE;
2122 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2123 break;
2125 case WGL_RENDERER_VENDOR_ID_WINE:
2126 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2127 if (!ret)
2129 *value = 0xffffffff;
2130 ret = TRUE;
2132 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2133 break;
2135 case WGL_RENDERER_VERSION_WINE:
2137 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2139 if (!pixel_format)
2140 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2141 if (pixel_format)
2143 const char* version = get_gl_string(pixel_format, GL_VERSION);
2145 CGLReleasePixelFormat(pixel_format);
2146 if (version)
2147 ret = parse_renderer_version(version, value);
2150 if (!ret)
2152 get_fallback_renderer_version(value);
2153 ret = TRUE;
2155 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2156 break;
2159 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2160 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2161 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2162 if (err != kCGLNoError && err != kCGLBadProperty)
2163 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2164 if (err != kCGLNoError)
2165 #endif
2167 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2168 *value /= 1024 * 1024;
2169 else
2170 *value = 0;
2172 ret = TRUE;
2173 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2174 break;
2176 default:
2177 FIXME("unrecognized attribute 0x%04x\n", attribute);
2178 break;
2181 return ret;
2185 /**********************************************************************
2186 * macdrv_glCopyColorTable
2188 * Hook into glCopyColorTable as part of the implementation of
2189 * wglMakeContextCurrentARB. If the context has a separate readable,
2190 * temporarily make that current, do glCopyColorTable, and then set it
2191 * back to the drawable. This is modeled after what Mesa GLX's Apple
2192 * implementation does.
2194 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2195 GLsizei width)
2197 struct wgl_context *context = NtCurrentTeb()->glContext;
2199 if (context->read_view || context->read_pbuffer)
2200 make_context_current(context, TRUE);
2202 pglCopyColorTable(target, internalformat, x, y, width);
2204 if (context->read_view || context->read_pbuffer)
2205 make_context_current(context, FALSE);
2209 /**********************************************************************
2210 * macdrv_glCopyPixels
2212 * Hook into glCopyPixels as part of the implementation of
2213 * wglMakeContextCurrentARB. If the context has a separate readable,
2214 * temporarily make that current, do glCopyPixels, and then set it back
2215 * to the drawable. This is modeled after what Mesa GLX's Apple
2216 * implementation does.
2218 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2220 struct wgl_context *context = NtCurrentTeb()->glContext;
2222 if (context->read_view || context->read_pbuffer)
2223 make_context_current(context, TRUE);
2225 pglCopyPixels(x, y, width, height, type);
2227 if (context->read_view || context->read_pbuffer)
2228 make_context_current(context, FALSE);
2232 /**********************************************************************
2233 * macdrv_glFinish
2235 static void macdrv_glFinish(void)
2237 struct wgl_context *context = NtCurrentTeb()->glContext;
2239 sync_swap_interval(context);
2240 sync_context(context);
2241 pglFinish();
2245 /**********************************************************************
2246 * macdrv_glFlush
2248 static void macdrv_glFlush(void)
2250 struct wgl_context *context = NtCurrentTeb()->glContext;
2252 sync_swap_interval(context);
2253 sync_context(context);
2255 if (skip_single_buffer_flushes)
2257 const pixel_format *pf = &pixel_formats[context->format - 1];
2258 DWORD now = GetTickCount();
2260 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2261 context->last_flush_time, now);
2262 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2264 TRACE("calling glFlushRenderAPPLE()\n");
2265 pglFlushRenderAPPLE();
2266 return;
2268 else
2270 TRACE("calling glFlush()\n");
2271 context->last_flush_time = now;
2275 pglFlush();
2279 /**********************************************************************
2280 * macdrv_glGetString
2282 * Hook into glGetString in order to return some legacy WGL extensions
2283 * that couldn't be advertised via the standard
2284 * WGL_ARB_extensions_string mechanism. Some programs, especially
2285 * older ones, expect to find certain older extensions, such as
2286 * WGL_EXT_extensions_string itself, in the standard GL extensions
2287 * string, and won't query any other WGL extensions unless they find
2288 * that particular extension there.
2290 static const GLubyte *macdrv_glGetString(GLenum name)
2292 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2293 return (const GLubyte *)gl_info.glExtensions;
2294 else
2295 return pglGetString(name);
2299 /**********************************************************************
2300 * macdrv_glReadPixels
2302 * Hook into glReadPixels as part of the implementation of
2303 * wglMakeContextCurrentARB. If the context has a separate readable,
2304 * temporarily make that current, do glReadPixels, and then set it back
2305 * to the drawable. This is modeled after what Mesa GLX's Apple
2306 * implementation does.
2308 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2309 GLenum format, GLenum type, void *pixels)
2311 struct wgl_context *context = NtCurrentTeb()->glContext;
2313 if (context->read_view || context->read_pbuffer)
2314 make_context_current(context, TRUE);
2316 pglReadPixels(x, y, width, height, format, type, pixels);
2318 if (context->read_view || context->read_pbuffer)
2319 make_context_current(context, FALSE);
2323 /**********************************************************************
2324 * macdrv_glViewport
2326 * Hook into glViewport as an opportunity to update the OpenGL context
2327 * if necessary. This is modeled after what Mesa GLX's Apple
2328 * implementation does.
2330 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2332 struct wgl_context *context = NtCurrentTeb()->glContext;
2334 sync_context(context);
2335 macdrv_update_opengl_context(context->context);
2336 pglViewport(x, y, width, height);
2340 /***********************************************************************
2341 * macdrv_wglBindTexImageARB
2343 * WGL_ARB_render_texture: wglBindTexImageARB
2345 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2347 struct wgl_context *context = NtCurrentTeb()->glContext;
2348 GLenum source;
2349 CGLError err;
2351 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2353 if (pbuffer->no_texture)
2355 SetLastError(ERROR_INVALID_OPERATION);
2356 return GL_FALSE;
2359 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2360 opengl_funcs.gl.p_glFlush();
2362 switch (iBuffer)
2364 case WGL_FRONT_LEFT_ARB:
2365 if (pixel_formats[pbuffer->format - 1].stereo)
2366 source = GL_FRONT_LEFT;
2367 else
2368 source = GL_FRONT;
2369 break;
2370 case WGL_FRONT_RIGHT_ARB:
2371 source = GL_FRONT_RIGHT;
2372 break;
2373 case WGL_BACK_LEFT_ARB:
2374 if (pixel_formats[pbuffer->format - 1].stereo)
2375 source = GL_BACK_LEFT;
2376 else
2377 source = GL_BACK;
2378 break;
2379 case WGL_BACK_RIGHT_ARB:
2380 source = GL_BACK_RIGHT;
2381 break;
2382 case WGL_AUX0_ARB: source = GL_AUX0; break;
2383 case WGL_AUX1_ARB: source = GL_AUX1; break;
2384 case WGL_AUX2_ARB: source = GL_AUX2; break;
2385 case WGL_AUX3_ARB: source = GL_AUX3; break;
2387 case WGL_AUX4_ARB:
2388 case WGL_AUX5_ARB:
2389 case WGL_AUX6_ARB:
2390 case WGL_AUX7_ARB:
2391 case WGL_AUX8_ARB:
2392 case WGL_AUX9_ARB:
2393 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2394 SetLastError(ERROR_INVALID_DATA);
2395 return GL_FALSE;
2397 default:
2398 WARN("unknown source buffer 0x%x\n", iBuffer);
2399 SetLastError(ERROR_INVALID_DATA);
2400 return GL_FALSE;
2403 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2404 if (err != kCGLNoError)
2406 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2407 SetLastError(ERROR_INVALID_OPERATION);
2408 return GL_FALSE;
2411 return GL_TRUE;
2415 /***********************************************************************
2416 * macdrv_wglChoosePixelFormatARB
2418 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2420 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2421 const FLOAT *pfAttribFList, UINT nMaxFormats,
2422 int *piFormats, UINT *nNumFormats)
2424 pixel_format pf, valid;
2425 const int *iptr;
2426 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2427 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2428 int float_color;
2429 BOOL srgb;
2430 int i, found = 0;
2432 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2433 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2434 if (pfAttribFList)
2435 FIXME("unused pfAttribFList\n");
2437 memset(&pf, 0, sizeof(pf));
2438 memset(&valid, 0, sizeof(valid));
2439 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2440 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2441 float_color = -1;
2442 srgb = FALSE;
2444 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2446 int attr = iptr[0];
2447 int value = iptr[1];
2449 TRACE("%s\n", debugstr_attrib(attr, value));
2451 switch (attr)
2453 case WGL_DRAW_TO_WINDOW_ARB:
2454 if (valid.window && (!pf.window != !value)) goto cant_match;
2455 pf.window = (value != 0);
2456 valid.window = 1;
2457 break;
2459 case WGL_DRAW_TO_BITMAP_ARB:
2460 goto cant_match;
2462 case WGL_ACCELERATION_ARB:
2463 if (value == WGL_FULL_ACCELERATION_ARB)
2464 value = 1;
2465 else if (value == WGL_NO_ACCELERATION_ARB)
2466 value = 0;
2467 else
2468 goto cant_match;
2469 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2470 pf.accelerated = value;
2471 valid.accelerated = 1;
2472 break;
2474 case WGL_NEED_PALETTE_ARB:
2475 case WGL_NEED_SYSTEM_PALETTE_ARB:
2476 case WGL_SWAP_LAYER_BUFFERS_ARB:
2477 if (value) goto cant_match;
2478 break;
2480 case WGL_SWAP_METHOD_ARB:
2481 if (value == WGL_SWAP_COPY_ARB)
2482 value = 1;
2483 else if (value == WGL_SWAP_UNDEFINED_ARB)
2484 value = 0;
2485 else
2486 goto cant_match;
2487 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2488 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2489 pf.backing_store = value;
2490 valid.backing_store = 1;
2491 break;
2493 case WGL_NUMBER_OVERLAYS_ARB:
2494 case WGL_NUMBER_UNDERLAYS_ARB:
2495 if (value) goto cant_match;
2496 break;
2498 case WGL_SHARE_DEPTH_ARB:
2499 case WGL_SHARE_STENCIL_ARB:
2500 case WGL_SHARE_ACCUM_ARB:
2501 /* no effect */
2502 break;
2504 case WGL_SUPPORT_GDI_ARB:
2505 if (value) goto cant_match;
2506 break;
2508 case WGL_SUPPORT_OPENGL_ARB:
2509 if (!value) goto cant_match;
2510 break;
2512 case WGL_DOUBLE_BUFFER_ARB:
2513 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2514 pf.double_buffer = (value != 0);
2515 valid.double_buffer = 1;
2516 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2517 break;
2519 case WGL_STEREO_ARB:
2520 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2521 pf.stereo = (value != 0);
2522 valid.stereo = 1;
2523 break;
2525 case WGL_PIXEL_TYPE_ARB:
2526 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2527 value = 1;
2528 else if (value == WGL_TYPE_RGBA_ARB)
2529 value = 0;
2530 else
2532 /* Mac contexts don't support rendering to unsigned floating
2533 point formats, even if GL_EXT_packed_float is supported.
2534 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2535 goto cant_match;
2537 if (float_color != -1 && float_color != value) goto cant_match;
2538 if (srgb && value) goto cant_match;
2539 float_color = value;
2540 break;
2542 case WGL_COLOR_BITS_ARB:
2543 if (color_bits < value) color_bits = value;
2544 break;
2546 case WGL_RED_BITS_ARB:
2547 if (srgb && value > 8) goto cant_match;
2548 if (red_bits < value) red_bits = value;
2549 break;
2551 case WGL_GREEN_BITS_ARB:
2552 if (srgb && value > 8) goto cant_match;
2553 if (green_bits < value) green_bits = value;
2554 break;
2556 case WGL_BLUE_BITS_ARB:
2557 if (srgb && value > 8) goto cant_match;
2558 if (blue_bits < value) blue_bits = value;
2559 break;
2561 case WGL_ALPHA_BITS_ARB:
2562 if (alpha_bits < value) alpha_bits = value;
2563 break;
2565 case WGL_ACCUM_BITS_ARB:
2566 if (accum_bits < value) accum_bits = value;
2567 break;
2569 case WGL_ACCUM_RED_BITS_ARB:
2570 if (accum_red_bits < value) accum_red_bits = value;
2571 break;
2573 case WGL_ACCUM_GREEN_BITS_ARB:
2574 if (accum_green_bits < value) accum_green_bits = value;
2575 break;
2577 case WGL_ACCUM_BLUE_BITS_ARB:
2578 if (accum_blue_bits < value) accum_blue_bits = value;
2579 break;
2581 case WGL_ACCUM_ALPHA_BITS_ARB:
2582 if (accum_alpha_bits < value) accum_alpha_bits = value;
2583 break;
2585 case WGL_DEPTH_BITS_ARB:
2586 if (value > 255) goto cant_match;
2587 if (pf.depth_bits < value) pf.depth_bits = value;
2588 break;
2590 case WGL_STENCIL_BITS_ARB:
2591 if (value > 255) goto cant_match;
2592 if (pf.stencil_bits < value) pf.stencil_bits = value;
2593 break;
2595 case WGL_AUX_BUFFERS_ARB:
2596 if (value > 7) goto cant_match;
2597 if (pf.aux_buffers < value) pf.aux_buffers = value;
2598 break;
2600 case WGL_SAMPLE_BUFFERS_ARB:
2601 if (value > 1) goto cant_match;
2602 if (pf.sample_buffers < value) pf.sample_buffers = value;
2603 break;
2605 case WGL_SAMPLES_ARB:
2606 if (value > 31) goto cant_match;
2607 if (pf.samples < value) pf.samples = value;
2608 break;
2610 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2611 /* sRGB is only supported for 8-bit integer color components */
2612 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2613 goto cant_match;
2614 srgb = TRUE;
2615 break;
2617 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2618 case WGL_RED_SHIFT_ARB:
2619 case WGL_GREEN_SHIFT_ARB:
2620 case WGL_BLUE_SHIFT_ARB:
2621 case WGL_ALPHA_SHIFT_ARB:
2622 case WGL_TRANSPARENT_ARB:
2623 case WGL_TRANSPARENT_RED_VALUE_ARB:
2624 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2625 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2626 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2627 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2628 /* ignored */
2629 break;
2631 case WGL_DRAW_TO_PBUFFER_ARB:
2632 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2633 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2634 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2635 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2636 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2637 pf.pbuffer = (value != 0);
2638 valid.pbuffer = 1;
2639 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2640 !alpha_bits)
2641 alpha_bits = 1;
2642 break;
2644 default:
2645 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2646 return GL_FALSE;
2650 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",
2651 valid.window ? (pf.window ? "1" : "0") : "?",
2652 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2653 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2654 color_bits,
2655 float_color == -1 ? "?" : float_color ? "f" : "",
2656 red_bits,
2657 green_bits,
2658 blue_bits,
2659 alpha_bits,
2660 (int)srgb,
2661 accum_bits,
2662 accum_red_bits,
2663 accum_green_bits,
2664 accum_blue_bits,
2665 accum_alpha_bits,
2666 pf.depth_bits,
2667 pf.stencil_bits,
2668 pf.aux_buffers,
2669 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2670 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2671 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2672 pf.sample_buffers,
2673 pf.samples);
2675 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2677 const struct color_mode *mode;
2679 if (valid.window && pixel_formats[i].window != pf.window) continue;
2680 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2681 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2682 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2683 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2684 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2686 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2687 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2688 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2689 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2690 if (pixel_formats[i].samples < pf.samples) continue;
2692 mode = &color_modes[pixel_formats[i].color_mode];
2693 /* If the mode doesn't have alpha, check requested color bits against
2694 bits per pixel instead of the mode's color bits. On Windows, color
2695 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2696 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2697 expects that to match such a pixel format, we need to accommodate that. */
2698 if (mode->alpha_bits)
2700 if (mode->color_bits < color_bits)
2701 continue;
2703 else
2705 if (mode->bits_per_pixel < color_bits)
2706 continue;
2708 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2709 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2710 continue;
2711 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2712 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2713 continue;
2715 if (pixel_formats[i].accum_mode)
2717 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2718 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2719 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2720 mode->alpha_bits < accum_alpha_bits)
2721 continue;
2723 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2724 continue;
2726 piFormats[found++] = i + 1;
2727 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2730 cant_match:
2731 *nNumFormats = found;
2733 return TRUE;
2737 /***********************************************************************
2738 * macdrv_wglCreateContextAttribsARB
2740 * WGL_ARB_create_context: wglCreateContextAttribsARB
2742 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2743 struct wgl_context *share_context,
2744 const int *attrib_list)
2746 int format;
2747 struct wgl_context *context;
2748 const int *iptr;
2749 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2750 BOOL core = FALSE;
2751 GLint renderer_id = 0;
2753 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2755 format = get_dc_pixel_format(hdc);
2757 if (!is_valid_pixel_format(format))
2759 ERR("Invalid pixel format %d, expect problems!\n", format);
2760 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2761 return NULL;
2764 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2766 int attr = iptr[0];
2767 int value = iptr[1];
2769 TRACE("%s\n", debugstr_attrib(attr, value));
2771 switch (attr)
2773 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2774 major = value;
2775 break;
2777 case WGL_CONTEXT_MINOR_VERSION_ARB:
2778 minor = value;
2779 break;
2781 case WGL_CONTEXT_LAYER_PLANE_ARB:
2782 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2783 break;
2785 case WGL_CONTEXT_FLAGS_ARB:
2786 flags = value;
2787 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2788 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2789 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2790 break;
2792 case WGL_CONTEXT_PROFILE_MASK_ARB:
2793 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2794 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2796 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2797 SetLastError(ERROR_INVALID_PROFILE_ARB);
2798 return NULL;
2800 profile = value;
2801 break;
2803 case WGL_RENDERER_ID_WINE:
2805 CGLError err;
2806 CGLRendererInfoObj renderer_info;
2807 GLint renderer_count, temp;
2809 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2810 if (err != kCGLNoError)
2812 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2813 SetLastError(ERROR_GEN_FAILURE);
2814 return NULL;
2817 value = map_renderer_index(renderer_info, renderer_count, value);
2819 if (value >= renderer_count)
2821 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2822 CGLDestroyRendererInfo(renderer_info);
2823 SetLastError(ERROR_INVALID_PARAMETER);
2824 return NULL;
2827 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2829 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2830 CGLDestroyRendererInfo(renderer_info);
2831 SetLastError(ERROR_GEN_FAILURE);
2832 return NULL;
2835 CGLDestroyRendererInfo(renderer_info);
2837 if (renderer_id && temp != renderer_id)
2839 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2840 SetLastError(ERROR_INVALID_PARAMETER);
2841 return NULL;
2843 renderer_id = temp;
2844 break;
2847 default:
2848 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2849 SetLastError(ERROR_INVALID_PARAMETER);
2850 return NULL;
2854 if ((major == 3 && (minor == 2 || minor == 3)) ||
2855 (major == 4 && (minor == 0 || minor == 1)))
2857 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2859 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2860 SetLastError(ERROR_INVALID_VERSION_ARB);
2861 return NULL;
2863 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2865 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2866 SetLastError(ERROR_INVALID_PROFILE_ARB);
2867 return NULL;
2869 if (major > gl_info.max_major ||
2870 (major == gl_info.max_major && minor > gl_info.max_minor))
2872 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2873 major, minor);
2874 SetLastError(ERROR_INVALID_PROFILE_ARB);
2875 return NULL;
2877 core = TRUE;
2879 else if (major >= 3)
2881 WARN("Profile version %u.%u not supported\n", major, minor);
2882 SetLastError(ERROR_INVALID_VERSION_ARB);
2883 return NULL;
2885 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2886 (major == 2 && (minor < 0 || minor > 1)))
2888 WARN("Invalid GL version requested\n");
2889 SetLastError(ERROR_INVALID_VERSION_ARB);
2890 return NULL;
2892 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2894 WARN("Forward compatible context requested for GL version < 3\n");
2895 SetLastError(ERROR_INVALID_VERSION_ARB);
2896 return NULL;
2899 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2901 context->format = format;
2902 context->renderer_id = renderer_id;
2903 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2905 HeapFree(GetProcessHeap(), 0, context);
2906 return NULL;
2909 EnterCriticalSection(&context_section);
2910 list_add_tail(&context_list, &context->entry);
2911 LeaveCriticalSection(&context_section);
2913 return context;
2917 /**********************************************************************
2918 * macdrv_wglCreatePbufferARB
2920 * WGL_ARB_pbuffer: wglCreatePbufferARB
2922 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2923 const int *piAttribList)
2925 struct wgl_pbuffer* pbuffer;
2926 GLenum target = 0;
2927 GLenum internalFormat = 0;
2928 CGLError err;
2930 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2931 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2933 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2935 WARN("invalid pixel format %d\n", iPixelFormat);
2936 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2937 return NULL;
2940 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2941 pbuffer->format = iPixelFormat;
2943 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2945 int attr = piAttribList[0];
2946 int value = piAttribList[1];
2948 switch (attr)
2950 case WGL_PBUFFER_LARGEST_ARB:
2951 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2952 break;
2954 case WGL_TEXTURE_FORMAT_ARB:
2955 switch (value)
2957 case WGL_TEXTURE_RGBA_ARB:
2958 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2959 internalFormat = GL_RGBA;
2960 break;
2961 case WGL_TEXTURE_RGB_ARB:
2962 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2963 internalFormat = GL_RGB;
2964 break;
2965 case WGL_NO_TEXTURE_ARB:
2966 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2967 internalFormat = 0;
2968 break;
2969 default:
2970 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2971 SetLastError(ERROR_INVALID_DATA);
2972 goto done;
2974 break;
2976 case WGL_TEXTURE_TARGET_ARB:
2977 pbuffer->face = 0;
2978 switch (value)
2980 case WGL_NO_TEXTURE_ARB:
2981 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2982 target = 0;
2983 break;
2984 case WGL_TEXTURE_CUBE_MAP_ARB:
2985 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2986 target = GL_TEXTURE_CUBE_MAP;
2987 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2988 break;
2989 case WGL_TEXTURE_1D_ARB:
2990 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2991 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2992 goto done;
2993 case WGL_TEXTURE_2D_ARB:
2994 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2995 target = GL_TEXTURE_2D;
2996 break;
2997 case WGL_TEXTURE_RECTANGLE_NV:
2998 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2999 target = GL_TEXTURE_RECTANGLE;
3000 break;
3001 default:
3002 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
3003 SetLastError(ERROR_INVALID_DATA);
3004 goto done;
3006 break;
3008 case WGL_MIPMAP_TEXTURE_ARB:
3009 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
3010 pbuffer->max_level = 0;
3011 if (value)
3013 int size = min(iWidth, iHeight) / 2;
3014 while (size)
3016 pbuffer->max_level++;
3017 size /= 2;
3020 break;
3022 default:
3023 WARN("unknown attribute 0x%x\n", attr);
3024 SetLastError(ERROR_INVALID_DATA);
3025 goto done;
3029 if (!target || !internalFormat)
3031 pbuffer->no_texture = TRUE;
3032 /* no actual way to turn off ability to texture; use most permissive target */
3033 target = GL_TEXTURE_RECTANGLE;
3034 internalFormat = GL_RGB;
3037 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3038 if (err != kCGLNoError)
3040 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3041 pbuffer->pbuffer = NULL;
3042 if (err == kCGLBadAlloc)
3043 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3044 else
3045 SetLastError(ERROR_INVALID_DATA);
3048 done:
3049 if (!pbuffer->pbuffer)
3051 HeapFree(GetProcessHeap(), 0, pbuffer);
3052 return NULL;
3055 TRACE(" -> %p\n", pbuffer);
3056 return pbuffer;
3060 /**********************************************************************
3061 * macdrv_wglDestroyPbufferARB
3063 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3065 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3067 TRACE("pbuffer %p\n", pbuffer);
3068 if (pbuffer && pbuffer->pbuffer)
3069 CGLReleasePBuffer(pbuffer->pbuffer);
3070 HeapFree(GetProcessHeap(), 0, pbuffer);
3071 return GL_TRUE;
3075 /**********************************************************************
3076 * macdrv_wglGetExtensionsStringARB
3078 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3080 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3082 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3083 this can be specific to the CGL renderer like we're supposed to do. */
3084 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3085 return gl_info.wglExtensions;
3089 /**********************************************************************
3090 * macdrv_wglGetExtensionsStringEXT
3092 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3094 static const char *macdrv_wglGetExtensionsStringEXT(void)
3096 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3097 return gl_info.wglExtensions;
3101 /**********************************************************************
3102 * macdrv_wglGetPbufferDCARB
3104 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3106 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3108 HDC hdc;
3109 struct wgl_pbuffer *prev;
3111 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3112 if (!hdc) return 0;
3114 EnterCriticalSection(&dc_pbuffers_section);
3115 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3116 if (prev)
3118 CGLReleasePBuffer(prev->pbuffer);
3119 HeapFree(GetProcessHeap(), 0, prev);
3121 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3122 LeaveCriticalSection(&dc_pbuffers_section);
3124 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3125 return hdc;
3129 /**********************************************************************
3130 * macdrv_wglGetPixelFormatAttribivARB
3132 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3134 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3135 UINT nAttributes, const int *piAttributes, int *piValues)
3137 const pixel_format *pf;
3138 UINT i;
3140 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3141 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3143 if (!nAttributes) return GL_TRUE;
3145 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3147 piValues[0] = nb_formats;
3148 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3149 return GL_TRUE;
3152 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3153 if (!pf)
3155 WARN("invalid pixel format %d\n", iPixelFormat);
3156 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3157 return GL_FALSE;
3160 for (i = 0; i < nAttributes; ++i)
3162 switch (piAttributes[i])
3164 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3165 piValues[i] = nb_formats;
3166 break;
3168 case WGL_DRAW_TO_WINDOW_ARB:
3169 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3170 break;
3172 case WGL_DRAW_TO_BITMAP_ARB:
3173 piValues[i] = GL_FALSE;
3174 break;
3176 case WGL_ACCELERATION_ARB:
3177 if (iLayerPlane) goto invalid_layer;
3178 if (pf->accelerated)
3179 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3180 else
3181 piValues[i] = WGL_NO_ACCELERATION_ARB;
3182 break;
3184 case WGL_NEED_PALETTE_ARB:
3185 case WGL_NEED_SYSTEM_PALETTE_ARB:
3186 case WGL_SWAP_LAYER_BUFFERS_ARB:
3187 piValues[i] = GL_FALSE;
3188 break;
3190 case WGL_SWAP_METHOD_ARB:
3191 if (pf->double_buffer && pf->backing_store)
3192 piValues[i] = WGL_SWAP_COPY_ARB;
3193 else
3194 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3195 break;
3197 case WGL_NUMBER_OVERLAYS_ARB:
3198 case WGL_NUMBER_UNDERLAYS_ARB:
3199 piValues[i] = 0;
3200 break;
3202 case WGL_TRANSPARENT_ARB:
3203 if (iLayerPlane) goto invalid_layer;
3204 piValues[i] = GL_FALSE;
3205 break;
3207 case WGL_TRANSPARENT_RED_VALUE_ARB:
3208 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3209 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3210 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3211 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3212 if (iLayerPlane) goto invalid_layer;
3213 piValues[i] = 0;
3214 break;
3216 case WGL_SHARE_DEPTH_ARB:
3217 case WGL_SHARE_STENCIL_ARB:
3218 case WGL_SHARE_ACCUM_ARB:
3219 if (iLayerPlane) goto invalid_layer;
3220 piValues[i] = GL_TRUE;
3221 break;
3223 case WGL_SUPPORT_GDI_ARB:
3224 if (iLayerPlane) goto invalid_layer;
3225 piValues[i] = GL_FALSE;
3226 break;
3228 case WGL_SUPPORT_OPENGL_ARB:
3229 if (iLayerPlane) goto invalid_layer;
3230 piValues[i] = GL_TRUE;
3231 break;
3233 case WGL_DOUBLE_BUFFER_ARB:
3234 if (iLayerPlane) goto invalid_layer;
3235 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3236 break;
3238 case WGL_STEREO_ARB:
3239 if (iLayerPlane) goto invalid_layer;
3240 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3241 break;
3243 case WGL_PIXEL_TYPE_ARB:
3244 if (iLayerPlane) goto invalid_layer;
3245 if (color_modes[pf->color_mode].is_float)
3246 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3247 else
3248 piValues[i] = WGL_TYPE_RGBA_ARB;
3249 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3250 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3251 However, Mac contexts don't support rendering to unsigned floating-point
3252 formats, even when GL_EXT_packed_float is supported. */
3253 break;
3255 case WGL_COLOR_BITS_ARB:
3256 if (iLayerPlane) goto invalid_layer;
3257 /* If the mode doesn't have alpha, return bits per pixel instead
3258 of color bits. On Windows, color bits sometimes exceeds r+g+b
3259 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3260 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3261 pixel format, we need to accommodate that. */
3262 if (color_modes[pf->color_mode].alpha_bits)
3263 piValues[i] = color_modes[pf->color_mode].color_bits;
3264 else
3265 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3266 break;
3268 case WGL_RED_BITS_ARB:
3269 if (iLayerPlane) goto invalid_layer;
3270 piValues[i] = color_modes[pf->color_mode].red_bits;
3271 break;
3273 case WGL_RED_SHIFT_ARB:
3274 if (iLayerPlane) goto invalid_layer;
3275 piValues[i] = color_modes[pf->color_mode].red_shift;
3276 break;
3278 case WGL_GREEN_BITS_ARB:
3279 if (iLayerPlane) goto invalid_layer;
3280 piValues[i] = color_modes[pf->color_mode].green_bits;
3281 break;
3283 case WGL_GREEN_SHIFT_ARB:
3284 if (iLayerPlane) goto invalid_layer;
3285 piValues[i] = color_modes[pf->color_mode].green_shift;
3286 break;
3288 case WGL_BLUE_BITS_ARB:
3289 if (iLayerPlane) goto invalid_layer;
3290 piValues[i] = color_modes[pf->color_mode].blue_bits;
3291 break;
3293 case WGL_BLUE_SHIFT_ARB:
3294 if (iLayerPlane) goto invalid_layer;
3295 piValues[i] = color_modes[pf->color_mode].blue_shift;
3296 break;
3298 case WGL_ALPHA_BITS_ARB:
3299 if (iLayerPlane) goto invalid_layer;
3300 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3301 break;
3303 case WGL_ALPHA_SHIFT_ARB:
3304 if (iLayerPlane) goto invalid_layer;
3305 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3306 break;
3308 case WGL_ACCUM_BITS_ARB:
3309 if (iLayerPlane) goto invalid_layer;
3310 if (pf->accum_mode)
3311 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3312 else
3313 piValues[i] = 0;
3314 break;
3316 case WGL_ACCUM_RED_BITS_ARB:
3317 if (iLayerPlane) goto invalid_layer;
3318 if (pf->accum_mode)
3319 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3320 else
3321 piValues[i] = 0;
3322 break;
3324 case WGL_ACCUM_GREEN_BITS_ARB:
3325 if (iLayerPlane) goto invalid_layer;
3326 if (pf->accum_mode)
3327 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3328 else
3329 piValues[i] = 0;
3330 break;
3332 case WGL_ACCUM_BLUE_BITS_ARB:
3333 if (iLayerPlane) goto invalid_layer;
3334 if (pf->accum_mode)
3335 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3336 else
3337 piValues[i] = 0;
3338 break;
3340 case WGL_ACCUM_ALPHA_BITS_ARB:
3341 if (iLayerPlane) goto invalid_layer;
3342 if (pf->accum_mode)
3343 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3344 else
3345 piValues[i] = 0;
3346 break;
3348 case WGL_DEPTH_BITS_ARB:
3349 if (iLayerPlane) goto invalid_layer;
3350 piValues[i] = pf->depth_bits;
3351 break;
3353 case WGL_STENCIL_BITS_ARB:
3354 if (iLayerPlane) goto invalid_layer;
3355 piValues[i] = pf->stencil_bits;
3356 break;
3358 case WGL_AUX_BUFFERS_ARB:
3359 if (iLayerPlane) goto invalid_layer;
3360 piValues[i] = pf->aux_buffers;
3361 break;
3363 case WGL_SAMPLE_BUFFERS_ARB:
3364 if (iLayerPlane) goto invalid_layer;
3365 piValues[i] = pf->sample_buffers;
3366 break;
3368 case WGL_SAMPLES_ARB:
3369 if (iLayerPlane) goto invalid_layer;
3370 piValues[i] = pf->samples;
3371 break;
3373 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3374 if (iLayerPlane) goto invalid_layer;
3375 /* sRGB is only supported for 8-bit integer color components */
3376 if (color_modes[pf->color_mode].red_bits == 8 &&
3377 color_modes[pf->color_mode].green_bits == 8 &&
3378 color_modes[pf->color_mode].blue_bits == 8 &&
3379 !color_modes[pf->color_mode].is_float)
3380 piValues[i] = GL_TRUE;
3381 else
3382 piValues[i] = GL_FALSE;
3383 break;
3385 case WGL_DRAW_TO_PBUFFER_ARB:
3386 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3387 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3388 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3389 break;
3391 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3392 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3393 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3394 break;
3396 case WGL_MAX_PBUFFER_WIDTH_ARB:
3397 piValues[i] = gl_info.max_viewport_dims[0];
3398 break;
3400 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3401 piValues[i] = gl_info.max_viewport_dims[1];
3402 break;
3404 case WGL_MAX_PBUFFER_PIXELS_ARB:
3405 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3406 break;
3408 default:
3409 WARN("invalid attribute %x\n", piAttributes[i]);
3410 return GL_FALSE;
3413 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3416 return GL_TRUE;
3418 invalid_layer:
3419 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3420 return GL_FALSE;
3424 /**********************************************************************
3425 * macdrv_wglGetPixelFormatAttribfvARB
3427 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3429 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3430 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3432 int *attr;
3433 int ret;
3435 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3436 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3438 /* Allocate a temporary array to store integer values */
3439 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
3440 if (!attr)
3442 ERR("couldn't allocate %d array\n", nAttributes);
3443 return GL_FALSE;
3446 /* Piggy-back on wglGetPixelFormatAttribivARB */
3447 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3448 if (ret)
3450 UINT i;
3452 /* Convert integer values to float. Should also check for attributes
3453 that can give decimal values here */
3454 for (i = 0; i < nAttributes; i++)
3455 pfValues[i] = attr[i];
3458 HeapFree(GetProcessHeap(), 0, attr);
3459 return ret;
3463 /**********************************************************************
3464 * macdrv_wglGetSwapIntervalEXT
3466 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3468 static int macdrv_wglGetSwapIntervalEXT(void)
3470 struct wgl_context *context = NtCurrentTeb()->glContext;
3471 struct macdrv_win_data *data;
3472 long value;
3473 CGLError err;
3475 TRACE("\n");
3477 if ((data = get_win_data(context->draw_hwnd)))
3479 value = data->swap_interval;
3480 release_win_data(data);
3482 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3483 set_swap_interval(context, allow_vsync ? value : 0);
3485 else
3487 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3488 if (err != kCGLNoError)
3490 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3491 err, CGLErrorString(err));
3492 value = 1;
3496 return value;
3500 /***********************************************************************
3501 * macdrv_wglMakeContextCurrentARB
3503 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3505 * This is not supported directly by OpenGL on the Mac. We emulate it
3506 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3507 * temporarily swap the drawable. This follows the technique used in
3508 * the implementation of Mesa GLX for Apple.
3510 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3512 struct macdrv_win_data *data;
3513 HWND hwnd;
3515 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3516 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3518 if (!context)
3520 macdrv_make_context_current(NULL, NULL, CGRectNull);
3521 NtCurrentTeb()->glContext = NULL;
3522 return TRUE;
3525 if ((hwnd = WindowFromDC(draw_hdc)))
3527 if (!(data = get_win_data(hwnd)))
3529 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3530 return FALSE;
3533 if (!data->pixel_format)
3535 WARN("no pixel format set\n");
3536 release_win_data(data);
3537 SetLastError(ERROR_INVALID_HANDLE);
3538 return FALSE;
3540 if (context->format != data->pixel_format)
3542 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3543 release_win_data(data);
3544 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3545 return FALSE;
3548 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd)
3549 set_swap_interval(context, allow_vsync ? data->swap_interval : 0);
3551 context->draw_hwnd = hwnd;
3552 context->draw_view = data->client_cocoa_view;
3553 context->draw_rect = data->client_rect;
3554 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3555 context->draw_pbuffer = NULL;
3556 release_win_data(data);
3558 else
3560 struct wgl_pbuffer *pbuffer;
3562 EnterCriticalSection(&dc_pbuffers_section);
3563 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3564 if (pbuffer)
3566 if (context->format != pbuffer->format)
3568 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3569 LeaveCriticalSection(&dc_pbuffers_section);
3570 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3571 return FALSE;
3574 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer)
3575 set_swap_interval(context, 0);
3577 else
3579 WARN("no window or pbuffer for DC\n");
3580 LeaveCriticalSection(&dc_pbuffers_section);
3581 SetLastError(ERROR_INVALID_HANDLE);
3582 return FALSE;
3585 context->draw_hwnd = NULL;
3586 context->draw_view = NULL;
3587 context->draw_pbuffer = pbuffer;
3588 LeaveCriticalSection(&dc_pbuffers_section);
3591 context->read_view = NULL;
3592 context->read_pbuffer = NULL;
3593 if (read_hdc && read_hdc != draw_hdc)
3595 if ((hwnd = WindowFromDC(read_hdc)))
3597 if ((data = get_win_data(hwnd)))
3599 if (data->client_cocoa_view != context->draw_view)
3601 context->read_view = data->client_cocoa_view;
3602 context->read_rect = data->client_rect;
3603 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3605 release_win_data(data);
3608 else
3610 EnterCriticalSection(&dc_pbuffers_section);
3611 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3612 LeaveCriticalSection(&dc_pbuffers_section);
3616 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3617 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3618 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3620 make_context_current(context, FALSE);
3621 context->has_been_current = TRUE;
3622 NtCurrentTeb()->glContext = context;
3624 return TRUE;
3628 /**********************************************************************
3629 * macdrv_wglQueryCurrentRendererIntegerWINE
3631 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3633 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3635 BOOL ret = FALSE;
3636 struct wgl_context *context = NtCurrentTeb()->glContext;
3637 CGLPixelFormatObj pixel_format;
3638 CGLError err;
3639 GLint virtual_screen;
3640 GLint display_mask;
3641 GLint pf_renderer_id;
3642 CGLRendererInfoObj renderer_info;
3643 GLint renderer_count;
3644 GLint renderer;
3646 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3647 (context ? context->cglcontext : NULL), attribute, value);
3649 if (attribute == WGL_RENDERER_VERSION_WINE)
3651 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3652 get_fallback_renderer_version(value);
3653 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3654 return TRUE;
3657 pixel_format = CGLGetPixelFormat(context->cglcontext);
3658 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3659 if (err != kCGLNoError)
3661 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3662 return FALSE;
3665 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3666 if (err != kCGLNoError)
3668 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3669 return FALSE;
3672 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3673 if (err != kCGLNoError)
3675 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3676 return FALSE;
3679 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3680 if (err != kCGLNoError)
3682 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3683 return FALSE;
3686 for (renderer = 0; renderer < renderer_count; renderer++)
3688 GLint renderer_id;
3690 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3691 continue;
3693 if (renderer_id == pf_renderer_id)
3695 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3696 break;
3700 if (renderer >= renderer_count)
3701 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3703 CGLDestroyRendererInfo(renderer_info);
3704 return ret;
3708 /**********************************************************************
3709 * macdrv_wglQueryCurrentRendererStringWINE
3711 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3713 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3715 const char* ret = NULL;
3716 struct wgl_context *context = NtCurrentTeb()->glContext;
3718 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3719 (context ? context->cglcontext : NULL), attribute);
3721 switch (attribute)
3723 case WGL_RENDERER_DEVICE_ID_WINE:
3725 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3726 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3727 break;
3730 case WGL_RENDERER_VENDOR_ID_WINE:
3732 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3733 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3734 break;
3737 default:
3738 FIXME("unrecognized attribute 0x%04x\n", attribute);
3739 break;
3742 return ret;
3746 /**********************************************************************
3747 * macdrv_wglQueryPbufferARB
3749 * WGL_ARB_pbuffer: wglQueryPbufferARB
3751 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3753 CGLError err;
3754 GLsizei width;
3755 GLsizei height;
3756 GLenum target;
3757 GLenum internalFormat;
3758 GLint mipmap;
3760 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3762 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3763 if (err != kCGLNoError)
3765 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3766 SetLastError(ERROR_INVALID_HANDLE);
3767 return GL_FALSE;
3770 switch (iAttribute)
3772 case WGL_PBUFFER_WIDTH_ARB:
3773 *piValue = width;
3774 break;
3775 case WGL_PBUFFER_HEIGHT_ARB:
3776 *piValue = height;
3777 break;
3778 case WGL_PBUFFER_LOST_ARB:
3779 /* Mac PBuffers can't be lost */
3780 *piValue = GL_FALSE;
3781 break;
3782 case WGL_TEXTURE_FORMAT_ARB:
3783 if (pbuffer->no_texture)
3784 *piValue = WGL_NO_TEXTURE_ARB;
3785 else switch (internalFormat)
3787 case GL_RGBA:
3788 *piValue = WGL_TEXTURE_RGBA_ARB;
3789 break;
3790 case GL_RGB:
3791 default:
3792 *piValue = WGL_TEXTURE_RGB_ARB;
3793 break;
3795 break;
3796 case WGL_TEXTURE_TARGET_ARB:
3797 if (pbuffer->no_texture)
3798 *piValue = WGL_NO_TEXTURE_ARB;
3799 else switch (target)
3801 case GL_TEXTURE_CUBE_MAP:
3802 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3803 break;
3804 case GL_TEXTURE_2D:
3805 *piValue = WGL_TEXTURE_2D_ARB;
3806 break;
3807 case GL_TEXTURE_RECTANGLE:
3808 default:
3809 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3810 break;
3812 break;
3813 case WGL_MIPMAP_TEXTURE_ARB:
3814 *piValue = (pbuffer->max_level > 0);
3815 break;
3816 case WGL_MIPMAP_LEVEL_ARB:
3817 *piValue = pbuffer->level;
3818 break;
3819 case WGL_CUBE_MAP_FACE_ARB:
3820 switch (pbuffer->face)
3822 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3823 default:
3824 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3825 break;
3826 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3827 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3828 break;
3829 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3830 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3831 break;
3832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3833 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3834 break;
3835 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3836 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3837 break;
3838 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3839 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3840 break;
3842 break;
3843 default:
3844 WARN("invalid attribute 0x%x\n", iAttribute);
3845 SetLastError(ERROR_INVALID_DATA);
3846 return GL_FALSE;
3849 return GL_TRUE;
3853 /**********************************************************************
3854 * macdrv_wglQueryRendererIntegerWINE
3856 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3858 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3860 BOOL ret = FALSE;
3861 CGLRendererInfoObj renderer_info;
3862 GLint renderer_count;
3863 CGLError err;
3865 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3867 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3868 if (err != kCGLNoError)
3870 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3871 return FALSE;
3874 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3876 if (renderer < renderer_count)
3877 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3878 else
3879 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3881 CGLDestroyRendererInfo(renderer_info);
3882 return ret;
3886 /**********************************************************************
3887 * macdrv_wglQueryRendererStringWINE
3889 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3891 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3893 const char* ret = NULL;
3894 CGLRendererInfoObj renderer_info;
3895 GLint renderer_count;
3896 CGLError err;
3898 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3900 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3901 if (err != kCGLNoError)
3903 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3904 return FALSE;
3907 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3909 if (renderer >= renderer_count)
3911 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3912 goto done;
3915 switch (attribute)
3917 case WGL_RENDERER_DEVICE_ID_WINE:
3918 case WGL_RENDERER_VENDOR_ID_WINE:
3920 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3921 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3923 if (!pixel_format)
3924 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3925 if (pixel_format)
3927 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3928 CGLReleasePixelFormat(pixel_format);
3931 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3932 break;
3935 default:
3936 FIXME("unrecognized attribute 0x%04x\n", attribute);
3937 break;
3940 done:
3941 CGLDestroyRendererInfo(renderer_info);
3942 return ret;
3946 /**********************************************************************
3947 * macdrv_wglReleasePbufferDCARB
3949 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3951 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3953 struct wgl_pbuffer *prev;
3955 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3957 EnterCriticalSection(&dc_pbuffers_section);
3959 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3960 if (prev)
3962 if (prev != pbuffer)
3963 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3964 CGLReleasePBuffer(prev->pbuffer);
3965 HeapFree(GetProcessHeap(), 0, prev);
3966 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3968 else hdc = 0;
3970 LeaveCriticalSection(&dc_pbuffers_section);
3972 return hdc && DeleteDC(hdc);
3976 /**********************************************************************
3977 * macdrv_wglReleaseTexImageARB
3979 * WGL_ARB_render_texture: wglReleaseTexImageARB
3981 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3983 struct wgl_context *context = NtCurrentTeb()->glContext;
3984 CGLError err;
3986 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3988 if (pbuffer->no_texture)
3990 SetLastError(ERROR_INVALID_OPERATION);
3991 return GL_FALSE;
3994 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3995 if (err != kCGLNoError)
3997 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3998 SetLastError(ERROR_INVALID_OPERATION);
3999 return GL_FALSE;
4002 return GL_TRUE;
4006 /**********************************************************************
4007 * macdrv_wglSetPbufferAttribARB
4009 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4011 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
4013 struct wgl_context *context = NtCurrentTeb()->glContext;
4015 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
4017 for ( ; piAttribList && *piAttribList; piAttribList += 2)
4019 int attr = piAttribList[0];
4020 int value = piAttribList[1];
4021 switch (attr)
4023 case WGL_MIPMAP_LEVEL_ARB:
4024 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
4025 pbuffer->level = value;
4026 break;
4027 case WGL_CUBE_MAP_FACE_ARB:
4028 switch (value)
4030 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
4031 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4032 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4033 break;
4034 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4035 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4036 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4037 break;
4038 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4039 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4040 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4041 break;
4042 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4043 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4044 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4045 break;
4046 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4047 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4048 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4049 break;
4050 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4051 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4052 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4053 break;
4054 default:
4055 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4056 SetLastError(ERROR_INVALID_DATA);
4057 return GL_FALSE;
4059 break;
4060 default:
4061 WARN("invalid attribute 0x%x\n", attr);
4062 SetLastError(ERROR_INVALID_DATA);
4063 return GL_FALSE;
4067 if (context && context->draw_pbuffer == pbuffer)
4068 make_context_current(context, FALSE);
4070 return GL_TRUE;
4074 /**********************************************************************
4075 * macdrv_wglSetPixelFormatWINE
4077 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4079 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4081 return set_pixel_format(hdc, fmt, TRUE);
4085 /**********************************************************************
4086 * macdrv_wglSwapIntervalEXT
4088 * WGL_EXT_swap_control: wglSwapIntervalEXT
4090 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4092 struct wgl_context *context = NtCurrentTeb()->glContext;
4093 BOOL changed = FALSE;
4095 TRACE("interval %d\n", interval);
4097 if (interval < 0)
4099 SetLastError(ERROR_INVALID_DATA);
4100 return FALSE;
4102 if (interval > 1)
4103 interval = 1;
4105 if (context->draw_hwnd)
4107 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4108 if (data)
4110 changed = data->swap_interval != interval;
4111 if (changed)
4112 data->swap_interval = interval;
4113 release_win_data(data);
4116 else /* pbuffer */
4117 interval = 0;
4119 if (!allow_vsync)
4120 interval = 0;
4122 InterlockedExchange(&context->update_swap_interval, FALSE);
4123 if (!set_swap_interval(context, interval))
4125 SetLastError(ERROR_GEN_FAILURE);
4126 return FALSE;
4129 if (changed)
4131 struct wgl_context *ctx;
4133 EnterCriticalSection(&context_section);
4134 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4136 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4137 InterlockedExchange(&context->update_swap_interval, TRUE);
4139 LeaveCriticalSection(&context_section);
4142 return TRUE;
4146 static void register_extension(const char *ext)
4148 if (gl_info.wglExtensions[0])
4149 strcat(gl_info.wglExtensions, " ");
4150 strcat(gl_info.wglExtensions, ext);
4152 TRACE("'%s'\n", ext);
4155 static void load_extensions(void)
4158 * ARB Extensions
4160 register_extension("WGL_ARB_extensions_string");
4161 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4163 register_extension("WGL_ARB_make_current_read");
4164 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4165 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4167 register_extension("WGL_ARB_pixel_format");
4168 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4169 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4170 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4172 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4174 register_extension("WGL_ARB_pixel_format_float");
4175 register_extension("WGL_ATI_pixel_format_float");
4178 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4179 register_extension("WGL_ARB_multisample");
4181 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4182 register_extension("WGL_ARB_framebuffer_sRGB");
4184 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4186 register_extension("WGL_ARB_pbuffer");
4187 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4188 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4189 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4190 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4191 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4193 register_extension("WGL_ARB_render_texture");
4194 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4195 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4196 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4198 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4199 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4200 register_extension("WGL_NV_render_texture_rectangle");
4203 register_extension("WGL_ARB_create_context");
4204 register_extension("WGL_ARB_create_context_profile");
4205 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4208 * EXT Extensions
4210 register_extension("WGL_EXT_extensions_string");
4211 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4213 if (allow_vsync)
4215 register_extension("WGL_EXT_swap_control");
4216 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4217 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4220 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4221 check for either, so register them separately. */
4222 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4223 register_extension("WGL_EXT_framebuffer_sRGB");
4225 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4226 register_extension("WGL_EXT_pixel_format_packed_float");
4229 * WINE-specific WGL Extensions
4232 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4233 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4235 register_extension("WGL_WINE_pixel_format_passthrough");
4236 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4238 register_extension("WGL_WINE_query_renderer");
4239 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4240 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4241 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4242 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4246 static BOOL CALLBACK init_opengl(INIT_ONCE *init_once, void *context, void **param)
4248 static BOOL init_done = FALSE;
4249 unsigned int i;
4251 if (init_done) return (opengl_handle != NULL);
4252 init_done = TRUE;
4254 TRACE("()\n");
4256 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4257 if (!dc_pbuffers)
4259 WARN("CFDictionaryCreateMutable failed\n");
4260 return FALSE;
4263 opengl_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD);
4264 if (!opengl_handle)
4266 ERR("Failed to load OpenGL: %s\n", dlerror());
4267 ERR("OpenGL support is disabled.\n");
4268 return FALSE;
4271 for (i = 0; i < ARRAY_SIZE(opengl_func_names); i++)
4273 if (!(((void **)&opengl_funcs.gl)[i] = dlsym(opengl_handle, opengl_func_names[i])))
4275 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4276 goto failed;
4280 if (!init_gl_info())
4281 goto failed;
4283 /* redirect some standard OpenGL functions */
4284 #define REDIRECT(func) \
4285 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4286 REDIRECT(glCopyPixels);
4287 REDIRECT(glGetString);
4288 REDIRECT(glReadPixels);
4289 REDIRECT(glViewport);
4290 if (skip_single_buffer_flushes || allow_vsync)
4291 REDIRECT(glFlush);
4292 if (allow_vsync)
4293 REDIRECT(glFinish);
4294 #undef REDIRECT
4296 /* redirect some OpenGL extension functions */
4297 #define REDIRECT(func) \
4298 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4299 REDIRECT(glCopyColorTable);
4300 #undef REDIRECT
4302 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4303 pglFlushRenderAPPLE = dlsym(opengl_handle, "glFlushRenderAPPLE");
4305 load_extensions();
4306 if (!init_pixel_formats())
4307 goto failed;
4309 return TRUE;
4311 failed:
4312 dlclose(opengl_handle);
4313 opengl_handle = NULL;
4314 return FALSE;
4318 /***********************************************************************
4319 * sync_gl_view
4321 * Synchronize the Mac GL view position with the Windows child window
4322 * position.
4324 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4326 if (data->client_cocoa_view && data->pixel_format)
4328 RECT old = *old_client_rect, new = data->client_rect;
4330 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4331 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4332 if (!EqualRect(&old, &new))
4334 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4335 mark_contexts_for_moved_view(data->client_cocoa_view);
4341 /**********************************************************************
4342 * macdrv_wglDescribePixelFormat
4344 static int WINAPI macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4346 const pixel_format *pf;
4347 const struct color_mode *mode;
4349 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4351 if (!descr) return nb_displayable_formats;
4352 if (size < sizeof(*descr)) return 0;
4354 if (!(pf = get_pixel_format(fmt, FALSE)))
4355 return 0;
4357 memset(descr, 0, sizeof(*descr));
4358 descr->nSize = sizeof(*descr);
4359 descr->nVersion = 1;
4361 descr->dwFlags = PFD_SUPPORT_OPENGL;
4362 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4363 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4364 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4365 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4366 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4368 descr->iPixelType = PFD_TYPE_RGBA;
4370 mode = &color_modes[pf->color_mode];
4371 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4372 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4373 R8G8B8A0 pixel format). If an app depends on that and expects that
4374 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4375 if (mode->alpha_bits)
4376 descr->cColorBits = mode->color_bits;
4377 else
4378 descr->cColorBits = mode->bits_per_pixel;
4379 descr->cRedBits = mode->red_bits;
4380 descr->cRedShift = mode->red_shift;
4381 descr->cGreenBits = mode->green_bits;
4382 descr->cGreenShift = mode->green_shift;
4383 descr->cBlueBits = mode->blue_bits;
4384 descr->cBlueShift = mode->blue_shift;
4385 descr->cAlphaBits = mode->alpha_bits;
4386 descr->cAlphaShift = mode->alpha_shift;
4388 if (pf->accum_mode)
4390 mode = &color_modes[pf->accum_mode - 1];
4391 descr->cAccumBits = mode->color_bits;
4392 descr->cAccumRedBits = mode->red_bits;
4393 descr->cAccumGreenBits = mode->green_bits;
4394 descr->cAccumBlueBits = mode->blue_bits;
4395 descr->cAccumAlphaBits = mode->alpha_bits;
4398 descr->cDepthBits = pf->depth_bits;
4399 descr->cStencilBits = pf->stencil_bits;
4400 descr->cAuxBuffers = pf->aux_buffers;
4401 descr->iLayerType = PFD_MAIN_PLANE;
4403 TRACE("%s\n", debugstr_pf(pf));
4404 return nb_displayable_formats;
4407 /***********************************************************************
4408 * macdrv_wglCopyContext
4410 static BOOL WINAPI macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4412 CGLError err;
4414 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4416 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4417 if (err != kCGLNoError)
4418 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4419 return (err == kCGLNoError);
4422 /***********************************************************************
4423 * macdrv_wglCreateContext
4425 static struct wgl_context * WINAPI macdrv_wglCreateContext(HDC hdc)
4427 struct wgl_context *context;
4429 TRACE("hdc %p\n", hdc);
4431 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4433 return context;
4436 /***********************************************************************
4437 * macdrv_wglDeleteContext
4439 static BOOL WINAPI macdrv_wglDeleteContext(struct wgl_context *context)
4441 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4443 EnterCriticalSection(&context_section);
4444 list_remove(&context->entry);
4445 LeaveCriticalSection(&context_section);
4447 macdrv_dispose_opengl_context(context->context);
4448 return HeapFree(GetProcessHeap(), 0, context);
4451 /***********************************************************************
4452 * macdrv_wglGetPixelFormat
4454 static int WINAPI macdrv_wglGetPixelFormat(HDC hdc)
4456 int format;
4458 format = get_dc_pixel_format(hdc);
4460 if (!is_valid_pixel_format(format)) /* not set yet */
4461 format = 0;
4462 else if (!is_displayable_pixel_format(format))
4464 /* Non-displayable formats can't be used with traditional WGL calls.
4465 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4466 format = 1;
4469 TRACE(" hdc %p -> %d\n", hdc, format);
4470 return format;
4473 /***********************************************************************
4474 * macdrv_wglGetProcAddress
4476 static PROC WINAPI macdrv_wglGetProcAddress(const char *proc)
4478 void *ret;
4480 if (!strncmp(proc, "wgl", 3)) return NULL;
4481 ret = dlsym(opengl_handle, proc);
4482 if (ret)
4484 if (TRACE_ON(wgl))
4486 Dl_info info;
4487 if (dladdr(ret, &info))
4488 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4489 else
4490 TRACE("%s -> %p (no library info)\n", proc, ret);
4493 else
4494 WARN("failed to find proc %s\n", debugstr_a(proc));
4495 return ret;
4498 /***********************************************************************
4499 * macdrv_wglMakeCurrent
4501 static BOOL WINAPI macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4503 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4504 (context ? context->cglcontext : NULL));
4506 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4509 /**********************************************************************
4510 * macdrv_wglSetPixelFormat
4512 static BOOL WINAPI macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4514 return set_pixel_format(hdc, fmt, FALSE);
4517 /***********************************************************************
4518 * macdrv_wglShareLists
4520 static BOOL WINAPI macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4522 macdrv_opengl_context saved_context;
4523 CGLContextObj saved_cglcontext;
4525 TRACE("org %p dest %p\n", org, dest);
4527 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4528 * at context creation time but in case of WGL it is done using wglShareLists.
4530 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4531 * and when a program requests sharing we recreate the destination context if it hasn't been made
4532 * current or when it hasn't shared display lists before.
4535 if (dest->has_been_current)
4537 WARN("could not share display lists, the destination context has been current already\n");
4538 return FALSE;
4540 else if (dest->sharing)
4542 WARN("could not share display lists because dest has already shared lists before\n");
4543 return FALSE;
4546 /* Re-create the Mac context and share display lists */
4547 saved_context = dest->context;
4548 saved_cglcontext = dest->cglcontext;
4549 dest->context = NULL;
4550 dest->cglcontext = NULL;
4551 if (!create_context(dest, org->cglcontext, dest->major))
4553 dest->context = saved_context;
4554 dest->cglcontext = saved_cglcontext;
4555 return FALSE;
4558 /* Implicitly disposes of saved_cglcontext. */
4559 macdrv_dispose_opengl_context(saved_context);
4561 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4562 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4564 org->sharing = TRUE;
4565 dest->sharing = TRUE;
4567 return TRUE;
4570 /**********************************************************************
4571 * macdrv_wglSwapBuffers
4573 static BOOL WINAPI macdrv_wglSwapBuffers(HDC hdc)
4575 struct wgl_context *context = NtCurrentTeb()->glContext;
4576 BOOL match = FALSE;
4577 HWND hwnd;
4579 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4580 (context ? context->cglcontext : NULL));
4582 if (context)
4584 sync_swap_interval(context);
4585 sync_context(context);
4588 if ((hwnd = WindowFromDC(hdc)))
4590 struct macdrv_win_data *data;
4592 if (!(data = get_win_data(hwnd)))
4594 SetLastError(ERROR_INVALID_HANDLE);
4595 return FALSE;
4598 if (context && context->draw_view == data->client_cocoa_view)
4599 match = TRUE;
4601 release_win_data(data);
4603 else
4605 struct wgl_pbuffer *pbuffer;
4607 EnterCriticalSection(&dc_pbuffers_section);
4608 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4609 LeaveCriticalSection(&dc_pbuffers_section);
4611 if (!pbuffer)
4613 SetLastError(ERROR_INVALID_HANDLE);
4614 return FALSE;
4617 if (context && context->draw_pbuffer == pbuffer)
4618 match = TRUE;
4621 if (match)
4622 macdrv_flush_opengl_context(context->context);
4623 else
4625 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4627 /* If there is a current context, then wglSwapBuffers should do an implicit
4628 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4629 in the other branch, but we have to do it explicitly here. */
4630 if (context)
4631 pglFlush();
4634 return TRUE;
4637 static struct opengl_funcs opengl_funcs =
4640 macdrv_wglCopyContext, /* p_wglCopyContext */
4641 macdrv_wglCreateContext, /* p_wglCreateContext */
4642 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4643 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4644 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4645 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4646 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4647 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4648 macdrv_wglShareLists, /* p_wglShareLists */
4649 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4653 /**********************************************************************
4654 * macdrv_wine_get_wgl_driver
4656 struct opengl_funcs * CDECL macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
4658 static INIT_ONCE opengl_init = INIT_ONCE_STATIC_INIT;
4660 if (version != WINE_WGL_DRIVER_VERSION)
4662 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4663 return NULL;
4666 if (!InitOnceExecuteOnce(&opengl_init, init_opengl, NULL, NULL)) return (void *)-1;
4668 return &opengl_funcs;