wevtapi: Add EvtOpenSession stub.
[wine.git] / dlls / winemac.drv / opengl.c
blobf11727fe8aafb49d09be4b61c8bf460659563245
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
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 < sizeof(attrib_names) / sizeof(attrib_names[0]); 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(sizeof(displays) / sizeof(displays[0]), 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); 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 < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 = sizeof(color_modes)/sizeof(color_modes[0]) - 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 < sizeof(color_modes)/sizeof(color_modes[0]); 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 < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); 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 < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); 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 && stencil_mode > 0)
745 continue;
747 attribs[n++] = kCGLPFAStencilSize;
748 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
749 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
751 /* FIXME: Could trim search space a bit here depending on GPU.
752 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
753 n_stack[++n_stack_idx] = n;
754 for (stereo = 0; stereo <= 1; stereo++)
756 int accum_mode;
758 n = n_stack[n_stack_idx];
760 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
761 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
762 continue;
764 if (stereo)
765 attribs[n++] = kCGLPFAStereo;
766 request.stereo = stereo;
768 /* Starts at -1 for a 0 accum size */
769 n_stack[++n_stack_idx] = n;
770 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
772 unsigned int target_pass;
774 n = n_stack[n_stack_idx];
776 if (accum_mode >= 0)
778 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
779 continue;
781 attribs[n++] = kCGLPFAAccumSize;
782 attribs[n++] = color_modes[accum_mode].color_bits;
783 request.accum_mode = accum_mode + 1;
785 else
786 request.accum_mode = 0;
788 /* Targets to request are:
789 accelerated: window OR window + pbuffer
790 software: window + pbuffer */
791 n_stack[++n_stack_idx] = n;
792 for (target_pass = 0; target_pass <= accelerated; target_pass++)
794 unsigned int samples, max_samples;
796 n = n_stack[n_stack_idx];
798 attribs[n++] = kCGLPFAWindow;
799 request.window = 1;
801 if (!accelerated || target_pass > 0)
803 attribs[n++] = kCGLPFAPBuffer;
804 request.pbuffer = 1;
806 else
807 request.pbuffer = 0;
809 /* FIXME: Could trim search space a bit here depending on GPU.
810 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
811 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
812 n_stack[++n_stack_idx] = n;
813 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
814 for (samples = 1; samples <= max_samples; samples *= 2)
816 unsigned int backing_store, min_backing_store, max_backing_store;
818 n = n_stack[n_stack_idx];
820 if (samples > 1)
822 attribs[n++] = kCGLPFASampleBuffers;
823 attribs[n++] = renderer.max_sample_buffers;
824 attribs[n++] = kCGLPFASamples;
825 attribs[n++] = samples;
826 request.sample_buffers = renderer.max_sample_buffers;
827 request.samples = samples;
829 else
830 request.sample_buffers = request.samples = 0;
832 if (renderer.backing_store && double_buffer)
834 /* The software renderer seems to always preserve the backing store, whether
835 we ask for it or not. So don't bother not asking for it. */
836 min_backing_store = accelerated ? 0 : 1;
837 max_backing_store = 1;
839 else
840 min_backing_store = max_backing_store = 0;
841 n_stack[++n_stack_idx] = n;
842 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
844 CGLPixelFormatObj pix;
845 GLint virtualScreens;
846 CGLError err;
848 n = n_stack[n_stack_idx];
850 if (backing_store)
851 attribs[n++] = kCGLPFABackingStore;
852 request.backing_store = backing_store;
854 attribs[n] = 0;
856 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
857 if (err == kCGLNoError && pix)
859 pixel_format pf;
860 GLint value, color_size, alpha_size, color_float;
861 UInt64 pf_code;
862 CFNumberRef code_object;
863 BOOL dupe;
865 memset(&pf, 0, sizeof(pf));
867 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
868 pf.accelerated = value;
869 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
870 pf.aux_buffers = value;
871 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
872 pf.depth_bits = value;
873 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
874 pf.double_buffer = value;
875 if (pf.double_buffer &&
876 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
877 pf.backing_store = value;
878 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
879 pf.pbuffer = value;
880 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
881 pf.sample_buffers = value;
882 if (pf.sample_buffers &&
883 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
884 pf.samples = value;
885 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
886 pf.stencil_bits = value;
887 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
888 pf.stereo = value;
889 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
890 pf.window = value;
892 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
893 color_size = 0;
894 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
895 alpha_size = 0;
896 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
897 color_float = 0;
898 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
900 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
901 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
903 CGLReleasePixelFormat(pix);
905 pf_code = code_for_pixel_format(&pf);
907 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
908 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
909 dupe_pixel_formats++;
910 else
912 CFSetAddValue(pixel_format_set, code_object);
913 CFArrayAppendValue(pixel_format_array, code_object);
914 new_pixel_formats++;
916 CFRelease(code_object);
918 if (pf_code == code_for_pixel_format(&request))
919 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
920 else
922 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
923 dupe ? " (duplicate)" : "");
926 else
928 failed_pixel_formats++;
929 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
932 tried_pixel_formats++;
935 n_stack_idx--;
938 n_stack_idx--;
941 n_stack_idx--;
944 n_stack_idx--;
947 n_stack_idx--;
950 n_stack_idx--;
953 n_stack_idx--;
956 n_stack_idx--;
959 n_stack_idx--;
962 n_stack_idx--;
964 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
965 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
966 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
967 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
971 /* The docs for WGL_ARB_pixel_format say:
972 Indices are assigned to pixel formats in the following order:
973 1. Accelerated pixel formats that are displayable
974 2. Accelerated pixel formats that are displayable and which have
975 extended attributes
976 3. Generic pixel formats
977 4. Accelerated pixel formats that are non displayable
979 static int pixel_format_category(pixel_format pf)
981 /* non-displayable */
982 if (!pf.window)
983 return 4;
985 /* non-accelerated a.k.a. software a.k.a. generic */
986 if (!pf.accelerated)
987 return 3;
989 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
990 if (color_modes[pf.color_mode].is_float)
991 return 2;
993 /* accelerated, displayable, no extended attributes */
994 return 1;
998 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
1000 CFNumberRef number1 = val1;
1001 CFNumberRef number2 = val2;
1002 UInt64 code1, code2;
1003 pixel_format pf1, pf2;
1004 int category1, category2;
1006 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
1007 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
1008 pf1 = pixel_format_for_code(code1);
1009 pf2 = pixel_format_for_code(code2);
1010 category1 = pixel_format_category(pf1);
1011 category2 = pixel_format_category(pf2);
1013 if (category1 < category2)
1014 return kCFCompareLessThan;
1015 if (category1 > category2)
1016 return kCFCompareGreaterThan;
1018 /* Within a category, sort the "best" formats toward the front since that's
1019 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1020 matches at least one Windows 7 machine's behavior.
1022 /* Accelerated before unaccelerated. */
1023 if (pf1.accelerated && !pf2.accelerated)
1024 return kCFCompareLessThan;
1025 if (!pf1.accelerated && pf2.accelerated)
1026 return kCFCompareGreaterThan;
1028 /* Explicit color mode ordering. */
1029 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1030 return kCFCompareLessThan;
1031 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1032 return kCFCompareGreaterThan;
1034 /* Non-pbuffer-capable before pbuffer-capable. */
1035 if (!pf1.pbuffer && pf2.pbuffer)
1036 return kCFCompareLessThan;
1037 if (pf1.pbuffer && !pf2.pbuffer)
1038 return kCFCompareGreaterThan;
1040 /* Fewer samples before more samples. */
1041 if (pf1.samples < pf2.samples)
1042 return kCFCompareLessThan;
1043 if (pf1.samples > pf2.samples)
1044 return kCFCompareGreaterThan;
1046 /* Monoscopic before stereoscopic. (This is a guess.) */
1047 if (!pf1.stereo && pf2.stereo)
1048 return kCFCompareLessThan;
1049 if (pf1.stereo && !pf2.stereo)
1050 return kCFCompareGreaterThan;
1052 /* Single buffered before double buffered. */
1053 if (!pf1.double_buffer && pf2.double_buffer)
1054 return kCFCompareLessThan;
1055 if (pf1.double_buffer && !pf2.double_buffer)
1056 return kCFCompareGreaterThan;
1058 /* Possibly-optimized double buffering before backing-store-preserving
1059 double buffering. */
1060 if (!pf1.backing_store && pf2.backing_store)
1061 return kCFCompareLessThan;
1062 if (pf1.backing_store && !pf2.backing_store)
1063 return kCFCompareGreaterThan;
1065 /* Bigger depth buffer before smaller depth buffer. */
1066 if (pf1.depth_bits > pf2.depth_bits)
1067 return kCFCompareLessThan;
1068 if (pf1.depth_bits < pf2.depth_bits)
1069 return kCFCompareGreaterThan;
1071 /* Smaller stencil buffer before bigger stencil buffer. */
1072 if (pf1.stencil_bits < pf2.stencil_bits)
1073 return kCFCompareLessThan;
1074 if (pf1.stencil_bits > pf2.stencil_bits)
1075 return kCFCompareGreaterThan;
1077 /* Smaller alpha bits before larger alpha bits. */
1078 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1079 return kCFCompareLessThan;
1080 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1081 return kCFCompareGreaterThan;
1083 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1084 if (pf1.accum_mode)
1086 if (pf2.accum_mode)
1088 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1089 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1090 return kCFCompareLessThan;
1091 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1092 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1093 return kCFCompareGreaterThan;
1095 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1096 return kCFCompareLessThan;
1097 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1098 return kCFCompareGreaterThan;
1100 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1101 return kCFCompareLessThan;
1102 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1103 return kCFCompareGreaterThan;
1105 else
1106 return kCFCompareGreaterThan;
1108 else if (pf2.accum_mode)
1109 return kCFCompareLessThan;
1111 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1112 if (pf1.aux_buffers < pf2.aux_buffers)
1113 return kCFCompareLessThan;
1114 if (pf1.aux_buffers > pf2.aux_buffers)
1115 return kCFCompareGreaterThan;
1117 /* If we get here, arbitrarily sort based on code. */
1118 if (code1 < code2)
1119 return kCFCompareLessThan;
1120 if (code1 > code2)
1121 return kCFCompareGreaterThan;
1122 return kCFCompareEqualTo;
1126 static BOOL init_pixel_formats(void)
1128 BOOL ret = FALSE;
1129 CGLRendererInfoObj renderer_info;
1130 GLint rendererCount;
1131 CGLError err;
1132 CFMutableSetRef pixel_format_set;
1133 CFMutableArrayRef pixel_format_array;
1134 int i;
1135 CFRange range;
1137 TRACE("()\n");
1139 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1140 if (err)
1142 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1143 return FALSE;
1146 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1147 if (!pixel_format_set)
1149 WARN("CFSetCreateMutable failed\n");
1150 CGLDestroyRendererInfo(renderer_info);
1151 return FALSE;
1154 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1155 if (!pixel_format_array)
1157 WARN("CFArrayCreateMutable failed\n");
1158 CFRelease(pixel_format_set);
1159 CGLDestroyRendererInfo(renderer_info);
1160 return FALSE;
1163 for (i = 0; i < rendererCount; i++)
1165 renderer_properties renderer;
1167 get_renderer_properties(renderer_info, i, &renderer);
1168 if (TRACE_ON(wgl))
1170 TRACE("renderer_properties %d:\n", i);
1171 dump_renderer(&renderer);
1174 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1177 CFRelease(pixel_format_set);
1178 CGLDestroyRendererInfo(renderer_info);
1180 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1181 if (range.length)
1183 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1184 if (pixel_formats)
1186 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1187 for (i = 0; i < range.length; i++)
1189 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1190 UInt64 code;
1192 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1193 pixel_formats[i] = pixel_format_for_code(code);
1194 if (pixel_formats[i].window)
1195 nb_displayable_formats++;
1198 nb_formats = range.length;
1199 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1200 ret = TRUE;
1202 else
1203 WARN("failed to allocate pixel format list\n");
1205 else
1206 WARN("got no pixel formats\n");
1208 CFRelease(pixel_format_array);
1209 return ret;
1213 static inline BOOL is_valid_pixel_format(int format)
1215 return format > 0 && format <= nb_formats;
1219 static inline BOOL is_displayable_pixel_format(int format)
1221 return format > 0 && format <= nb_displayable_formats;
1225 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1227 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1228 * format in case of probing the number of pixel formats.
1230 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1232 TRACE("Returning format %d\n", format);
1233 return &pixel_formats[format - 1];
1235 return NULL;
1239 static BOOL init_gl_info(void)
1241 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1242 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1244 CGDirectDisplayID display = CGMainDisplayID();
1245 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1246 CGLPixelFormatAttribute attribs[] = {
1247 kCGLPFADisplayMask, displayMask,
1250 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1251 CGLPixelFormatAttribute core_attribs[] =
1253 kCGLPFADisplayMask, displayMask,
1254 kCGLPFAAccelerated,
1255 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1258 #endif
1259 CGLPixelFormatObj pix;
1260 GLint virtualScreens;
1261 CGLError err;
1262 CGLContextObj context;
1263 CGLContextObj old_context = CGLGetCurrentContext();
1264 const char *str;
1265 size_t length;
1267 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1268 if (err != kCGLNoError || !pix)
1270 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1271 return FALSE;
1274 err = CGLCreateContext(pix, NULL, &context);
1275 CGLReleasePixelFormat(pix);
1276 if (err != kCGLNoError || !context)
1278 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1279 return FALSE;
1282 err = CGLSetCurrentContext(context);
1283 if (err != kCGLNoError)
1285 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1286 CGLReleaseContext(context);
1287 return FALSE;
1290 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1291 length = strlen(str) + sizeof(legacy_extensions);
1292 if (allow_vsync)
1293 length += strlen(legacy_ext_swap_control);
1294 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1295 strcpy(gl_info.glExtensions, str);
1296 strcat(gl_info.glExtensions, legacy_extensions);
1297 if (allow_vsync)
1298 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1300 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1302 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1303 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1304 TRACE("GL version : %s\n", str);
1305 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1307 CGLSetCurrentContext(old_context);
1308 CGLReleaseContext(context);
1310 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1311 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1312 if (err != kCGLNoError || !pix)
1314 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1315 err, CGLErrorString(err));
1316 return TRUE;
1319 err = CGLCreateContext(pix, NULL, &context);
1320 CGLReleasePixelFormat(pix);
1321 if (err != kCGLNoError || !context)
1323 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1324 err, CGLErrorString(err));
1325 return TRUE;
1328 err = CGLSetCurrentContext(context);
1329 if (err != kCGLNoError)
1331 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1332 err, CGLErrorString(err));
1333 CGLReleaseContext(context);
1334 return TRUE;
1337 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1338 TRACE("Core context GL version: %s\n", str);
1339 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1340 CGLSetCurrentContext(old_context);
1341 CGLReleaseContext(context);
1342 #endif
1344 return TRUE;
1348 static int get_dc_pixel_format(HDC hdc)
1350 int format;
1351 HWND hwnd;
1353 if ((hwnd = WindowFromDC(hdc)))
1355 struct macdrv_win_data *data;
1357 if (!(data = get_win_data(hwnd)))
1359 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1360 return 0;
1363 format = data->pixel_format;
1364 release_win_data(data);
1366 else
1368 struct wgl_pbuffer *pbuffer;
1370 EnterCriticalSection(&dc_pbuffers_section);
1371 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1372 if (pbuffer)
1373 format = pbuffer->format;
1374 else
1376 WARN("no window or pbuffer for DC %p\n", hdc);
1377 format = 0;
1379 LeaveCriticalSection(&dc_pbuffers_section);
1382 return format;
1386 /**********************************************************************
1387 * create_context
1389 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1391 const pixel_format *pf;
1392 CGLPixelFormatAttribute attribs[64];
1393 int n = 0;
1394 CGLPixelFormatObj pix;
1395 GLint virtualScreens;
1396 CGLError err;
1397 BOOL core = major >= 3;
1399 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1400 if (core)
1402 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1403 return FALSE;
1405 #endif
1407 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1408 if (!pf)
1410 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1411 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1412 return FALSE;
1415 attribs[n++] = kCGLPFAMinimumPolicy;
1416 attribs[n++] = kCGLPFAClosestPolicy;
1418 if (context->renderer_id)
1420 attribs[n++] = kCGLPFARendererID;
1421 attribs[n++] = context->renderer_id;
1422 attribs[n++] = kCGLPFASingleRenderer;
1423 attribs[n++] = kCGLPFANoRecovery;
1426 if (pf->accelerated)
1428 attribs[n++] = kCGLPFAAccelerated;
1429 attribs[n++] = kCGLPFANoRecovery;
1431 else
1433 attribs[n++] = kCGLPFARendererID;
1434 attribs[n++] = kCGLRendererGenericFloatID;
1437 if (pf->double_buffer)
1438 attribs[n++] = kCGLPFADoubleBuffer;
1440 if (!core)
1442 attribs[n++] = kCGLPFAAuxBuffers;
1443 attribs[n++] = pf->aux_buffers;
1446 attribs[n++] = kCGLPFAColorSize;
1447 attribs[n++] = color_modes[pf->color_mode].color_bits;
1448 attribs[n++] = kCGLPFAAlphaSize;
1449 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1450 if (color_modes[pf->color_mode].is_float)
1451 attribs[n++] = kCGLPFAColorFloat;
1453 attribs[n++] = kCGLPFADepthSize;
1454 attribs[n++] = pf->depth_bits;
1456 attribs[n++] = kCGLPFAStencilSize;
1457 attribs[n++] = pf->stencil_bits;
1459 if (pf->stereo)
1460 attribs[n++] = kCGLPFAStereo;
1462 if (pf->accum_mode && !core)
1464 attribs[n++] = kCGLPFAAccumSize;
1465 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1468 if (pf->pbuffer && !core)
1469 attribs[n++] = kCGLPFAPBuffer;
1471 if (pf->sample_buffers && pf->samples)
1473 attribs[n++] = kCGLPFASampleBuffers;
1474 attribs[n++] = pf->sample_buffers;
1475 attribs[n++] = kCGLPFASamples;
1476 attribs[n++] = pf->samples;
1479 if (pf->backing_store)
1480 attribs[n++] = kCGLPFABackingStore;
1482 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1483 if (core)
1485 attribs[n++] = kCGLPFAOpenGLProfile;
1486 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1487 if (major == 3)
1488 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1489 else
1490 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1491 #else
1492 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1493 #endif
1495 #endif
1497 attribs[n] = 0;
1499 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1500 if (err != kCGLNoError || !pix)
1502 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1503 SetLastError(ERROR_INVALID_OPERATION);
1504 return FALSE;
1507 err = CGLCreateContext(pix, share, &context->cglcontext);
1508 CGLReleasePixelFormat(pix);
1509 if (err != kCGLNoError || !context->cglcontext)
1511 context->cglcontext = NULL;
1512 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1513 SetLastError(ERROR_INVALID_OPERATION);
1514 return FALSE;
1517 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1519 GLint opacity = 0;
1520 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1521 if (err != kCGLNoError)
1522 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1524 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1526 GLint order = -1;
1527 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1528 if (err != kCGLNoError)
1529 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1532 context->context = macdrv_create_opengl_context(context->cglcontext);
1533 CGLReleaseContext(context->cglcontext);
1534 if (!context->context)
1536 WARN("macdrv_create_opengl_context() failed\n");
1537 SetLastError(ERROR_INVALID_OPERATION);
1538 return FALSE;
1540 context->major = major;
1542 if (allow_vsync)
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 (context->draw_hwnd)
1747 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1748 if (data)
1750 interval = data->swap_interval;
1751 release_win_data(data);
1753 else /* window was destroyed? */
1754 interval = 1;
1756 else /* pbuffer */
1757 interval = 0;
1759 set_swap_interval(context, interval);
1764 /**********************************************************************
1765 * get_iokit_display_property
1767 static BOOL get_iokit_display_property(CGLRendererInfoObj renderer_info, GLint renderer, CFStringRef property, GLuint* value)
1769 GLint accelerated;
1770 GLint display_mask;
1771 int i;
1773 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, &accelerated) || !accelerated)
1775 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1776 return FALSE;
1779 if (!get_renderer_property(renderer_info, renderer, kCGLRPDisplayMask, &display_mask))
1781 WARN("failed to get kCGLRPDisplayMask\n");
1782 return FALSE;
1785 for (i = 0; i < sizeof(GLint) * 8; i++)
1787 GLint this_display_mask = (GLint)(1U << i);
1788 if (this_display_mask & display_mask)
1790 CGDirectDisplayID display_id = CGOpenGLDisplayMaskToDisplayID(this_display_mask);
1791 io_service_t service;
1792 CFDataRef data;
1793 uint32_t prop_value;
1795 if (!display_id)
1796 continue;
1797 service = CGDisplayIOServicePort(display_id);
1798 if (!service)
1800 WARN("CGDisplayIOServicePort(%u) failed\n", display_id);
1801 continue;
1804 data = IORegistryEntrySearchCFProperty(service, kIOServicePlane, property, NULL,
1805 kIORegistryIterateRecursively | kIORegistryIterateParents);
1806 if (!data)
1808 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property), display_id);
1809 continue;
1811 if (CFGetTypeID(data) != CFDataGetTypeID())
1813 WARN("property %s is not a data object: %s\n", debugstr_cf(property), debugstr_cf(data));
1814 CFRelease(data);
1815 continue;
1817 if (CFDataGetLength(data) != sizeof(prop_value))
1819 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property), display_id,
1820 (unsigned long long)CFDataGetLength(data));
1821 CFRelease(data);
1822 continue;
1825 CFDataGetBytes(data, CFRangeMake(0, sizeof(prop_value)), (UInt8*)&prop_value);
1826 CFRelease(data);
1827 *value = prop_value;
1828 return TRUE;
1832 return FALSE;
1836 /**********************************************************************
1837 * create_pixel_format_for_renderer
1839 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1840 * responsible for releasing the pixel format object.
1842 static CGLPixelFormatObj create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info, GLint renderer, BOOL core)
1844 GLint renderer_id;
1845 CGLPixelFormatAttribute attrs[] = {
1846 kCGLPFARendererID, 0,
1847 kCGLPFASingleRenderer,
1848 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1851 CGError err;
1852 CGLPixelFormatObj pixel_format;
1853 GLint virtual_screens;
1855 if (core)
1857 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1858 attrs[3] = kCGLPFAOpenGLProfile;
1859 attrs[4] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
1860 #else
1861 return NULL;
1862 #endif
1865 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
1866 return NULL;
1868 attrs[1] = renderer_id;
1869 err = CGLChoosePixelFormat(attrs, &pixel_format, &virtual_screens);
1870 if (err != kCGLNoError)
1871 pixel_format = NULL;
1872 return pixel_format;
1876 /**********************************************************************
1877 * map_renderer_index
1879 * We can't create pixel formats for all renderers listed. For example,
1880 * in a dual-GPU system, the integrated GPU is typically unavailable
1881 * when the discrete GPU is active.
1883 * This function conceptually creates a list of "good" renderers from the
1884 * list of all renderers. It treats the input "renderer" parameter as an
1885 * index into that list of good renderers and returns the corresponding
1886 * index into the list of all renderers.
1888 static GLint map_renderer_index(CGLRendererInfoObj renderer_info, GLint renderer_count, GLint renderer)
1890 GLint good_count, i;
1892 good_count = 0;
1893 for (i = 0; i < renderer_count; i++)
1895 CGLPixelFormatObj pix = create_pixel_format_for_renderer(renderer_info, i, FALSE);
1896 if (pix)
1898 CGLReleasePixelFormat(pix);
1899 good_count++;
1900 if (good_count > renderer)
1901 break;
1903 else
1904 TRACE("skipping bad renderer %d\n", i);
1907 TRACE("mapped requested renderer %d to index %d\n", renderer, i);
1908 return i;
1912 /**********************************************************************
1913 * get_gl_string
1915 static const char* get_gl_string(CGLPixelFormatObj pixel_format, GLenum name)
1917 const char* ret = NULL;
1918 CGLContextObj context, old_context;
1919 CGLError err;
1921 err = CGLCreateContext(pixel_format, NULL, &context);
1922 if (err == kCGLNoError && context)
1924 old_context = CGLGetCurrentContext();
1925 err = CGLSetCurrentContext(context);
1926 if (err == kCGLNoError)
1928 ret = (const char*)opengl_funcs.gl.p_glGetString(name);
1929 CGLSetCurrentContext(old_context);
1931 else
1932 WARN("CGLSetCurrentContext failed: %d %s\n", err, CGLErrorString(err));
1933 CGLReleaseContext(context);
1935 else
1936 WARN("CGLCreateContext failed: %d %s\n", err, CGLErrorString(err));
1938 return ret;
1942 /**********************************************************************
1943 * get_fallback_renderer_version
1945 static void get_fallback_renderer_version(GLuint *value)
1947 BOOL got_it = FALSE;
1948 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1949 kCFURLPOSIXPathStyle, TRUE);
1950 if (url)
1952 CFBundleRef bundle = CFBundleCreate(NULL, url);
1953 CFRelease(url);
1954 if (bundle)
1956 CFStringRef version = CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
1957 if (version && CFGetTypeID(version) == CFStringGetTypeID())
1959 size_t len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(version), kCFStringEncodingUTF8);
1960 char* buf = HeapAlloc(GetProcessHeap(), 0, len);
1961 if (buf && CFStringGetCString(version, buf, len, kCFStringEncodingUTF8))
1963 unsigned int major, minor, bugfix;
1964 int count = sscanf(buf, "%u.%u.%u", &major, &minor, &bugfix);
1965 if (count >= 2)
1967 value[0] = major;
1968 value[1] = minor;
1969 if (count == 3)
1970 value[2] = bugfix;
1971 else
1972 value[2] = 0;
1973 got_it = TRUE;
1976 HeapFree(GetProcessHeap(), 0, buf);
1978 CFRelease(bundle);
1982 if (!got_it)
1984 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1985 earliest version that the Mac driver supports. */
1986 value[0] = 1;
1987 value[1] = 6;
1988 value[2] = 14;
1993 /**********************************************************************
1994 * parse_renderer_version
1996 * Get the renderer version from the OpenGL version string. Assumes
1997 * the string is of the form
1998 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1999 * where major, minor, and bugfix are what we're interested in. This
2000 * form for the vendor specific information is not generally applicable,
2001 * but seems reliable on OS X.
2003 static BOOL parse_renderer_version(const char* version, GLuint *value)
2005 const char* p = strchr(version, ' ');
2006 int count;
2007 unsigned int major, minor, bugfix;
2009 if (p) p = strchr(p + 1, '-');
2010 if (!p) return FALSE;
2012 count = sscanf(p + 1, "%u.%u.%u", &major, &minor, &bugfix);
2013 if (count < 2)
2014 return FALSE;
2016 value[0] = major;
2017 value[1] = minor;
2018 if (count == 3)
2019 value[2] = bugfix;
2020 else
2021 value[2] = 0;
2023 return TRUE;
2027 /**********************************************************************
2028 * query_renderer_integer
2030 static BOOL query_renderer_integer(CGLRendererInfoObj renderer_info, GLint renderer, GLenum attribute, GLuint *value)
2032 BOOL ret = FALSE;
2033 CGLError err;
2035 if (TRACE_ON(wgl))
2037 GLint renderer_id;
2038 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
2039 renderer_id = 0;
2040 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer, renderer_id, attribute, value);
2043 switch (attribute)
2045 case WGL_RENDERER_ACCELERATED_WINE:
2046 if (!get_renderer_property(renderer_info, renderer, kCGLRPAccelerated, (GLint*)value))
2047 break;
2048 *value = !!*value;
2049 ret = TRUE;
2050 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value);
2051 break;
2053 case WGL_RENDERER_DEVICE_ID_WINE:
2054 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("device-id"), value);
2055 if (!ret)
2057 *value = 0xffffffff;
2058 ret = TRUE;
2060 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value);
2061 break;
2063 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE:
2064 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE:
2066 BOOL core = (attribute == WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE);
2067 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, core);
2069 if (pixel_format)
2071 const char* version = get_gl_string(pixel_format, GL_VERSION);
2073 CGLReleasePixelFormat(pixel_format);
2074 if (version)
2076 unsigned int major, minor;
2078 if (sscanf(version, "%u.%u", &major, &minor) == 2)
2080 value[0] = major;
2081 value[1] = minor;
2082 ret = TRUE;
2087 if (!ret)
2089 value[0] = value[1] = 0;
2090 ret = TRUE;
2092 TRACE("%s -> %u.%u\n", core ? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2093 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value[0], value[1]);
2094 break;
2097 case WGL_RENDERER_PREFERRED_PROFILE_WINE:
2099 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2101 if (pixel_format)
2103 CGLReleasePixelFormat(pixel_format);
2104 *value = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2105 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value);
2107 else
2109 *value = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
2110 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value);
2112 ret = TRUE;
2113 break;
2116 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE:
2117 /* FIXME: no API to query this */
2118 *value = 0;
2119 ret = TRUE;
2120 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value);
2121 break;
2123 case WGL_RENDERER_VENDOR_ID_WINE:
2124 ret = get_iokit_display_property(renderer_info, renderer, CFSTR("vendor-id"), value);
2125 if (!ret)
2127 *value = 0xffffffff;
2128 ret = TRUE;
2130 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value);
2131 break;
2133 case WGL_RENDERER_VERSION_WINE:
2135 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
2137 if (!pixel_format)
2138 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
2139 if (pixel_format)
2141 const char* version = get_gl_string(pixel_format, GL_VERSION);
2143 CGLReleasePixelFormat(pixel_format);
2144 if (version)
2145 ret = parse_renderer_version(version, value);
2148 if (!ret)
2150 get_fallback_renderer_version(value);
2151 ret = TRUE;
2153 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
2154 break;
2157 case WGL_RENDERER_VIDEO_MEMORY_WINE:
2158 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2159 err = CGLDescribeRenderer(renderer_info, renderer, kCGLRPVideoMemoryMegabytes, (GLint*)value);
2160 if (err != kCGLNoError && err != kCGLBadProperty)
2161 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err, CGLErrorString(err));
2162 if (err != kCGLNoError)
2163 #endif
2165 if (get_renderer_property(renderer_info, renderer, kCGLRPVideoMemory, (GLint*)value))
2166 *value /= 1024 * 1024;
2167 else
2168 *value = 0;
2170 ret = TRUE;
2171 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value);
2172 break;
2174 default:
2175 FIXME("unrecognized attribute 0x%04x\n", attribute);
2176 break;
2179 return ret;
2183 /**********************************************************************
2184 * macdrv_glCopyColorTable
2186 * Hook into glCopyColorTable as part of the implementation of
2187 * wglMakeContextCurrentARB. If the context has a separate readable,
2188 * temporarily make that current, do glCopyColorTable, and then set it
2189 * back to the drawable. This is modeled after what Mesa GLX's Apple
2190 * implementation does.
2192 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
2193 GLsizei width)
2195 struct wgl_context *context = NtCurrentTeb()->glContext;
2197 if (context->read_view || context->read_pbuffer)
2198 make_context_current(context, TRUE);
2200 pglCopyColorTable(target, internalformat, x, y, width);
2202 if (context->read_view || context->read_pbuffer)
2203 make_context_current(context, FALSE);
2207 /**********************************************************************
2208 * macdrv_glCopyPixels
2210 * Hook into glCopyPixels as part of the implementation of
2211 * wglMakeContextCurrentARB. If the context has a separate readable,
2212 * temporarily make that current, do glCopyPixels, and then set it back
2213 * to the drawable. This is modeled after what Mesa GLX's Apple
2214 * implementation does.
2216 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2218 struct wgl_context *context = NtCurrentTeb()->glContext;
2220 if (context->read_view || context->read_pbuffer)
2221 make_context_current(context, TRUE);
2223 pglCopyPixels(x, y, width, height, type);
2225 if (context->read_view || context->read_pbuffer)
2226 make_context_current(context, FALSE);
2230 /**********************************************************************
2231 * macdrv_glFinish
2233 static void macdrv_glFinish(void)
2235 struct wgl_context *context = NtCurrentTeb()->glContext;
2237 sync_swap_interval(context);
2238 sync_context(context);
2239 pglFinish();
2243 /**********************************************************************
2244 * macdrv_glFlush
2246 static void macdrv_glFlush(void)
2248 struct wgl_context *context = NtCurrentTeb()->glContext;
2250 sync_swap_interval(context);
2251 sync_context(context);
2253 if (skip_single_buffer_flushes)
2255 const pixel_format *pf = &pixel_formats[context->format - 1];
2256 DWORD now = GetTickCount();
2258 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
2259 context->last_flush_time, now);
2260 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
2262 TRACE("calling glFlushRenderAPPLE()\n");
2263 pglFlushRenderAPPLE();
2264 return;
2266 else
2268 TRACE("calling glFlush()\n");
2269 context->last_flush_time = now;
2273 pglFlush();
2277 /**********************************************************************
2278 * macdrv_glGetString
2280 * Hook into glGetString in order to return some legacy WGL extensions
2281 * that couldn't be advertised via the standard
2282 * WGL_ARB_extensions_string mechanism. Some programs, especially
2283 * older ones, expect to find certain older extensions, such as
2284 * WGL_EXT_extensions_string itself, in the standard GL extensions
2285 * string, and won't query any other WGL extensions unless they find
2286 * that particular extension there.
2288 static const GLubyte *macdrv_glGetString(GLenum name)
2290 if (name == GL_EXTENSIONS && gl_info.glExtensions)
2291 return (const GLubyte *)gl_info.glExtensions;
2292 else
2293 return pglGetString(name);
2297 /**********************************************************************
2298 * macdrv_glReadPixels
2300 * Hook into glReadPixels as part of the implementation of
2301 * wglMakeContextCurrentARB. If the context has a separate readable,
2302 * temporarily make that current, do glReadPixels, and then set it back
2303 * to the drawable. This is modeled after what Mesa GLX's Apple
2304 * implementation does.
2306 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2307 GLenum format, GLenum type, void *pixels)
2309 struct wgl_context *context = NtCurrentTeb()->glContext;
2311 if (context->read_view || context->read_pbuffer)
2312 make_context_current(context, TRUE);
2314 pglReadPixels(x, y, width, height, format, type, pixels);
2316 if (context->read_view || context->read_pbuffer)
2317 make_context_current(context, FALSE);
2321 /**********************************************************************
2322 * macdrv_glViewport
2324 * Hook into glViewport as an opportunity to update the OpenGL context
2325 * if necessary. This is modeled after what Mesa GLX's Apple
2326 * implementation does.
2328 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2330 struct wgl_context *context = NtCurrentTeb()->glContext;
2332 sync_context(context);
2333 macdrv_update_opengl_context(context->context);
2334 pglViewport(x, y, width, height);
2338 /***********************************************************************
2339 * macdrv_wglBindTexImageARB
2341 * WGL_ARB_render_texture: wglBindTexImageARB
2343 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2345 struct wgl_context *context = NtCurrentTeb()->glContext;
2346 GLenum source;
2347 CGLError err;
2349 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
2351 if (pbuffer->no_texture)
2353 SetLastError(ERROR_INVALID_OPERATION);
2354 return GL_FALSE;
2357 if (!context->draw_view && context->draw_pbuffer == pbuffer)
2358 opengl_funcs.gl.p_glFlush();
2360 switch (iBuffer)
2362 case WGL_FRONT_LEFT_ARB:
2363 if (pixel_formats[pbuffer->format - 1].stereo)
2364 source = GL_FRONT_LEFT;
2365 else
2366 source = GL_FRONT;
2367 break;
2368 case WGL_FRONT_RIGHT_ARB:
2369 source = GL_FRONT_RIGHT;
2370 break;
2371 case WGL_BACK_LEFT_ARB:
2372 if (pixel_formats[pbuffer->format - 1].stereo)
2373 source = GL_BACK_LEFT;
2374 else
2375 source = GL_BACK;
2376 break;
2377 case WGL_BACK_RIGHT_ARB:
2378 source = GL_BACK_RIGHT;
2379 break;
2380 case WGL_AUX0_ARB: source = GL_AUX0; break;
2381 case WGL_AUX1_ARB: source = GL_AUX1; break;
2382 case WGL_AUX2_ARB: source = GL_AUX2; break;
2383 case WGL_AUX3_ARB: source = GL_AUX3; break;
2385 case WGL_AUX4_ARB:
2386 case WGL_AUX5_ARB:
2387 case WGL_AUX6_ARB:
2388 case WGL_AUX7_ARB:
2389 case WGL_AUX8_ARB:
2390 case WGL_AUX9_ARB:
2391 FIXME("unsupported source buffer 0x%x\n", iBuffer);
2392 SetLastError(ERROR_INVALID_DATA);
2393 return GL_FALSE;
2395 default:
2396 WARN("unknown source buffer 0x%x\n", iBuffer);
2397 SetLastError(ERROR_INVALID_DATA);
2398 return GL_FALSE;
2401 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
2402 if (err != kCGLNoError)
2404 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2405 SetLastError(ERROR_INVALID_OPERATION);
2406 return GL_FALSE;
2409 return GL_TRUE;
2413 /***********************************************************************
2414 * macdrv_wglChoosePixelFormatARB
2416 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2418 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2419 const FLOAT *pfAttribFList, UINT nMaxFormats,
2420 int *piFormats, UINT *nNumFormats)
2422 pixel_format pf, valid;
2423 const int *iptr;
2424 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2425 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2426 int float_color;
2427 BOOL srgb;
2428 int i, found = 0;
2430 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2431 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2432 if (pfAttribFList)
2433 FIXME("unused pfAttribFList\n");
2435 memset(&pf, 0, sizeof(pf));
2436 memset(&valid, 0, sizeof(valid));
2437 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2438 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2439 float_color = -1;
2440 srgb = FALSE;
2442 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2444 int attr = iptr[0];
2445 int value = iptr[1];
2447 TRACE("%s\n", debugstr_attrib(attr, value));
2449 switch (attr)
2451 case WGL_DRAW_TO_WINDOW_ARB:
2452 if (valid.window && (!pf.window != !value)) goto cant_match;
2453 pf.window = (value != 0);
2454 valid.window = 1;
2455 break;
2457 case WGL_DRAW_TO_BITMAP_ARB:
2458 goto cant_match;
2460 case WGL_ACCELERATION_ARB:
2461 if (value == WGL_FULL_ACCELERATION_ARB)
2462 value = 1;
2463 else if (value == WGL_NO_ACCELERATION_ARB)
2464 value = 0;
2465 else
2466 goto cant_match;
2467 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2468 pf.accelerated = value;
2469 valid.accelerated = 1;
2470 break;
2472 case WGL_NEED_PALETTE_ARB:
2473 case WGL_NEED_SYSTEM_PALETTE_ARB:
2474 case WGL_SWAP_LAYER_BUFFERS_ARB:
2475 if (value) goto cant_match;
2476 break;
2478 case WGL_SWAP_METHOD_ARB:
2479 if (value == WGL_SWAP_COPY_ARB)
2480 value = 1;
2481 else if (value == WGL_SWAP_UNDEFINED_ARB)
2482 value = 0;
2483 else
2484 goto cant_match;
2485 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2486 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2487 pf.backing_store = value;
2488 valid.backing_store = 1;
2489 break;
2491 case WGL_NUMBER_OVERLAYS_ARB:
2492 case WGL_NUMBER_UNDERLAYS_ARB:
2493 if (value) goto cant_match;
2494 break;
2496 case WGL_SHARE_DEPTH_ARB:
2497 case WGL_SHARE_STENCIL_ARB:
2498 case WGL_SHARE_ACCUM_ARB:
2499 /* no effect */
2500 break;
2502 case WGL_SUPPORT_GDI_ARB:
2503 if (value) goto cant_match;
2504 break;
2506 case WGL_SUPPORT_OPENGL_ARB:
2507 if (!value) goto cant_match;
2508 break;
2510 case WGL_DOUBLE_BUFFER_ARB:
2511 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2512 pf.double_buffer = (value != 0);
2513 valid.double_buffer = 1;
2514 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2515 break;
2517 case WGL_STEREO_ARB:
2518 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2519 pf.stereo = (value != 0);
2520 valid.stereo = 1;
2521 break;
2523 case WGL_PIXEL_TYPE_ARB:
2524 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2525 value = 1;
2526 else if (value == WGL_TYPE_RGBA_ARB)
2527 value = 0;
2528 else
2530 /* Mac contexts don't support rendering to unsigned floating
2531 point formats, even if GL_EXT_packed_float is supported.
2532 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2533 goto cant_match;
2535 if (float_color != -1 && float_color != value) goto cant_match;
2536 if (srgb && value) goto cant_match;
2537 float_color = value;
2538 break;
2540 case WGL_COLOR_BITS_ARB:
2541 if (color_bits < value) color_bits = value;
2542 break;
2544 case WGL_RED_BITS_ARB:
2545 if (srgb && value > 8) goto cant_match;
2546 if (red_bits < value) red_bits = value;
2547 break;
2549 case WGL_GREEN_BITS_ARB:
2550 if (srgb && value > 8) goto cant_match;
2551 if (green_bits < value) green_bits = value;
2552 break;
2554 case WGL_BLUE_BITS_ARB:
2555 if (srgb && value > 8) goto cant_match;
2556 if (blue_bits < value) blue_bits = value;
2557 break;
2559 case WGL_ALPHA_BITS_ARB:
2560 if (alpha_bits < value) alpha_bits = value;
2561 break;
2563 case WGL_ACCUM_BITS_ARB:
2564 if (accum_bits < value) accum_bits = value;
2565 break;
2567 case WGL_ACCUM_RED_BITS_ARB:
2568 if (accum_red_bits < value) accum_red_bits = value;
2569 break;
2571 case WGL_ACCUM_GREEN_BITS_ARB:
2572 if (accum_green_bits < value) accum_green_bits = value;
2573 break;
2575 case WGL_ACCUM_BLUE_BITS_ARB:
2576 if (accum_blue_bits < value) accum_blue_bits = value;
2577 break;
2579 case WGL_ACCUM_ALPHA_BITS_ARB:
2580 if (accum_alpha_bits < value) accum_alpha_bits = value;
2581 break;
2583 case WGL_DEPTH_BITS_ARB:
2584 if (value > 255) goto cant_match;
2585 if (pf.depth_bits < value) pf.depth_bits = value;
2586 break;
2588 case WGL_STENCIL_BITS_ARB:
2589 if (value > 255) goto cant_match;
2590 if (pf.stencil_bits < value) pf.stencil_bits = value;
2591 break;
2593 case WGL_AUX_BUFFERS_ARB:
2594 if (value > 7) goto cant_match;
2595 if (pf.aux_buffers < value) pf.aux_buffers = value;
2596 break;
2598 case WGL_SAMPLE_BUFFERS_ARB:
2599 if (value > 1) goto cant_match;
2600 if (pf.sample_buffers < value) pf.sample_buffers = value;
2601 break;
2603 case WGL_SAMPLES_ARB:
2604 if (value > 31) goto cant_match;
2605 if (pf.samples < value) pf.samples = value;
2606 break;
2608 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2609 /* sRGB is only supported for 8-bit integer color components */
2610 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2611 goto cant_match;
2612 srgb = TRUE;
2613 break;
2615 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2616 case WGL_RED_SHIFT_ARB:
2617 case WGL_GREEN_SHIFT_ARB:
2618 case WGL_BLUE_SHIFT_ARB:
2619 case WGL_ALPHA_SHIFT_ARB:
2620 case WGL_TRANSPARENT_ARB:
2621 case WGL_TRANSPARENT_RED_VALUE_ARB:
2622 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2623 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2624 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2625 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2626 /* ignored */
2627 break;
2629 case WGL_DRAW_TO_PBUFFER_ARB:
2630 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2631 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2632 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2633 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2634 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2635 pf.pbuffer = (value != 0);
2636 valid.pbuffer = 1;
2637 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2638 !alpha_bits)
2639 alpha_bits = 1;
2640 break;
2642 default:
2643 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2644 return GL_FALSE;
2648 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",
2649 valid.window ? (pf.window ? "1" : "0") : "?",
2650 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2651 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2652 color_bits,
2653 float_color == -1 ? "?" : float_color ? "f" : "",
2654 red_bits,
2655 green_bits,
2656 blue_bits,
2657 alpha_bits,
2658 (int)srgb,
2659 accum_bits,
2660 accum_red_bits,
2661 accum_green_bits,
2662 accum_blue_bits,
2663 accum_alpha_bits,
2664 pf.depth_bits,
2665 pf.stencil_bits,
2666 pf.aux_buffers,
2667 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2668 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2669 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2670 pf.sample_buffers,
2671 pf.samples);
2673 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2675 const struct color_mode *mode;
2677 if (valid.window && pixel_formats[i].window != pf.window) continue;
2678 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2679 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2680 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2681 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2682 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2684 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2685 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2686 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2687 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2688 if (pixel_formats[i].samples < pf.samples) continue;
2690 mode = &color_modes[pixel_formats[i].color_mode];
2691 /* If the mode doesn't have alpha, check requested color bits against
2692 bits per pixel instead of the mode's color bits. On Windows, color
2693 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2694 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2695 expects that to match such a pixel format, we need to accommodate that. */
2696 if (mode->alpha_bits)
2698 if (mode->color_bits < color_bits)
2699 continue;
2701 else
2703 if (mode->bits_per_pixel < color_bits)
2704 continue;
2706 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2707 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2708 continue;
2709 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2710 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2711 continue;
2713 if (pixel_formats[i].accum_mode)
2715 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2716 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2717 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2718 mode->alpha_bits < accum_alpha_bits)
2719 continue;
2721 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2722 continue;
2724 piFormats[found++] = i + 1;
2725 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2728 cant_match:
2729 *nNumFormats = found;
2731 return TRUE;
2735 /***********************************************************************
2736 * macdrv_wglCreateContextAttribsARB
2738 * WGL_ARB_create_context: wglCreateContextAttribsARB
2740 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2741 struct wgl_context *share_context,
2742 const int *attrib_list)
2744 int format;
2745 struct wgl_context *context;
2746 const int *iptr;
2747 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2748 BOOL core = FALSE;
2749 GLint renderer_id = 0;
2751 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2753 format = get_dc_pixel_format(hdc);
2755 if (!is_valid_pixel_format(format))
2757 ERR("Invalid pixel format %d, expect problems!\n", format);
2758 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2759 return NULL;
2762 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2764 int attr = iptr[0];
2765 int value = iptr[1];
2767 TRACE("%s\n", debugstr_attrib(attr, value));
2769 switch (attr)
2771 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2772 major = value;
2773 break;
2775 case WGL_CONTEXT_MINOR_VERSION_ARB:
2776 minor = value;
2777 break;
2779 case WGL_CONTEXT_LAYER_PLANE_ARB:
2780 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2781 break;
2783 case WGL_CONTEXT_FLAGS_ARB:
2784 flags = value;
2785 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2786 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2787 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2788 break;
2790 case WGL_CONTEXT_PROFILE_MASK_ARB:
2791 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2792 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2794 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2795 SetLastError(ERROR_INVALID_PROFILE_ARB);
2796 return NULL;
2798 profile = value;
2799 break;
2801 case WGL_RENDERER_ID_WINE:
2803 CGLError err;
2804 CGLRendererInfoObj renderer_info;
2805 GLint renderer_count, temp;
2807 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
2808 if (err != kCGLNoError)
2810 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
2811 SetLastError(ERROR_GEN_FAILURE);
2812 return NULL;
2815 value = map_renderer_index(renderer_info, renderer_count, value);
2817 if (value >= renderer_count)
2819 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value, renderer_count);
2820 CGLDestroyRendererInfo(renderer_info);
2821 SetLastError(ERROR_INVALID_PARAMETER);
2822 return NULL;
2825 if (!get_renderer_property(renderer_info, value, kCGLRPRendererID, &temp))
2827 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value);
2828 CGLDestroyRendererInfo(renderer_info);
2829 SetLastError(ERROR_GEN_FAILURE);
2830 return NULL;
2833 CGLDestroyRendererInfo(renderer_info);
2835 if (renderer_id && temp != renderer_id)
2837 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id, temp);
2838 SetLastError(ERROR_INVALID_PARAMETER);
2839 return NULL;
2841 renderer_id = temp;
2842 break;
2845 default:
2846 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2847 SetLastError(ERROR_INVALID_PARAMETER);
2848 return NULL;
2852 if ((major == 3 && (minor == 2 || minor == 3)) ||
2853 (major == 4 && (minor == 0 || minor == 1)))
2855 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2857 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2858 SetLastError(ERROR_INVALID_VERSION_ARB);
2859 return NULL;
2861 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2863 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2864 SetLastError(ERROR_INVALID_PROFILE_ARB);
2865 return NULL;
2867 if (major > gl_info.max_major ||
2868 (major == gl_info.max_major && minor > gl_info.max_minor))
2870 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2871 major, minor);
2872 SetLastError(ERROR_INVALID_PROFILE_ARB);
2873 return NULL;
2875 core = TRUE;
2877 else if (major >= 3)
2879 WARN("Profile version %u.%u not supported\n", major, minor);
2880 SetLastError(ERROR_INVALID_VERSION_ARB);
2881 return NULL;
2883 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2884 (major == 2 && (minor < 0 || minor > 1)))
2886 WARN("Invalid GL version requested\n");
2887 SetLastError(ERROR_INVALID_VERSION_ARB);
2888 return NULL;
2890 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2892 WARN("Forward compatible context requested for GL version < 3\n");
2893 SetLastError(ERROR_INVALID_VERSION_ARB);
2894 return NULL;
2897 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2899 context->format = format;
2900 context->renderer_id = renderer_id;
2901 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2903 HeapFree(GetProcessHeap(), 0, context);
2904 return NULL;
2907 EnterCriticalSection(&context_section);
2908 list_add_tail(&context_list, &context->entry);
2909 LeaveCriticalSection(&context_section);
2911 return context;
2915 /**********************************************************************
2916 * macdrv_wglCreatePbufferARB
2918 * WGL_ARB_pbuffer: wglCreatePbufferARB
2920 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2921 const int *piAttribList)
2923 struct wgl_pbuffer* pbuffer;
2924 GLenum target = 0;
2925 GLenum internalFormat = 0;
2926 CGLError err;
2928 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2929 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2931 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2933 WARN("invalid pixel format %d\n", iPixelFormat);
2934 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2935 return NULL;
2938 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2939 pbuffer->format = iPixelFormat;
2941 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2943 int attr = piAttribList[0];
2944 int value = piAttribList[1];
2946 switch (attr)
2948 case WGL_PBUFFER_LARGEST_ARB:
2949 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2950 break;
2952 case WGL_TEXTURE_FORMAT_ARB:
2953 switch (value)
2955 case WGL_TEXTURE_RGBA_ARB:
2956 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2957 internalFormat = GL_RGBA;
2958 break;
2959 case WGL_TEXTURE_RGB_ARB:
2960 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2961 internalFormat = GL_RGB;
2962 break;
2963 case WGL_NO_TEXTURE_ARB:
2964 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2965 internalFormat = 0;
2966 break;
2967 default:
2968 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2969 SetLastError(ERROR_INVALID_DATA);
2970 goto done;
2972 break;
2974 case WGL_TEXTURE_TARGET_ARB:
2975 pbuffer->face = 0;
2976 switch (value)
2978 case WGL_NO_TEXTURE_ARB:
2979 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2980 target = 0;
2981 break;
2982 case WGL_TEXTURE_CUBE_MAP_ARB:
2983 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2984 target = GL_TEXTURE_CUBE_MAP;
2985 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2986 break;
2987 case WGL_TEXTURE_1D_ARB:
2988 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2989 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2990 goto done;
2991 case WGL_TEXTURE_2D_ARB:
2992 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2993 target = GL_TEXTURE_2D;
2994 break;
2995 case WGL_TEXTURE_RECTANGLE_NV:
2996 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2997 target = GL_TEXTURE_RECTANGLE;
2998 break;
2999 default:
3000 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
3001 SetLastError(ERROR_INVALID_DATA);
3002 goto done;
3004 break;
3006 case WGL_MIPMAP_TEXTURE_ARB:
3007 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
3008 pbuffer->max_level = 0;
3009 if (value)
3011 int size = min(iWidth, iHeight) / 2;
3012 while (size)
3014 pbuffer->max_level++;
3015 size /= 2;
3018 break;
3020 default:
3021 WARN("unknown attribute 0x%x\n", attr);
3022 SetLastError(ERROR_INVALID_DATA);
3023 goto done;
3027 if (!target || !internalFormat)
3029 pbuffer->no_texture = TRUE;
3030 /* no actual way to turn off ability to texture; use most permissive target */
3031 target = GL_TEXTURE_RECTANGLE;
3032 internalFormat = GL_RGB;
3035 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
3036 if (err != kCGLNoError)
3038 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
3039 pbuffer->pbuffer = NULL;
3040 if (err == kCGLBadAlloc)
3041 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
3042 else
3043 SetLastError(ERROR_INVALID_DATA);
3046 done:
3047 if (!pbuffer->pbuffer)
3049 HeapFree(GetProcessHeap(), 0, pbuffer);
3050 return NULL;
3053 TRACE(" -> %p\n", pbuffer);
3054 return pbuffer;
3058 /**********************************************************************
3059 * macdrv_wglDestroyPbufferARB
3061 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3063 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
3065 TRACE("pbuffer %p\n", pbuffer);
3066 if (pbuffer && pbuffer->pbuffer)
3067 CGLReleasePBuffer(pbuffer->pbuffer);
3068 HeapFree(GetProcessHeap(), 0, pbuffer);
3069 return GL_TRUE;
3073 /**********************************************************************
3074 * macdrv_wglGetExtensionsStringARB
3076 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3078 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
3080 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3081 this can be specific to the CGL renderer like we're supposed to do. */
3082 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3083 return gl_info.wglExtensions;
3087 /**********************************************************************
3088 * macdrv_wglGetExtensionsStringEXT
3090 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3092 static const char *macdrv_wglGetExtensionsStringEXT(void)
3094 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
3095 return gl_info.wglExtensions;
3099 /**********************************************************************
3100 * macdrv_wglGetPbufferDCARB
3102 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3104 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
3106 HDC hdc;
3107 struct wgl_pbuffer *prev;
3109 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3110 if (!hdc) return 0;
3112 EnterCriticalSection(&dc_pbuffers_section);
3113 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3114 if (prev)
3116 CGLReleasePBuffer(prev->pbuffer);
3117 HeapFree(GetProcessHeap(), 0, prev);
3119 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
3120 LeaveCriticalSection(&dc_pbuffers_section);
3122 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
3123 return hdc;
3127 /**********************************************************************
3128 * macdrv_wglGetPixelFormatAttribivARB
3130 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3132 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3133 UINT nAttributes, const int *piAttributes, int *piValues)
3135 const pixel_format *pf;
3136 UINT i;
3138 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3139 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
3141 if (!nAttributes) return GL_TRUE;
3143 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
3145 piValues[0] = nb_formats;
3146 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
3147 return GL_TRUE;
3150 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
3151 if (!pf)
3153 WARN("invalid pixel format %d\n", iPixelFormat);
3154 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3155 return GL_FALSE;
3158 for (i = 0; i < nAttributes; ++i)
3160 switch (piAttributes[i])
3162 case WGL_NUMBER_PIXEL_FORMATS_ARB:
3163 piValues[i] = nb_formats;
3164 break;
3166 case WGL_DRAW_TO_WINDOW_ARB:
3167 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
3168 break;
3170 case WGL_DRAW_TO_BITMAP_ARB:
3171 piValues[i] = GL_FALSE;
3172 break;
3174 case WGL_ACCELERATION_ARB:
3175 if (iLayerPlane) goto invalid_layer;
3176 if (pf->accelerated)
3177 piValues[i] = WGL_FULL_ACCELERATION_ARB;
3178 else
3179 piValues[i] = WGL_NO_ACCELERATION_ARB;
3180 break;
3182 case WGL_NEED_PALETTE_ARB:
3183 case WGL_NEED_SYSTEM_PALETTE_ARB:
3184 case WGL_SWAP_LAYER_BUFFERS_ARB:
3185 piValues[i] = GL_FALSE;
3186 break;
3188 case WGL_SWAP_METHOD_ARB:
3189 if (pf->double_buffer && pf->backing_store)
3190 piValues[i] = WGL_SWAP_COPY_ARB;
3191 else
3192 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
3193 break;
3195 case WGL_NUMBER_OVERLAYS_ARB:
3196 case WGL_NUMBER_UNDERLAYS_ARB:
3197 piValues[i] = 0;
3198 break;
3200 case WGL_TRANSPARENT_ARB:
3201 if (iLayerPlane) goto invalid_layer;
3202 piValues[i] = GL_FALSE;
3203 break;
3205 case WGL_TRANSPARENT_RED_VALUE_ARB:
3206 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
3207 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
3208 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
3209 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
3210 if (iLayerPlane) goto invalid_layer;
3211 piValues[i] = 0;
3212 break;
3214 case WGL_SHARE_DEPTH_ARB:
3215 case WGL_SHARE_STENCIL_ARB:
3216 case WGL_SHARE_ACCUM_ARB:
3217 if (iLayerPlane) goto invalid_layer;
3218 piValues[i] = GL_TRUE;
3219 break;
3221 case WGL_SUPPORT_GDI_ARB:
3222 if (iLayerPlane) goto invalid_layer;
3223 piValues[i] = GL_FALSE;
3224 break;
3226 case WGL_SUPPORT_OPENGL_ARB:
3227 if (iLayerPlane) goto invalid_layer;
3228 piValues[i] = GL_TRUE;
3229 break;
3231 case WGL_DOUBLE_BUFFER_ARB:
3232 if (iLayerPlane) goto invalid_layer;
3233 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
3234 break;
3236 case WGL_STEREO_ARB:
3237 if (iLayerPlane) goto invalid_layer;
3238 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
3239 break;
3241 case WGL_PIXEL_TYPE_ARB:
3242 if (iLayerPlane) goto invalid_layer;
3243 if (color_modes[pf->color_mode].is_float)
3244 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
3245 else
3246 piValues[i] = WGL_TYPE_RGBA_ARB;
3247 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3248 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3249 However, Mac contexts don't support rendering to unsigned floating-point
3250 formats, even when GL_EXT_packed_float is supported. */
3251 break;
3253 case WGL_COLOR_BITS_ARB:
3254 if (iLayerPlane) goto invalid_layer;
3255 /* If the mode doesn't have alpha, return bits per pixel instead
3256 of color bits. On Windows, color bits sometimes exceeds r+g+b
3257 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3258 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3259 pixel format, we need to accommodate that. */
3260 if (color_modes[pf->color_mode].alpha_bits)
3261 piValues[i] = color_modes[pf->color_mode].color_bits;
3262 else
3263 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
3264 break;
3266 case WGL_RED_BITS_ARB:
3267 if (iLayerPlane) goto invalid_layer;
3268 piValues[i] = color_modes[pf->color_mode].red_bits;
3269 break;
3271 case WGL_RED_SHIFT_ARB:
3272 if (iLayerPlane) goto invalid_layer;
3273 piValues[i] = color_modes[pf->color_mode].red_shift;
3274 break;
3276 case WGL_GREEN_BITS_ARB:
3277 if (iLayerPlane) goto invalid_layer;
3278 piValues[i] = color_modes[pf->color_mode].green_bits;
3279 break;
3281 case WGL_GREEN_SHIFT_ARB:
3282 if (iLayerPlane) goto invalid_layer;
3283 piValues[i] = color_modes[pf->color_mode].green_shift;
3284 break;
3286 case WGL_BLUE_BITS_ARB:
3287 if (iLayerPlane) goto invalid_layer;
3288 piValues[i] = color_modes[pf->color_mode].blue_bits;
3289 break;
3291 case WGL_BLUE_SHIFT_ARB:
3292 if (iLayerPlane) goto invalid_layer;
3293 piValues[i] = color_modes[pf->color_mode].blue_shift;
3294 break;
3296 case WGL_ALPHA_BITS_ARB:
3297 if (iLayerPlane) goto invalid_layer;
3298 piValues[i] = color_modes[pf->color_mode].alpha_bits;
3299 break;
3301 case WGL_ALPHA_SHIFT_ARB:
3302 if (iLayerPlane) goto invalid_layer;
3303 piValues[i] = color_modes[pf->color_mode].alpha_shift;
3304 break;
3306 case WGL_ACCUM_BITS_ARB:
3307 if (iLayerPlane) goto invalid_layer;
3308 if (pf->accum_mode)
3309 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
3310 else
3311 piValues[i] = 0;
3312 break;
3314 case WGL_ACCUM_RED_BITS_ARB:
3315 if (iLayerPlane) goto invalid_layer;
3316 if (pf->accum_mode)
3317 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
3318 else
3319 piValues[i] = 0;
3320 break;
3322 case WGL_ACCUM_GREEN_BITS_ARB:
3323 if (iLayerPlane) goto invalid_layer;
3324 if (pf->accum_mode)
3325 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
3326 else
3327 piValues[i] = 0;
3328 break;
3330 case WGL_ACCUM_BLUE_BITS_ARB:
3331 if (iLayerPlane) goto invalid_layer;
3332 if (pf->accum_mode)
3333 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
3334 else
3335 piValues[i] = 0;
3336 break;
3338 case WGL_ACCUM_ALPHA_BITS_ARB:
3339 if (iLayerPlane) goto invalid_layer;
3340 if (pf->accum_mode)
3341 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
3342 else
3343 piValues[i] = 0;
3344 break;
3346 case WGL_DEPTH_BITS_ARB:
3347 if (iLayerPlane) goto invalid_layer;
3348 piValues[i] = pf->depth_bits;
3349 break;
3351 case WGL_STENCIL_BITS_ARB:
3352 if (iLayerPlane) goto invalid_layer;
3353 piValues[i] = pf->stencil_bits;
3354 break;
3356 case WGL_AUX_BUFFERS_ARB:
3357 if (iLayerPlane) goto invalid_layer;
3358 piValues[i] = pf->aux_buffers;
3359 break;
3361 case WGL_SAMPLE_BUFFERS_ARB:
3362 if (iLayerPlane) goto invalid_layer;
3363 piValues[i] = pf->sample_buffers;
3364 break;
3366 case WGL_SAMPLES_ARB:
3367 if (iLayerPlane) goto invalid_layer;
3368 piValues[i] = pf->samples;
3369 break;
3371 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3372 if (iLayerPlane) goto invalid_layer;
3373 /* sRGB is only supported for 8-bit integer color components */
3374 if (color_modes[pf->color_mode].red_bits == 8 &&
3375 color_modes[pf->color_mode].green_bits == 8 &&
3376 color_modes[pf->color_mode].blue_bits == 8 &&
3377 !color_modes[pf->color_mode].is_float)
3378 piValues[i] = GL_TRUE;
3379 else
3380 piValues[i] = GL_FALSE;
3381 break;
3383 case WGL_DRAW_TO_PBUFFER_ARB:
3384 case WGL_BIND_TO_TEXTURE_RGB_ARB:
3385 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
3386 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
3387 break;
3389 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
3390 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
3391 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
3392 break;
3394 case WGL_MAX_PBUFFER_WIDTH_ARB:
3395 piValues[i] = gl_info.max_viewport_dims[0];
3396 break;
3398 case WGL_MAX_PBUFFER_HEIGHT_ARB:
3399 piValues[i] = gl_info.max_viewport_dims[1];
3400 break;
3402 case WGL_MAX_PBUFFER_PIXELS_ARB:
3403 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
3404 break;
3406 default:
3407 WARN("invalid attribute %x\n", piAttributes[i]);
3408 return GL_FALSE;
3411 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
3414 return GL_TRUE;
3416 invalid_layer:
3417 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
3418 return GL_FALSE;
3422 /**********************************************************************
3423 * macdrv_wglGetPixelFormatAttribfvARB
3425 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3427 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
3428 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
3430 int *attr;
3431 int ret;
3433 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3434 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
3436 /* Allocate a temporary array to store integer values */
3437 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
3438 if (!attr)
3440 ERR("couldn't allocate %d array\n", nAttributes);
3441 return GL_FALSE;
3444 /* Piggy-back on wglGetPixelFormatAttribivARB */
3445 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
3446 if (ret)
3448 UINT i;
3450 /* Convert integer values to float. Should also check for attributes
3451 that can give decimal values here */
3452 for (i = 0; i < nAttributes; i++)
3453 pfValues[i] = attr[i];
3456 HeapFree(GetProcessHeap(), 0, attr);
3457 return ret;
3461 /**********************************************************************
3462 * macdrv_wglGetSwapIntervalEXT
3464 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3466 static int macdrv_wglGetSwapIntervalEXT(void)
3468 struct wgl_context *context = NtCurrentTeb()->glContext;
3469 struct macdrv_win_data *data;
3470 long value;
3471 CGLError err;
3473 TRACE("\n");
3475 if ((data = get_win_data(context->draw_hwnd)))
3477 value = data->swap_interval;
3478 release_win_data(data);
3480 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3481 set_swap_interval(context, value);
3483 else
3485 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3486 if (err != kCGLNoError)
3488 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3489 err, CGLErrorString(err));
3490 value = 1;
3494 return value;
3498 /***********************************************************************
3499 * macdrv_wglMakeContextCurrentARB
3501 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3503 * This is not supported directly by OpenGL on the Mac. We emulate it
3504 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3505 * temporarily swap the drawable. This follows the technique used in
3506 * the implementation of Mesa GLX for Apple.
3508 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3510 struct macdrv_win_data *data;
3511 HWND hwnd;
3513 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3514 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3516 if (!context)
3518 macdrv_make_context_current(NULL, NULL, CGRectNull);
3519 NtCurrentTeb()->glContext = NULL;
3520 return TRUE;
3523 if ((hwnd = WindowFromDC(draw_hdc)))
3525 if (!(data = get_win_data(hwnd)))
3527 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3528 return FALSE;
3531 if (!data->pixel_format)
3533 WARN("no pixel format set\n");
3534 release_win_data(data);
3535 SetLastError(ERROR_INVALID_HANDLE);
3536 return FALSE;
3538 if (context->format != data->pixel_format)
3540 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3541 release_win_data(data);
3542 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3543 return FALSE;
3546 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3547 set_swap_interval(context, data->swap_interval);
3549 context->draw_hwnd = hwnd;
3550 context->draw_view = data->client_cocoa_view;
3551 context->draw_rect = data->client_rect;
3552 OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top);
3553 context->draw_pbuffer = NULL;
3554 release_win_data(data);
3556 else
3558 struct wgl_pbuffer *pbuffer;
3560 EnterCriticalSection(&dc_pbuffers_section);
3561 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3562 if (pbuffer)
3564 if (context->format != pbuffer->format)
3566 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3567 LeaveCriticalSection(&dc_pbuffers_section);
3568 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3569 return FALSE;
3572 if (allow_vsync &&
3573 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3574 set_swap_interval(context, 0);
3576 else
3578 WARN("no window or pbuffer for DC\n");
3579 LeaveCriticalSection(&dc_pbuffers_section);
3580 SetLastError(ERROR_INVALID_HANDLE);
3581 return FALSE;
3584 context->draw_hwnd = NULL;
3585 context->draw_view = NULL;
3586 context->draw_pbuffer = pbuffer;
3587 LeaveCriticalSection(&dc_pbuffers_section);
3590 context->read_view = NULL;
3591 context->read_pbuffer = NULL;
3592 if (read_hdc && read_hdc != draw_hdc)
3594 if ((hwnd = WindowFromDC(read_hdc)))
3596 if ((data = get_win_data(hwnd)))
3598 if (data->client_cocoa_view != context->draw_view)
3600 context->read_view = data->client_cocoa_view;
3601 context->read_rect = data->client_rect;
3602 OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top);
3604 release_win_data(data);
3607 else
3609 EnterCriticalSection(&dc_pbuffers_section);
3610 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3611 LeaveCriticalSection(&dc_pbuffers_section);
3615 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3616 context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
3617 context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
3619 make_context_current(context, FALSE);
3620 context->has_been_current = TRUE;
3621 NtCurrentTeb()->glContext = context;
3623 return TRUE;
3627 /**********************************************************************
3628 * macdrv_wglQueryCurrentRendererIntegerWINE
3630 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3632 static BOOL macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute, GLuint *value)
3634 BOOL ret = FALSE;
3635 struct wgl_context *context = NtCurrentTeb()->glContext;
3636 CGLPixelFormatObj pixel_format;
3637 CGLError err;
3638 GLint virtual_screen;
3639 GLint display_mask;
3640 GLint pf_renderer_id;
3641 CGLRendererInfoObj renderer_info;
3642 GLint renderer_count;
3643 GLint renderer;
3645 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context, (context ? context->context : NULL),
3646 (context ? context->cglcontext : NULL), attribute, value);
3648 if (attribute == WGL_RENDERER_VERSION_WINE)
3650 if (!parse_renderer_version((const char*)opengl_funcs.gl.p_glGetString(GL_VERSION), value))
3651 get_fallback_renderer_version(value);
3652 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value[0], value[1], value[2]);
3653 return TRUE;
3656 pixel_format = CGLGetPixelFormat(context->cglcontext);
3657 err = CGLGetVirtualScreen(context->cglcontext, &virtual_screen);
3658 if (err != kCGLNoError)
3660 WARN("CGLGetVirtualScreen failed: %d %s\n", err, CGLErrorString(err));
3661 return FALSE;
3664 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFADisplayMask, &display_mask);
3665 if (err != kCGLNoError)
3667 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err, CGLErrorString(err));
3668 return FALSE;
3671 err = CGLDescribePixelFormat(pixel_format, virtual_screen, kCGLPFARendererID, &pf_renderer_id);
3672 if (err != kCGLNoError)
3674 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err, CGLErrorString(err));
3675 return FALSE;
3678 err = CGLQueryRendererInfo(display_mask, &renderer_info, &renderer_count);
3679 if (err != kCGLNoError)
3681 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3682 return FALSE;
3685 for (renderer = 0; renderer < renderer_count; renderer++)
3687 GLint renderer_id;
3689 if (!get_renderer_property(renderer_info, renderer, kCGLRPRendererID, &renderer_id))
3690 continue;
3692 if (renderer_id == pf_renderer_id)
3694 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3695 break;
3699 if (renderer >= renderer_count)
3700 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id, display_mask);
3702 CGLDestroyRendererInfo(renderer_info);
3703 return ret;
3707 /**********************************************************************
3708 * macdrv_wglQueryCurrentRendererStringWINE
3710 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3712 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute)
3714 const char* ret = NULL;
3715 struct wgl_context *context = NtCurrentTeb()->glContext;
3717 TRACE("context %p/%p/%p attribute 0x%04x\n", context, (context ? context->context : NULL),
3718 (context ? context->cglcontext : NULL), attribute);
3720 switch (attribute)
3722 case WGL_RENDERER_DEVICE_ID_WINE:
3724 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_RENDERER);
3725 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret));
3726 break;
3729 case WGL_RENDERER_VENDOR_ID_WINE:
3731 ret = (const char*)opengl_funcs.gl.p_glGetString(GL_VENDOR);
3732 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret));
3733 break;
3736 default:
3737 FIXME("unrecognized attribute 0x%04x\n", attribute);
3738 break;
3741 return ret;
3745 /**********************************************************************
3746 * macdrv_wglQueryPbufferARB
3748 * WGL_ARB_pbuffer: wglQueryPbufferARB
3750 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3752 CGLError err;
3753 GLsizei width;
3754 GLsizei height;
3755 GLenum target;
3756 GLenum internalFormat;
3757 GLint mipmap;
3759 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3761 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3762 if (err != kCGLNoError)
3764 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3765 SetLastError(ERROR_INVALID_HANDLE);
3766 return GL_FALSE;
3769 switch (iAttribute)
3771 case WGL_PBUFFER_WIDTH_ARB:
3772 *piValue = width;
3773 break;
3774 case WGL_PBUFFER_HEIGHT_ARB:
3775 *piValue = height;
3776 break;
3777 case WGL_PBUFFER_LOST_ARB:
3778 /* Mac PBuffers can't be lost */
3779 *piValue = GL_FALSE;
3780 break;
3781 case WGL_TEXTURE_FORMAT_ARB:
3782 if (pbuffer->no_texture)
3783 *piValue = WGL_NO_TEXTURE_ARB;
3784 else switch (internalFormat)
3786 case GL_RGBA:
3787 *piValue = WGL_TEXTURE_RGBA_ARB;
3788 break;
3789 case GL_RGB:
3790 default:
3791 *piValue = WGL_TEXTURE_RGB_ARB;
3792 break;
3794 break;
3795 case WGL_TEXTURE_TARGET_ARB:
3796 if (pbuffer->no_texture)
3797 *piValue = WGL_NO_TEXTURE_ARB;
3798 else switch (target)
3800 case GL_TEXTURE_CUBE_MAP:
3801 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3802 break;
3803 case GL_TEXTURE_2D:
3804 *piValue = WGL_TEXTURE_2D_ARB;
3805 break;
3806 case GL_TEXTURE_RECTANGLE:
3807 default:
3808 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3809 break;
3811 break;
3812 case WGL_MIPMAP_TEXTURE_ARB:
3813 *piValue = (pbuffer->max_level > 0);
3814 break;
3815 case WGL_MIPMAP_LEVEL_ARB:
3816 *piValue = pbuffer->level;
3817 break;
3818 case WGL_CUBE_MAP_FACE_ARB:
3819 switch (pbuffer->face)
3821 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3822 default:
3823 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3824 break;
3825 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3826 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3827 break;
3828 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3829 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3830 break;
3831 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3832 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3833 break;
3834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3835 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3836 break;
3837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3838 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3839 break;
3841 break;
3842 default:
3843 WARN("invalid attribute 0x%x\n", iAttribute);
3844 SetLastError(ERROR_INVALID_DATA);
3845 return GL_FALSE;
3848 return GL_TRUE;
3852 /**********************************************************************
3853 * macdrv_wglQueryRendererIntegerWINE
3855 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3857 static BOOL macdrv_wglQueryRendererIntegerWINE(HDC dc, GLint renderer, GLenum attribute, GLuint *value)
3859 BOOL ret = FALSE;
3860 CGLRendererInfoObj renderer_info;
3861 GLint renderer_count;
3862 CGLError err;
3864 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc, renderer, attribute, value);
3866 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3867 if (err != kCGLNoError)
3869 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3870 return FALSE;
3873 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3875 if (renderer < renderer_count)
3876 ret = query_renderer_integer(renderer_info, renderer, attribute, value);
3877 else
3878 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3880 CGLDestroyRendererInfo(renderer_info);
3881 return ret;
3885 /**********************************************************************
3886 * macdrv_wglQueryRendererStringWINE
3888 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3890 static const char *macdrv_wglQueryRendererStringWINE(HDC dc, GLint renderer, GLenum attribute)
3892 const char* ret = NULL;
3893 CGLRendererInfoObj renderer_info;
3894 GLint renderer_count;
3895 CGLError err;
3897 TRACE("dc %p renderer %d attribute 0x%04x\n", dc, renderer, attribute);
3899 err = CGLQueryRendererInfo(active_displays_mask(), &renderer_info, &renderer_count);
3900 if (err != kCGLNoError)
3902 WARN("CGLQueryRendererInfo failed: %d %s\n", err, CGLErrorString(err));
3903 return FALSE;
3906 renderer = map_renderer_index(renderer_info, renderer_count, renderer);
3908 if (renderer >= renderer_count)
3910 TRACE("requested information for renderer %d exceeding count %d\n", renderer, renderer_count);
3911 goto done;
3914 switch (attribute)
3916 case WGL_RENDERER_DEVICE_ID_WINE:
3917 case WGL_RENDERER_VENDOR_ID_WINE:
3919 BOOL device = (attribute == WGL_RENDERER_DEVICE_ID_WINE);
3920 CGLPixelFormatObj pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, TRUE);
3922 if (!pixel_format)
3923 pixel_format = create_pixel_format_for_renderer(renderer_info, renderer, FALSE);
3924 if (pixel_format)
3926 ret = get_gl_string(pixel_format, device ? GL_RENDERER : GL_VENDOR);
3927 CGLReleasePixelFormat(pixel_format);
3930 TRACE("%s -> %s\n", device ? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret));
3931 break;
3934 default:
3935 FIXME("unrecognized attribute 0x%04x\n", attribute);
3936 break;
3939 done:
3940 CGLDestroyRendererInfo(renderer_info);
3941 return ret;
3945 /**********************************************************************
3946 * macdrv_wglReleasePbufferDCARB
3948 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3950 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3952 struct wgl_pbuffer *prev;
3954 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3956 EnterCriticalSection(&dc_pbuffers_section);
3958 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3959 if (prev)
3961 if (prev != pbuffer)
3962 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3963 CGLReleasePBuffer(prev->pbuffer);
3964 HeapFree(GetProcessHeap(), 0, prev);
3965 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3967 else hdc = 0;
3969 LeaveCriticalSection(&dc_pbuffers_section);
3971 return hdc && DeleteDC(hdc);
3975 /**********************************************************************
3976 * macdrv_wglReleaseTexImageARB
3978 * WGL_ARB_render_texture: wglReleaseTexImageARB
3980 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3982 struct wgl_context *context = NtCurrentTeb()->glContext;
3983 CGLError err;
3985 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3987 if (pbuffer->no_texture)
3989 SetLastError(ERROR_INVALID_OPERATION);
3990 return GL_FALSE;
3993 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3994 if (err != kCGLNoError)
3996 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3997 SetLastError(ERROR_INVALID_OPERATION);
3998 return GL_FALSE;
4001 return GL_TRUE;
4005 /**********************************************************************
4006 * macdrv_wglSetPbufferAttribARB
4008 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4010 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
4012 struct wgl_context *context = NtCurrentTeb()->glContext;
4014 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
4016 for ( ; piAttribList && *piAttribList; piAttribList += 2)
4018 int attr = piAttribList[0];
4019 int value = piAttribList[1];
4020 switch (attr)
4022 case WGL_MIPMAP_LEVEL_ARB:
4023 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
4024 pbuffer->level = value;
4025 break;
4026 case WGL_CUBE_MAP_FACE_ARB:
4027 switch (value)
4029 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
4030 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4031 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
4032 break;
4033 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
4034 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4035 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
4036 break;
4037 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
4038 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4039 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
4040 break;
4041 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
4042 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4043 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
4044 break;
4045 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
4046 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4047 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
4048 break;
4049 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
4050 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4051 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
4052 break;
4053 default:
4054 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
4055 SetLastError(ERROR_INVALID_DATA);
4056 return GL_FALSE;
4058 break;
4059 default:
4060 WARN("invalid attribute 0x%x\n", attr);
4061 SetLastError(ERROR_INVALID_DATA);
4062 return GL_FALSE;
4066 if (context && context->draw_pbuffer == pbuffer)
4067 make_context_current(context, FALSE);
4069 return GL_TRUE;
4073 /**********************************************************************
4074 * macdrv_wglSetPixelFormatWINE
4076 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4078 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
4080 return set_pixel_format(hdc, fmt, TRUE);
4084 /**********************************************************************
4085 * macdrv_wglSwapIntervalEXT
4087 * WGL_EXT_swap_control: wglSwapIntervalEXT
4089 static BOOL macdrv_wglSwapIntervalEXT(int interval)
4091 struct wgl_context *context = NtCurrentTeb()->glContext;
4092 BOOL changed = FALSE;
4094 TRACE("interval %d\n", interval);
4096 if (interval < 0)
4098 SetLastError(ERROR_INVALID_DATA);
4099 return FALSE;
4101 if (interval > 1)
4102 interval = 1;
4104 if (context->draw_hwnd)
4106 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
4107 if (data)
4109 changed = data->swap_interval != interval;
4110 if (changed)
4111 data->swap_interval = interval;
4112 release_win_data(data);
4115 else /* pbuffer */
4116 interval = 0;
4118 InterlockedExchange(&context->update_swap_interval, FALSE);
4119 if (!set_swap_interval(context, interval))
4121 SetLastError(ERROR_GEN_FAILURE);
4122 return FALSE;
4125 if (changed)
4127 struct wgl_context *ctx;
4129 EnterCriticalSection(&context_section);
4130 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
4132 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
4133 InterlockedExchange(&context->update_swap_interval, TRUE);
4135 LeaveCriticalSection(&context_section);
4138 return TRUE;
4142 static void register_extension(const char *ext)
4144 if (gl_info.wglExtensions[0])
4145 strcat(gl_info.wglExtensions, " ");
4146 strcat(gl_info.wglExtensions, ext);
4148 TRACE("'%s'\n", ext);
4151 static void load_extensions(void)
4154 * ARB Extensions
4156 register_extension("WGL_ARB_extensions_string");
4157 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
4159 register_extension("WGL_ARB_make_current_read");
4160 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
4161 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
4163 register_extension("WGL_ARB_pixel_format");
4164 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
4165 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
4166 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
4168 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
4170 register_extension("WGL_ARB_pixel_format_float");
4171 register_extension("WGL_ATI_pixel_format_float");
4174 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
4175 register_extension("WGL_ARB_multisample");
4177 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4178 register_extension("WGL_ARB_framebuffer_sRGB");
4180 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
4182 register_extension("WGL_ARB_pbuffer");
4183 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
4184 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
4185 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
4186 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
4187 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
4189 register_extension("WGL_ARB_render_texture");
4190 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
4191 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
4192 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
4194 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
4195 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
4196 register_extension("WGL_NV_render_texture_rectangle");
4199 register_extension("WGL_ARB_create_context");
4200 register_extension("WGL_ARB_create_context_profile");
4201 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
4204 * EXT Extensions
4206 register_extension("WGL_EXT_extensions_string");
4207 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
4209 if (allow_vsync)
4211 register_extension("WGL_EXT_swap_control");
4212 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
4213 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
4216 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4217 check for either, so register them separately. */
4218 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
4219 register_extension("WGL_EXT_framebuffer_sRGB");
4221 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
4222 register_extension("WGL_EXT_pixel_format_packed_float");
4225 * WINE-specific WGL Extensions
4228 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4229 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4231 register_extension("WGL_WINE_pixel_format_passthrough");
4232 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
4234 register_extension("WGL_WINE_query_renderer");
4235 opengl_funcs.ext.p_wglQueryCurrentRendererIntegerWINE = macdrv_wglQueryCurrentRendererIntegerWINE;
4236 opengl_funcs.ext.p_wglQueryCurrentRendererStringWINE = macdrv_wglQueryCurrentRendererStringWINE;
4237 opengl_funcs.ext.p_wglQueryRendererIntegerWINE = macdrv_wglQueryRendererIntegerWINE;
4238 opengl_funcs.ext.p_wglQueryRendererStringWINE = macdrv_wglQueryRendererStringWINE;
4242 static BOOL init_opengl(void)
4244 static BOOL init_done = FALSE;
4245 unsigned int i;
4246 char buffer[200];
4248 if (init_done) return (opengl_handle != NULL);
4249 init_done = TRUE;
4251 TRACE("()\n");
4253 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
4254 if (!dc_pbuffers)
4256 WARN("CFDictionaryCreateMutable failed\n");
4257 return FALSE;
4260 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
4261 if (!opengl_handle)
4263 ERR("Failed to load OpenGL: %s\n", buffer);
4264 ERR("OpenGL support is disabled.\n");
4265 return FALSE;
4268 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
4270 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
4272 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
4273 goto failed;
4277 /* redirect some standard OpenGL functions */
4278 #define REDIRECT(func) \
4279 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4280 REDIRECT(glCopyPixels);
4281 REDIRECT(glGetString);
4282 REDIRECT(glReadPixels);
4283 REDIRECT(glViewport);
4284 if (skip_single_buffer_flushes || allow_vsync)
4285 REDIRECT(glFlush);
4286 if (allow_vsync)
4287 REDIRECT(glFinish);
4288 #undef REDIRECT
4290 /* redirect some OpenGL extension functions */
4291 #define REDIRECT(func) \
4292 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4293 REDIRECT(glCopyColorTable);
4294 #undef REDIRECT
4296 if (!init_gl_info())
4297 goto failed;
4299 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
4300 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
4302 load_extensions();
4303 if (!init_pixel_formats())
4304 goto failed;
4306 return TRUE;
4308 failed:
4309 wine_dlclose(opengl_handle, NULL, 0);
4310 opengl_handle = NULL;
4311 return FALSE;
4315 /***********************************************************************
4316 * sync_gl_view
4318 * Synchronize the Mac GL view position with the Windows child window
4319 * position.
4321 void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect)
4323 if (data->client_cocoa_view && data->pixel_format)
4325 RECT old = *old_client_rect, new = data->client_rect;
4327 OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top);
4328 OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top);
4329 if (!EqualRect(&old, &new))
4331 TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view);
4332 mark_contexts_for_moved_view(data->client_cocoa_view);
4338 /**********************************************************************
4339 * macdrv_wglDescribePixelFormat
4341 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
4343 const pixel_format *pf;
4344 const struct color_mode *mode;
4346 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
4348 if (!descr) return nb_displayable_formats;
4349 if (size < sizeof(*descr)) return 0;
4351 if (!(pf = get_pixel_format(fmt, FALSE)))
4352 return 0;
4354 memset(descr, 0, sizeof(*descr));
4355 descr->nSize = sizeof(*descr);
4356 descr->nVersion = 1;
4358 descr->dwFlags = PFD_SUPPORT_OPENGL;
4359 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
4360 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
4361 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
4362 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
4363 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
4365 descr->iPixelType = PFD_TYPE_RGBA;
4367 mode = &color_modes[pf->color_mode];
4368 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4369 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4370 R8G8B8A0 pixel format). If an app depends on that and expects that
4371 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4372 if (mode->alpha_bits)
4373 descr->cColorBits = mode->color_bits;
4374 else
4375 descr->cColorBits = mode->bits_per_pixel;
4376 descr->cRedBits = mode->red_bits;
4377 descr->cRedShift = mode->red_shift;
4378 descr->cGreenBits = mode->green_bits;
4379 descr->cGreenShift = mode->green_shift;
4380 descr->cBlueBits = mode->blue_bits;
4381 descr->cBlueShift = mode->blue_shift;
4382 descr->cAlphaBits = mode->alpha_bits;
4383 descr->cAlphaShift = mode->alpha_shift;
4385 if (pf->accum_mode)
4387 mode = &color_modes[pf->accum_mode - 1];
4388 descr->cAccumBits = mode->color_bits;
4389 descr->cAccumRedBits = mode->red_bits;
4390 descr->cAccumGreenBits = mode->green_bits;
4391 descr->cAccumBlueBits = mode->blue_bits;
4392 descr->cAccumAlphaBits = mode->alpha_bits;
4395 descr->cDepthBits = pf->depth_bits;
4396 descr->cStencilBits = pf->stencil_bits;
4397 descr->cAuxBuffers = pf->aux_buffers;
4398 descr->iLayerType = PFD_MAIN_PLANE;
4400 TRACE("%s\n", debugstr_pf(pf));
4401 return nb_displayable_formats;
4404 /***********************************************************************
4405 * macdrv_wglCopyContext
4407 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
4409 CGLError err;
4411 TRACE("src %p dst %p mask %x\n", src, dst, mask);
4413 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
4414 if (err != kCGLNoError)
4415 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
4416 return (err == kCGLNoError);
4419 /***********************************************************************
4420 * macdrv_wglCreateContext
4422 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
4424 struct wgl_context *context;
4426 TRACE("hdc %p\n", hdc);
4428 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
4430 return context;
4433 /***********************************************************************
4434 * macdrv_wglDeleteContext
4436 static BOOL macdrv_wglDeleteContext(struct wgl_context *context)
4438 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
4440 EnterCriticalSection(&context_section);
4441 list_remove(&context->entry);
4442 LeaveCriticalSection(&context_section);
4444 macdrv_dispose_opengl_context(context->context);
4445 return HeapFree(GetProcessHeap(), 0, context);
4448 /***********************************************************************
4449 * macdrv_wglGetPixelFormat
4451 static int macdrv_wglGetPixelFormat(HDC hdc)
4453 int format;
4455 format = get_dc_pixel_format(hdc);
4457 if (!is_valid_pixel_format(format)) /* not set yet */
4458 format = 0;
4459 else if (!is_displayable_pixel_format(format))
4461 /* Non-displayable formats can't be used with traditional WGL calls.
4462 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4463 format = 1;
4466 TRACE(" hdc %p -> %d\n", hdc, format);
4467 return format;
4470 /***********************************************************************
4471 * macdrv_wglGetProcAddress
4473 static PROC macdrv_wglGetProcAddress(const char *proc)
4475 void *ret;
4477 if (!strncmp(proc, "wgl", 3)) return NULL;
4478 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
4479 if (ret)
4481 if (TRACE_ON(wgl))
4483 Dl_info info;
4484 if (dladdr(ret, &info))
4485 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
4486 else
4487 TRACE("%s -> %p (no library info)\n", proc, ret);
4490 else
4491 WARN("failed to find proc %s\n", debugstr_a(proc));
4492 return ret;
4495 /***********************************************************************
4496 * macdrv_wglMakeCurrent
4498 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
4500 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4501 (context ? context->cglcontext : NULL));
4503 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
4506 /**********************************************************************
4507 * macdrv_wglSetPixelFormat
4509 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
4511 return set_pixel_format(hdc, fmt, FALSE);
4514 /***********************************************************************
4515 * macdrv_wglShareLists
4517 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
4519 macdrv_opengl_context saved_context;
4520 CGLContextObj saved_cglcontext;
4522 TRACE("org %p dest %p\n", org, dest);
4524 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4525 * at context creation time but in case of WGL it is done using wglShareLists.
4527 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4528 * and when a program requests sharing we recreate the destination context if it hasn't been made
4529 * current or when it hasn't shared display lists before.
4532 if (dest->has_been_current)
4534 WARN("could not share display lists, the destination context has been current already\n");
4535 return FALSE;
4537 else if (dest->sharing)
4539 WARN("could not share display lists because dest has already shared lists before\n");
4540 return FALSE;
4543 /* Re-create the Mac context and share display lists */
4544 saved_context = dest->context;
4545 saved_cglcontext = dest->cglcontext;
4546 dest->context = NULL;
4547 dest->cglcontext = NULL;
4548 if (!create_context(dest, org->cglcontext, dest->major))
4550 dest->context = saved_context;
4551 dest->cglcontext = saved_cglcontext;
4552 return FALSE;
4555 /* Implicitly disposes of saved_cglcontext. */
4556 macdrv_dispose_opengl_context(saved_context);
4558 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4559 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
4561 org->sharing = TRUE;
4562 dest->sharing = TRUE;
4564 return TRUE;
4567 /**********************************************************************
4568 * macdrv_wglSwapBuffers
4570 static BOOL macdrv_wglSwapBuffers(HDC hdc)
4572 struct wgl_context *context = NtCurrentTeb()->glContext;
4573 BOOL match = FALSE;
4574 HWND hwnd;
4576 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
4577 (context ? context->cglcontext : NULL));
4579 if (context)
4581 sync_swap_interval(context);
4582 sync_context(context);
4585 if ((hwnd = WindowFromDC(hdc)))
4587 struct macdrv_win_data *data;
4589 if (!(data = get_win_data(hwnd)))
4591 SetLastError(ERROR_INVALID_HANDLE);
4592 return FALSE;
4595 if (context && context->draw_view == data->client_cocoa_view)
4596 match = TRUE;
4598 release_win_data(data);
4600 else
4602 struct wgl_pbuffer *pbuffer;
4604 EnterCriticalSection(&dc_pbuffers_section);
4605 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
4606 LeaveCriticalSection(&dc_pbuffers_section);
4608 if (!pbuffer)
4610 SetLastError(ERROR_INVALID_HANDLE);
4611 return FALSE;
4614 if (context && context->draw_pbuffer == pbuffer)
4615 match = TRUE;
4618 if (match)
4619 macdrv_flush_opengl_context(context->context);
4620 else
4622 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
4624 /* If there is a current context, then wglSwapBuffers should do an implicit
4625 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4626 in the other branch, but we have to do it explicitly here. */
4627 if (context)
4628 pglFlush();
4631 return TRUE;
4634 static struct opengl_funcs opengl_funcs =
4637 macdrv_wglCopyContext, /* p_wglCopyContext */
4638 macdrv_wglCreateContext, /* p_wglCreateContext */
4639 macdrv_wglDeleteContext, /* p_wglDeleteContext */
4640 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
4641 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
4642 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
4643 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
4644 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
4645 macdrv_wglShareLists, /* p_wglShareLists */
4646 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
4650 /**********************************************************************
4651 * macdrv_wine_get_wgl_driver
4653 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
4655 if (version != WINE_WGL_DRIVER_VERSION)
4657 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
4658 return NULL;
4661 if (!init_opengl()) return (void *)-1;
4663 return &opengl_funcs;