winemac: Make the swap interval a property of the window, not the context.
[wine/multimedia.git] / dlls / winemac.drv / opengl.c
blob825e52325b80904344eb5116ede38dc616713112
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
36 #define __gl_h_
37 #define __gltypes_h_
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
41 #include <dlfcn.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 struct gl_info {
47 char *glVersion;
48 char *glExtensions;
50 char wglExtensions[4096];
52 GLint max_viewport_dims[2];
55 static struct gl_info gl_info;
58 struct wgl_context
60 struct list entry;
61 int format;
62 macdrv_opengl_context context;
63 CGLContextObj cglcontext;
64 HWND draw_hwnd;
65 macdrv_view draw_view;
66 struct wgl_pbuffer *draw_pbuffer;
67 macdrv_view read_view;
68 struct wgl_pbuffer *read_pbuffer;
69 BOOL has_been_current;
70 BOOL sharing;
71 LONG update_swap_interval;
72 DWORD last_flush_time;
75 static struct list context_list = LIST_INIT(context_list);
77 static CRITICAL_SECTION context_section;
78 static CRITICAL_SECTION_DEBUG critsect_debug =
80 0, 0, &context_section,
81 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
82 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
84 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
87 struct wgl_pbuffer
89 CGLPBufferObj pbuffer;
90 int format;
91 BOOL no_texture;
92 int max_level;
93 GLint level;
94 GLenum face;
97 static CFMutableDictionaryRef dc_pbuffers;
99 static CRITICAL_SECTION dc_pbuffers_section;
100 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
102 0, 0, &dc_pbuffers_section,
103 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
104 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
106 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
109 static struct opengl_funcs opengl_funcs;
111 #define USE_GL_FUNC(name) #name,
112 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
113 #undef USE_GL_FUNC
116 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
117 GLsizei width);
118 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
119 static void (*pglFinish)(void);
120 static void (*pglFlush)(void);
121 static void (*pglFlushRenderAPPLE)(void);
122 static const GLubyte *(*pglGetString)(GLenum name);
123 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
124 GLenum format, GLenum type, void *pixels);
125 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
128 struct color_mode {
129 GLint mode;
130 int bits_per_pixel;
131 GLint color_bits; /* including alpha_bits */
132 int red_bits, red_shift;
133 int green_bits, green_shift;
134 int blue_bits, blue_shift;
135 GLint alpha_bits, alpha_shift;
136 BOOL is_float;
137 int color_ordering;
140 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
141 observations of the behavior of Windows systems, but also subjective judgments
142 about what color formats are more "normal" than others.
144 On at least some Windows systems, integer color formats are listed before
145 floating-point formats. Within the integer formats, higher color bits were
146 usually listed before lower color bits, while for floating-point formats it
147 was the reverse. However, that leads D3D to select 64-bit integer formats in
148 preference to 32-bit formats when the latter would be sufficient. It seems
149 that a 32-bit format is much more likely to be normally used in that case.
151 Also, there are certain odd color formats supported on the Mac which seem like
152 they would be less appropriate than more common ones. For instance, the color
153 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
154 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
155 components.
157 For two color formats which differ only in whether or not they have alpha bits,
158 we use the same ordering. pixel_format_comparator() gives alpha bits a
159 different weight than color formats.
161 static const struct color_mode color_modes[] = {
162 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
163 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
164 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
165 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
166 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
167 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
168 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
169 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
170 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
171 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
172 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
173 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
174 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
175 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
176 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
177 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
178 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
179 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
180 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
181 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
182 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
183 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
184 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
185 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
189 static const struct {
190 GLint mode;
191 int bits;
192 } depth_stencil_modes[] = {
193 { kCGL0Bit, 0 },
194 { kCGL1Bit, 1 },
195 { kCGL2Bit, 2 },
196 { kCGL3Bit, 3 },
197 { kCGL4Bit, 4 },
198 { kCGL5Bit, 5 },
199 { kCGL6Bit, 6 },
200 { kCGL8Bit, 8 },
201 { kCGL10Bit, 10 },
202 { kCGL12Bit, 12 },
203 { kCGL16Bit, 16 },
204 { kCGL24Bit, 24 },
205 { kCGL32Bit, 32 },
206 { kCGL48Bit, 48 },
207 { kCGL64Bit, 64 },
208 { kCGL96Bit, 96 },
209 { kCGL128Bit, 128 },
213 typedef struct {
214 GLint renderer_id;
215 GLint buffer_modes;
216 GLint color_modes;
217 GLint accum_modes;
218 GLint depth_modes;
219 GLint stencil_modes;
220 GLint max_aux_buffers;
221 GLint max_sample_buffers;
222 GLint max_samples;
223 BOOL offscreen;
224 BOOL accelerated;
225 BOOL backing_store;
226 BOOL window;
227 BOOL online;
228 } renderer_properties;
231 typedef struct {
232 unsigned int window:1;
233 unsigned int pbuffer:1;
234 unsigned int accelerated:1;
235 unsigned int color_mode:5; /* index into color_modes table */
236 unsigned int aux_buffers:3;
237 unsigned int depth_bits:8;
238 unsigned int stencil_bits:8;
239 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
240 unsigned int double_buffer:1;
241 unsigned int stereo:1;
242 unsigned int sample_buffers:1;
243 unsigned int samples:5;
244 unsigned int backing_store:1;
245 } pixel_format;
248 typedef union
250 pixel_format format;
251 UInt64 code;
252 } pixel_format_or_code;
253 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
256 static pixel_format *pixel_formats;
257 static int nb_formats, nb_displayable_formats;
260 static void *opengl_handle;
263 static const char* debugstr_attrib(int attrib, int value)
265 static const struct {
266 int attrib;
267 const char *name;
268 } attrib_names[] = {
269 #define ATTRIB(a) { a, #a }
270 ATTRIB(WGL_ACCELERATION_ARB),
271 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
272 ATTRIB(WGL_ACCUM_BITS_ARB),
273 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
274 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
275 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
276 ATTRIB(WGL_ALPHA_BITS_ARB),
277 ATTRIB(WGL_ALPHA_SHIFT_ARB),
278 ATTRIB(WGL_AUX_BUFFERS_ARB),
279 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
280 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
281 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
283 ATTRIB(WGL_BLUE_BITS_ARB),
284 ATTRIB(WGL_BLUE_SHIFT_ARB),
285 ATTRIB(WGL_COLOR_BITS_ARB),
286 ATTRIB(WGL_DEPTH_BITS_ARB),
287 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
288 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
289 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
290 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
291 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
292 ATTRIB(WGL_GREEN_BITS_ARB),
293 ATTRIB(WGL_GREEN_SHIFT_ARB),
294 ATTRIB(WGL_NEED_PALETTE_ARB),
295 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
296 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
297 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
298 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
299 ATTRIB(WGL_PIXEL_TYPE_ARB),
300 ATTRIB(WGL_RED_BITS_ARB),
301 ATTRIB(WGL_RED_SHIFT_ARB),
302 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
303 ATTRIB(WGL_SAMPLES_ARB),
304 ATTRIB(WGL_SHARE_ACCUM_ARB),
305 ATTRIB(WGL_SHARE_DEPTH_ARB),
306 ATTRIB(WGL_SHARE_STENCIL_ARB),
307 ATTRIB(WGL_STENCIL_BITS_ARB),
308 ATTRIB(WGL_STEREO_ARB),
309 ATTRIB(WGL_SUPPORT_GDI_ARB),
310 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
311 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
312 ATTRIB(WGL_SWAP_METHOD_ARB),
313 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
314 ATTRIB(WGL_TRANSPARENT_ARB),
315 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
316 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
317 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
318 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
319 #undef ATTRIB
321 int i;
322 const char *attrib_name = NULL;
323 const char *value_name = NULL;
325 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
327 if (attrib_names[i].attrib == attrib)
329 attrib_name = attrib_names[i].name;
330 break;
334 if (!attrib_name)
335 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
337 switch (attrib)
339 case WGL_ACCELERATION_ARB:
340 switch (value)
342 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
343 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
344 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
346 break;
347 case WGL_PIXEL_TYPE_ARB:
348 switch (value)
350 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
351 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
352 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
353 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
355 break;
356 case WGL_SWAP_METHOD_ARB:
357 switch (value)
359 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
360 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
361 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
363 break;
366 if (!value_name)
367 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
369 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
373 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
374 CGLRendererProperty property, GLint *value)
376 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
377 if (err != kCGLNoError)
378 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
379 return (err == kCGLNoError);
383 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
385 GLint value;
387 memset(properties, 0, sizeof(*properties));
389 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
390 properties->renderer_id = value & kCGLRendererIDMatchingMask;
392 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
393 properties->buffer_modes = value;
395 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
396 properties->color_modes = value;
398 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
399 properties->accum_modes = value;
401 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
402 properties->depth_modes = value;
404 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
405 properties->stencil_modes = value;
407 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
408 properties->max_aux_buffers = value;
410 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
411 properties->max_sample_buffers = value;
413 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
414 properties->max_samples = value;
416 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
417 properties->offscreen = (value != 0);
419 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
420 properties->accelerated = (value != 0);
422 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
423 properties->backing_store = (value != 0);
425 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
426 properties->window = (value != 0);
428 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
429 properties->online = (value != 0);
433 static void dump_renderer(const renderer_properties* renderer)
435 int i;
437 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
438 TRACE("Buffer modes:\n");
439 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
440 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
441 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
442 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
444 TRACE("Color buffer modes:\n");
445 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
447 if (renderer->color_modes & color_modes[i].mode)
449 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
450 if (color_modes[i].is_float)
451 TRACE(", Float");
452 TRACE("\n");
456 TRACE("Accumulation buffer sizes: { ");
457 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
459 if (renderer->accum_modes & color_modes[i].mode)
460 TRACE("%d, ", color_modes[i].color_bits);
462 TRACE("}\n");
464 TRACE("Depth buffer sizes: { ");
465 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
467 if (renderer->depth_modes & depth_stencil_modes[i].mode)
468 TRACE("%d, ", depth_stencil_modes[i].bits);
470 TRACE("}\n");
472 TRACE("Stencil buffer sizes: { ");
473 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
475 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
476 TRACE("%d, ", depth_stencil_modes[i].bits);
478 TRACE("}\n");
480 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
481 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
482 TRACE("Max. Samples: %d\n", renderer->max_samples);
483 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
484 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
485 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
486 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
487 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
491 static inline UInt64 code_for_pixel_format(const pixel_format* format)
493 pixel_format_or_code pfc;
495 pfc.code = 0;
496 pfc.format = *format;
497 return pfc.code;
501 static inline pixel_format pixel_format_for_code(UInt64 code)
503 pixel_format_or_code pfc;
505 pfc.code = code;
506 return pfc.format;
510 static const char *debugstr_pf(const pixel_format *pf)
512 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",
513 pf->window,
514 pf->pbuffer,
515 pf->accelerated,
516 color_modes[pf->color_mode].color_bits,
517 (color_modes[pf->color_mode].is_float ? "f" : ""),
518 color_modes[pf->color_mode].alpha_bits,
519 pf->depth_bits,
520 pf->stencil_bits,
521 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
522 pf->aux_buffers,
523 pf->backing_store,
524 pf->double_buffer,
525 pf->stereo,
526 pf->sample_buffers,
527 pf->samples,
528 code_for_pixel_format(pf));
532 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
534 int best = -1;
535 int i;
537 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
539 if ((modes & color_modes[i].mode) &&
540 color_modes[i].color_bits >= color_size &&
541 color_modes[i].alpha_bits >= alpha_size &&
542 !color_modes[i].is_float == !color_float)
544 if (best < 0) /* no existing best choice */
545 best = i;
546 else if (color_modes[i].color_bits == color_size &&
547 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
549 /* prefer it over a best which isn't exact or which has a higher bpp */
550 if (color_modes[best].color_bits != color_size ||
551 color_modes[best].alpha_bits != alpha_size ||
552 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
553 best = i;
555 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
556 (color_modes[i].color_bits == color_modes[best].color_bits &&
557 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
558 best = i;
562 if (best < 0)
564 /* Couldn't find a match. Return first one that renderer supports. */
565 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
567 if (modes & color_modes[i].mode)
568 return i;
572 return best;
576 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
578 int best = -1;
579 int i;
581 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
583 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
585 /* Prefer the fewest color bits, then prefer more alpha bits, then
586 prefer more bits per pixel. */
587 if (best < 0)
588 best = i;
589 else if (color_modes[i].color_bits < color_modes[best].color_bits)
590 best = i;
591 else if (color_modes[i].color_bits == color_modes[best].color_bits)
593 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
594 best = i;
595 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
596 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
597 best = i;
602 if (best < 0)
604 /* Couldn't find a match. Return last one that renderer supports. */
605 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
607 if (modes & color_modes[i].mode)
608 return i;
612 return best;
616 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
617 CFMutableSetRef pixel_format_set)
619 CGLPixelFormatAttribute attribs[64] = {
620 kCGLPFAMinimumPolicy,
621 kCGLPFAClosestPolicy,
622 kCGLPFARendererID, renderer.renderer_id,
623 kCGLPFASingleRenderer,
625 int n = 5, n_stack[16], n_stack_idx = -1;
626 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
627 new_pixel_formats = 0;
628 pixel_format request;
629 unsigned int double_buffer;
630 unsigned int accelerated = renderer.accelerated;
632 if (accelerated)
634 attribs[n++] = kCGLPFAAccelerated;
635 attribs[n++] = kCGLPFANoRecovery;
637 else if (!allow_software_rendering)
639 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
640 return;
643 n_stack[++n_stack_idx] = n;
644 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
646 unsigned int aux;
648 n = n_stack[n_stack_idx];
650 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
651 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
652 continue;
654 if (double_buffer)
655 attribs[n++] = kCGLPFADoubleBuffer;
656 memset(&request, 0, sizeof(request));
657 request.accelerated = accelerated;
658 request.double_buffer = double_buffer;
660 /* Don't bother with in-between aux buffers values: either 0 or max. */
661 n_stack[++n_stack_idx] = n;
662 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
664 unsigned int color_mode;
666 n = n_stack[n_stack_idx];
668 attribs[n++] = kCGLPFAAuxBuffers;
669 attribs[n++] = aux;
670 request.aux_buffers = aux;
672 n_stack[++n_stack_idx] = n;
673 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
675 unsigned int depth_mode;
677 n = n_stack[n_stack_idx];
679 if (!(renderer.color_modes & color_modes[color_mode].mode))
680 continue;
682 attribs[n++] = kCGLPFAColorSize;
683 attribs[n++] = color_modes[color_mode].color_bits;
684 attribs[n++] = kCGLPFAAlphaSize;
685 attribs[n++] = color_modes[color_mode].alpha_bits;
686 if (color_modes[color_mode].is_float)
687 attribs[n++] = kCGLPFAColorFloat;
688 request.color_mode = color_mode;
690 n_stack[++n_stack_idx] = n;
691 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
693 unsigned int stencil_mode;
695 n = n_stack[n_stack_idx];
697 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
698 continue;
700 attribs[n++] = kCGLPFADepthSize;
701 attribs[n++] = depth_stencil_modes[depth_mode].bits;
702 request.depth_bits = depth_stencil_modes[depth_mode].bits;
704 n_stack[++n_stack_idx] = n;
705 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
707 unsigned int stereo;
709 n = n_stack[n_stack_idx];
711 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
712 continue;
713 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
714 continue;
716 attribs[n++] = kCGLPFAStencilSize;
717 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
718 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
720 /* FIXME: Could trim search space a bit here depending on GPU.
721 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
722 n_stack[++n_stack_idx] = n;
723 for (stereo = 0; stereo <= 1; stereo++)
725 int accum_mode;
727 n = n_stack[n_stack_idx];
729 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
730 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
731 continue;
733 if (stereo)
734 attribs[n++] = kCGLPFAStereo;
735 request.stereo = stereo;
737 /* Starts at -1 for a 0 accum size */
738 n_stack[++n_stack_idx] = n;
739 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
741 unsigned int target_pass;
743 n = n_stack[n_stack_idx];
745 if (accum_mode >= 0)
747 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
748 continue;
750 attribs[n++] = kCGLPFAAccumSize;
751 attribs[n++] = color_modes[accum_mode].color_bits;
752 request.accum_mode = accum_mode + 1;
754 else
755 request.accum_mode = 0;
757 /* Targets to request are:
758 accelerated: window OR window + pbuffer
759 software: window + pbuffer */
760 n_stack[++n_stack_idx] = n;
761 for (target_pass = 0; target_pass <= accelerated; target_pass++)
763 unsigned int samples, max_samples;
765 n = n_stack[n_stack_idx];
767 attribs[n++] = kCGLPFAWindow;
768 request.window = 1;
770 if (!accelerated || target_pass > 0)
772 attribs[n++] = kCGLPFAPBuffer;
773 request.pbuffer = 1;
775 else
776 request.pbuffer = 0;
778 /* FIXME: Could trim search space a bit here depending on GPU.
779 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
780 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
781 n_stack[++n_stack_idx] = n;
782 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
783 for (samples = 1; samples <= max_samples; samples *= 2)
785 unsigned int backing_store, min_backing_store, max_backing_store;
787 n = n_stack[n_stack_idx];
789 if (samples > 1)
791 attribs[n++] = kCGLPFASampleBuffers;
792 attribs[n++] = renderer.max_sample_buffers;
793 attribs[n++] = kCGLPFASamples;
794 attribs[n++] = samples;
795 request.sample_buffers = renderer.max_sample_buffers;
796 request.samples = samples;
798 else
799 request.sample_buffers = request.samples = 0;
801 if (renderer.backing_store && double_buffer)
803 /* The software renderer seems to always preserve the backing store, whether
804 we ask for it or not. So don't bother not asking for it. */
805 min_backing_store = accelerated ? 0 : 1;
806 max_backing_store = 1;
808 else
809 min_backing_store = max_backing_store = 0;
810 n_stack[++n_stack_idx] = n;
811 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
813 CGLPixelFormatObj pix;
814 GLint virtualScreens;
815 CGLError err;
817 n = n_stack[n_stack_idx];
819 if (backing_store)
820 attribs[n++] = kCGLPFABackingStore;
821 request.backing_store = backing_store;
823 attribs[n] = 0;
825 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
826 if (err == kCGLNoError && pix)
828 pixel_format pf;
829 GLint value, color_size, alpha_size, color_float;
830 UInt64 pf_code;
831 CFNumberRef code_object;
832 BOOL dupe;
834 memset(&pf, 0, sizeof(pf));
836 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
837 pf.accelerated = value;
838 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
839 pf.aux_buffers = value;
840 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
841 pf.depth_bits = value;
842 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
843 pf.double_buffer = value;
844 if (pf.double_buffer &&
845 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
846 pf.backing_store = value;
847 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
848 pf.pbuffer = value;
849 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
850 pf.sample_buffers = value;
851 if (pf.sample_buffers &&
852 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
853 pf.samples = value;
854 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
855 pf.stencil_bits = value;
856 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
857 pf.stereo = value;
858 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
859 pf.window = value;
861 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
862 color_size = 0;
863 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
864 alpha_size = 0;
865 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
866 color_float = 0;
867 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
869 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
870 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
872 CGLReleasePixelFormat(pix);
874 pf_code = code_for_pixel_format(&pf);
876 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
877 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
878 dupe_pixel_formats++;
879 else
881 CFSetAddValue(pixel_format_set, code_object);
882 CFArrayAppendValue(pixel_format_array, code_object);
883 new_pixel_formats++;
885 CFRelease(code_object);
887 if (pf_code == code_for_pixel_format(&request))
888 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
889 else
891 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
892 dupe ? " (duplicate)" : "");
895 else
897 failed_pixel_formats++;
898 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
901 tried_pixel_formats++;
904 n_stack_idx--;
907 n_stack_idx--;
910 n_stack_idx--;
913 n_stack_idx--;
916 n_stack_idx--;
919 n_stack_idx--;
922 n_stack_idx--;
925 n_stack_idx--;
928 n_stack_idx--;
931 n_stack_idx--;
933 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
934 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
935 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
936 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
940 /* The docs for WGL_ARB_pixel_format say:
941 Indices are assigned to pixel formats in the following order:
942 1. Accelerated pixel formats that are displayable
943 2. Accelerated pixel formats that are displayable and which have
944 extended attributes
945 3. Generic pixel formats
946 4. Accelerated pixel formats that are non displayable
948 static int pixel_format_category(pixel_format pf)
950 /* non-displayable */
951 if (!pf.window)
952 return 4;
954 /* non-accelerated a.k.a. software a.k.a. generic */
955 if (!pf.accelerated)
956 return 3;
958 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
959 if (color_modes[pf.color_mode].is_float)
960 return 2;
962 /* accelerated, displayable, no extended attributes */
963 return 1;
967 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
969 CFNumberRef number1 = val1;
970 CFNumberRef number2 = val2;
971 UInt64 code1, code2;
972 pixel_format pf1, pf2;
973 int category1, category2;
975 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
976 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
977 pf1 = pixel_format_for_code(code1);
978 pf2 = pixel_format_for_code(code2);
979 category1 = pixel_format_category(pf1);
980 category2 = pixel_format_category(pf2);
982 if (category1 < category2)
983 return kCFCompareLessThan;
984 if (category1 > category2)
985 return kCFCompareGreaterThan;
987 /* Within a category, sort the "best" formats toward the front since that's
988 what wglChoosePixelFormatARB() has to do. The ordering implemented here
989 matches at least one Windows 7 machine's behavior.
991 /* Accelerated before unaccelerated. */
992 if (pf1.accelerated && !pf2.accelerated)
993 return kCFCompareLessThan;
994 if (!pf1.accelerated && pf2.accelerated)
995 return kCFCompareGreaterThan;
997 /* Explicit color mode ordering. */
998 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
999 return kCFCompareLessThan;
1000 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1001 return kCFCompareGreaterThan;
1003 /* Non-pbuffer-capable before pbuffer-capable. */
1004 if (!pf1.pbuffer && pf2.pbuffer)
1005 return kCFCompareLessThan;
1006 if (pf1.pbuffer && !pf2.pbuffer)
1007 return kCFCompareGreaterThan;
1009 /* Fewer samples before more samples. */
1010 if (pf1.samples < pf2.samples)
1011 return kCFCompareLessThan;
1012 if (pf1.samples > pf2.samples)
1013 return kCFCompareGreaterThan;
1015 /* Monoscopic before stereoscopic. (This is a guess.) */
1016 if (!pf1.stereo && pf2.stereo)
1017 return kCFCompareLessThan;
1018 if (pf1.stereo && !pf2.stereo)
1019 return kCFCompareGreaterThan;
1021 /* Single buffered before double buffered. */
1022 if (!pf1.double_buffer && pf2.double_buffer)
1023 return kCFCompareLessThan;
1024 if (pf1.double_buffer && !pf2.double_buffer)
1025 return kCFCompareGreaterThan;
1027 /* Possibly-optimized double buffering before backing-store-preserving
1028 double buffering. */
1029 if (!pf1.backing_store && pf2.backing_store)
1030 return kCFCompareLessThan;
1031 if (pf1.backing_store && !pf2.backing_store)
1032 return kCFCompareGreaterThan;
1034 /* Bigger depth buffer before smaller depth buffer. */
1035 if (pf1.depth_bits > pf2.depth_bits)
1036 return kCFCompareLessThan;
1037 if (pf1.depth_bits < pf2.depth_bits)
1038 return kCFCompareGreaterThan;
1040 /* Smaller stencil buffer before bigger stencil buffer. */
1041 if (pf1.stencil_bits < pf2.stencil_bits)
1042 return kCFCompareLessThan;
1043 if (pf1.stencil_bits > pf2.stencil_bits)
1044 return kCFCompareGreaterThan;
1046 /* Smaller alpha bits before larger alpha bits. */
1047 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1048 return kCFCompareLessThan;
1049 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1050 return kCFCompareGreaterThan;
1052 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1053 if (pf1.accum_mode)
1055 if (pf2.accum_mode)
1057 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1058 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1059 return kCFCompareLessThan;
1060 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1061 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1062 return kCFCompareGreaterThan;
1064 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1065 return kCFCompareLessThan;
1066 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1067 return kCFCompareGreaterThan;
1069 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1070 return kCFCompareLessThan;
1071 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1072 return kCFCompareGreaterThan;
1074 else
1075 return kCFCompareGreaterThan;
1077 else if (pf2.accum_mode)
1078 return kCFCompareLessThan;
1080 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1081 if (pf1.aux_buffers < pf2.aux_buffers)
1082 return kCFCompareLessThan;
1083 if (pf1.aux_buffers > pf2.aux_buffers)
1084 return kCFCompareGreaterThan;
1086 /* If we get here, arbitrarily sort based on code. */
1087 if (code1 < code2)
1088 return kCFCompareLessThan;
1089 if (code1 > code2)
1090 return kCFCompareGreaterThan;
1091 return kCFCompareEqualTo;
1095 static BOOL init_pixel_formats(void)
1097 BOOL ret = FALSE;
1098 CGLRendererInfoObj renderer_info;
1099 GLint rendererCount;
1100 CGLError err;
1101 CFMutableSetRef pixel_format_set;
1102 CFMutableArrayRef pixel_format_array;
1103 int i;
1104 CFRange range;
1106 TRACE("()\n");
1108 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1109 if (err)
1111 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1112 return FALSE;
1115 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1116 if (!pixel_format_set)
1118 WARN("CFSetCreateMutable failed\n");
1119 CGLDestroyRendererInfo(renderer_info);
1120 return FALSE;
1123 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1124 if (!pixel_format_array)
1126 WARN("CFArrayCreateMutable failed\n");
1127 CFRelease(pixel_format_set);
1128 CGLDestroyRendererInfo(renderer_info);
1129 return FALSE;
1132 for (i = 0; i < rendererCount; i++)
1134 renderer_properties renderer;
1136 get_renderer_properties(renderer_info, i, &renderer);
1137 if (TRACE_ON(wgl))
1139 TRACE("renderer_properties %d:\n", i);
1140 dump_renderer(&renderer);
1143 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1146 CFRelease(pixel_format_set);
1147 CGLDestroyRendererInfo(renderer_info);
1149 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1150 if (range.length)
1152 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1153 if (pixel_formats)
1155 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1156 for (i = 0; i < range.length; i++)
1158 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1159 UInt64 code;
1161 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1162 pixel_formats[i] = pixel_format_for_code(code);
1163 if (pixel_formats[i].window)
1164 nb_displayable_formats++;
1167 nb_formats = range.length;
1168 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1169 ret = TRUE;
1171 else
1172 WARN("failed to allocate pixel format list\n");
1174 else
1175 WARN("got no pixel formats\n");
1177 CFRelease(pixel_format_array);
1178 return ret;
1182 static inline BOOL is_valid_pixel_format(int format)
1184 return format > 0 && format <= nb_formats;
1188 static inline BOOL is_displayable_pixel_format(int format)
1190 return format > 0 && format <= nb_displayable_formats;
1194 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1196 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1197 * format in case of probing the number of pixel formats.
1199 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1201 TRACE("Returning format %d\n", format);
1202 return &pixel_formats[format - 1];
1204 return NULL;
1208 static BOOL init_gl_info(void)
1210 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1211 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1213 CGDirectDisplayID display = CGMainDisplayID();
1214 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1215 CGLPixelFormatAttribute attribs[] = {
1216 kCGLPFADisplayMask, displayMask,
1219 CGLPixelFormatObj pix;
1220 GLint virtualScreens;
1221 CGLError err;
1222 CGLContextObj context;
1223 CGLContextObj old_context = CGLGetCurrentContext();
1224 const char *str;
1225 size_t length;
1227 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1228 if (err != kCGLNoError || !pix)
1230 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1231 return FALSE;
1234 err = CGLCreateContext(pix, NULL, &context);
1235 CGLReleasePixelFormat(pix);
1236 if (err != kCGLNoError || !context)
1238 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1239 return FALSE;
1242 err = CGLSetCurrentContext(context);
1243 if (err != kCGLNoError)
1245 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1246 CGLReleaseContext(context);
1247 return FALSE;
1250 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1251 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1252 strcpy(gl_info.glVersion, str);
1253 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1254 length = strlen(str) + sizeof(legacy_extensions);
1255 if (allow_vsync)
1256 length += strlen(legacy_ext_swap_control);
1257 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1258 strcpy(gl_info.glExtensions, str);
1259 strcat(gl_info.glExtensions, legacy_extensions);
1260 if (allow_vsync)
1261 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1263 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1265 TRACE("GL version : %s\n", gl_info.glVersion);
1266 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1268 CGLSetCurrentContext(old_context);
1269 CGLReleaseContext(context);
1271 return TRUE;
1275 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1277 BOOL ret = TRUE;
1278 *rect = data->client_rect;
1280 if (data->cocoa_window)
1282 if (window)
1283 *window = data->cocoa_window;
1284 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1286 else
1288 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1289 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1290 struct macdrv_win_data *top_data = get_win_data(top);
1292 if (top_data && top_data->cocoa_window)
1294 if (window)
1295 *window = top_data->cocoa_window;
1296 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1297 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1299 else
1300 ret = FALSE;
1302 release_win_data(top_data);
1305 return ret;
1309 /***********************************************************************
1310 * set_win_format
1312 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1314 macdrv_window cocoa_window;
1316 TRACE("hwnd %p format %d\n", data->hwnd, format);
1318 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1320 ERR("no top-level parent with Cocoa window in this process\n");
1321 return FALSE;
1324 if (data->gl_view) macdrv_dispose_view(data->gl_view);
1325 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1327 if (!data->gl_view)
1329 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1330 return FALSE;
1333 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1334 wine_dbgstr_rect(&data->gl_rect));
1336 data->pixel_format = format;
1338 return TRUE;
1342 /**********************************************************************
1343 * set_pixel_format
1345 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1347 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1349 struct macdrv_win_data *data;
1350 const pixel_format *pf;
1351 HWND hwnd = WindowFromDC(hdc);
1352 BOOL ret = FALSE;
1354 TRACE("hdc %p format %d\n", hdc, fmt);
1356 if (!hwnd || hwnd == GetDesktopWindow())
1358 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1359 return FALSE;
1362 if (!(data = get_win_data(hwnd)))
1364 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1365 return FALSE;
1368 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1370 ret = (data->pixel_format == fmt);
1371 goto done;
1374 /* Check if fmt is in our list of supported formats to see if it is supported. */
1375 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1376 if (!pf)
1378 ERR("Invalid pixel format: %d\n", fmt);
1379 goto done;
1382 if (!pf->window)
1384 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1385 goto done;
1388 if (!set_win_format(data, fmt))
1390 WARN("Couldn't set format of the window, returning failure\n");
1391 goto done;
1394 TRACE("pixel format:\n");
1395 TRACE(" window: %u\n", (unsigned int)pf->window);
1396 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1397 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1398 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1399 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1400 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1401 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1402 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1403 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1404 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1405 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1406 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1407 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1408 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1409 ret = TRUE;
1411 done:
1412 release_win_data(data);
1413 if (ret) __wine_set_pixel_format(hwnd, fmt);
1414 return ret;
1418 /**********************************************************************
1419 * set_gl_view_parent
1421 void set_gl_view_parent(HWND hwnd, HWND parent)
1423 struct macdrv_win_data *data;
1425 if (!(data = get_win_data(hwnd))) return;
1427 if (data->gl_view)
1429 macdrv_window cocoa_window;
1431 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1433 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1435 ERR("no top-level parent with Cocoa window in this process\n");
1436 macdrv_dispose_view(data->gl_view);
1437 data->gl_view = NULL;
1438 release_win_data(data);
1439 __wine_set_pixel_format( hwnd, 0 );
1440 return;
1443 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1446 release_win_data(data);
1450 /**********************************************************************
1451 * make_context_current
1453 static void make_context_current(struct wgl_context *context, BOOL read)
1455 macdrv_view view;
1456 struct wgl_pbuffer *pbuffer;
1458 if (read)
1460 view = context->read_view;
1461 pbuffer = context->read_pbuffer;
1463 else
1465 view = context->draw_view;
1466 pbuffer = context->draw_pbuffer;
1469 if (view || !pbuffer)
1470 macdrv_make_context_current(context->context, view);
1471 else
1473 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1474 pbuffer->level, 0);
1475 CGLSetCurrentContext(context->cglcontext);
1480 /**********************************************************************
1481 * set_swap_interval
1483 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1485 CGLError err;
1487 /* In theory, for single-buffered contexts, there's no such thing as a swap
1488 so the swap interval shouldn't matter. But OS X will synchronize flushes
1489 of single-buffered contexts if the interval is set to non-zero. */
1490 if (interval && !pixel_formats[context->format - 1].double_buffer)
1491 interval = 0;
1493 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1494 if (err != kCGLNoError)
1495 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1497 return err == kCGLNoError;
1501 /**********************************************************************
1502 * sync_swap_interval
1504 static void sync_swap_interval(struct wgl_context *context)
1506 struct macdrv_win_data *data;
1508 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) &&
1509 (data = get_win_data(context->draw_hwnd)))
1511 set_swap_interval(context, data->swap_interval);
1512 release_win_data(data);
1517 /**********************************************************************
1518 * macdrv_glCopyColorTable
1520 * Hook into glCopyColorTable as part of the implementation of
1521 * wglMakeContextCurrentARB. If the context has a separate readable,
1522 * temporarily make that current, do glCopyColorTable, and then set it
1523 * back to the drawable. This is modeled after what Mesa GLX's Apple
1524 * implementation does.
1526 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1527 GLsizei width)
1529 struct wgl_context *context = NtCurrentTeb()->glContext;
1531 if (context->read_view || context->read_pbuffer)
1532 make_context_current(context, TRUE);
1534 pglCopyColorTable(target, internalformat, x, y, width);
1536 if (context->read_view || context->read_pbuffer)
1537 make_context_current(context, FALSE);
1541 /**********************************************************************
1542 * macdrv_glCopyPixels
1544 * Hook into glCopyPixels as part of the implementation of
1545 * wglMakeContextCurrentARB. If the context has a separate readable,
1546 * temporarily make that current, do glCopyPixels, and then set it back
1547 * to the drawable. This is modeled after what Mesa GLX's Apple
1548 * implementation does.
1550 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1552 struct wgl_context *context = NtCurrentTeb()->glContext;
1554 if (context->read_view || context->read_pbuffer)
1555 make_context_current(context, TRUE);
1557 pglCopyPixels(x, y, width, height, type);
1559 if (context->read_view || context->read_pbuffer)
1560 make_context_current(context, FALSE);
1564 /**********************************************************************
1565 * macdrv_glFinish
1567 static void macdrv_glFinish(void)
1569 struct wgl_context *context = NtCurrentTeb()->glContext;
1571 sync_swap_interval(context);
1572 pglFinish();
1576 /**********************************************************************
1577 * macdrv_glFlush
1579 static void macdrv_glFlush(void)
1581 struct wgl_context *context = NtCurrentTeb()->glContext;
1583 sync_swap_interval(context);
1585 if (skip_single_buffer_flushes)
1587 const pixel_format *pf = &pixel_formats[context->format - 1];
1588 DWORD now = GetTickCount();
1590 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1591 context->last_flush_time, now);
1592 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1594 TRACE("calling glFlushRenderAPPLE()\n");
1595 pglFlushRenderAPPLE();
1596 return;
1598 else
1600 TRACE("calling glFlush()\n");
1601 context->last_flush_time = now;
1605 pglFlush();
1609 /**********************************************************************
1610 * macdrv_glGetString
1612 * Hook into glGetString in order to return some legacy WGL extensions
1613 * that couldn't be advertised via the standard
1614 * WGL_ARB_extensions_string mechanism. Some programs, especially
1615 * older ones, expect to find certain older extensions, such as
1616 * WGL_EXT_extensions_string itself, in the standard GL extensions
1617 * string, and won't query any other WGL extensions unless they find
1618 * that particular extension there.
1620 static const GLubyte *macdrv_glGetString(GLenum name)
1622 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1623 return (const GLubyte *)gl_info.glExtensions;
1624 else
1625 return pglGetString(name);
1629 /**********************************************************************
1630 * macdrv_glReadPixels
1632 * Hook into glReadPixels as part of the implementation of
1633 * wglMakeContextCurrentARB. If the context has a separate readable,
1634 * temporarily make that current, do glReadPixels, and then set it back
1635 * to the drawable. This is modeled after what Mesa GLX's Apple
1636 * implementation does.
1638 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1639 GLenum format, GLenum type, void *pixels)
1641 struct wgl_context *context = NtCurrentTeb()->glContext;
1643 if (context->read_view || context->read_pbuffer)
1644 make_context_current(context, TRUE);
1646 pglReadPixels(x, y, width, height, format, type, pixels);
1648 if (context->read_view || context->read_pbuffer)
1649 make_context_current(context, FALSE);
1653 /**********************************************************************
1654 * macdrv_glViewport
1656 * Hook into glViewport as an opportunity to update the OpenGL context
1657 * if necessary. This is modeled after what Mesa GLX's Apple
1658 * implementation does.
1660 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1662 struct wgl_context *context = NtCurrentTeb()->glContext;
1664 macdrv_update_opengl_context(context->context);
1665 pglViewport(x, y, width, height);
1669 /***********************************************************************
1670 * macdrv_wglBindTexImageARB
1672 * WGL_ARB_render_texture: wglBindTexImageARB
1674 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1676 struct wgl_context *context = NtCurrentTeb()->glContext;
1677 GLenum source;
1678 CGLError err;
1680 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1682 if (pbuffer->no_texture)
1684 SetLastError(ERROR_INVALID_OPERATION);
1685 return GL_FALSE;
1688 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1689 opengl_funcs.gl.p_glFlush();
1691 switch (iBuffer)
1693 case WGL_FRONT_LEFT_ARB:
1694 if (pixel_formats[pbuffer->format - 1].stereo)
1695 source = GL_FRONT_LEFT;
1696 else
1697 source = GL_FRONT;
1698 break;
1699 case WGL_FRONT_RIGHT_ARB:
1700 source = GL_FRONT_RIGHT;
1701 break;
1702 case WGL_BACK_LEFT_ARB:
1703 if (pixel_formats[pbuffer->format - 1].stereo)
1704 source = GL_BACK_LEFT;
1705 else
1706 source = GL_BACK;
1707 break;
1708 case WGL_BACK_RIGHT_ARB:
1709 source = GL_BACK_RIGHT;
1710 break;
1711 case WGL_AUX0_ARB: source = GL_AUX0; break;
1712 case WGL_AUX1_ARB: source = GL_AUX1; break;
1713 case WGL_AUX2_ARB: source = GL_AUX2; break;
1714 case WGL_AUX3_ARB: source = GL_AUX3; break;
1716 case WGL_AUX4_ARB:
1717 case WGL_AUX5_ARB:
1718 case WGL_AUX6_ARB:
1719 case WGL_AUX7_ARB:
1720 case WGL_AUX8_ARB:
1721 case WGL_AUX9_ARB:
1722 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1723 SetLastError(ERROR_INVALID_DATA);
1724 return GL_FALSE;
1726 default:
1727 WARN("unknown source buffer 0x%x\n", iBuffer);
1728 SetLastError(ERROR_INVALID_DATA);
1729 return GL_FALSE;
1732 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1733 if (err != kCGLNoError)
1735 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1736 SetLastError(ERROR_INVALID_OPERATION);
1737 return GL_FALSE;
1740 return GL_TRUE;
1744 /***********************************************************************
1745 * macdrv_wglChoosePixelFormatARB
1747 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1749 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1750 const FLOAT *pfAttribFList, UINT nMaxFormats,
1751 int *piFormats, UINT *nNumFormats)
1753 pixel_format pf, valid;
1754 const int *iptr;
1755 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1756 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1757 int float_color;
1758 BOOL srgb;
1759 int i, found = 0;
1761 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1762 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1763 if (pfAttribFList)
1764 FIXME("unused pfAttribFList\n");
1766 memset(&pf, 0, sizeof(pf));
1767 memset(&valid, 0, sizeof(valid));
1768 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1769 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1770 float_color = -1;
1771 srgb = FALSE;
1773 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1775 int attr = iptr[0];
1776 int value = iptr[1];
1778 TRACE("%s\n", debugstr_attrib(attr, value));
1780 switch (attr)
1782 case WGL_DRAW_TO_WINDOW_ARB:
1783 if (valid.window && (!pf.window != !value)) goto cant_match;
1784 pf.window = (value != 0);
1785 valid.window = 1;
1786 break;
1788 case WGL_DRAW_TO_BITMAP_ARB:
1789 goto cant_match;
1791 case WGL_ACCELERATION_ARB:
1792 if (value == WGL_FULL_ACCELERATION_ARB)
1793 value = 1;
1794 else if (value == WGL_NO_ACCELERATION_ARB)
1795 value = 0;
1796 else
1797 goto cant_match;
1798 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1799 pf.accelerated = value;
1800 valid.accelerated = 1;
1801 break;
1803 case WGL_NEED_PALETTE_ARB:
1804 case WGL_NEED_SYSTEM_PALETTE_ARB:
1805 case WGL_SWAP_LAYER_BUFFERS_ARB:
1806 if (value) goto cant_match;
1807 break;
1809 case WGL_SWAP_METHOD_ARB:
1810 if (value == WGL_SWAP_COPY_ARB)
1811 value = 1;
1812 else if (value == WGL_SWAP_UNDEFINED_ARB)
1813 value = 0;
1814 else
1815 goto cant_match;
1816 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1817 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1818 pf.backing_store = value;
1819 valid.backing_store = 1;
1820 break;
1822 case WGL_NUMBER_OVERLAYS_ARB:
1823 case WGL_NUMBER_UNDERLAYS_ARB:
1824 if (value) goto cant_match;
1825 break;
1827 case WGL_SHARE_DEPTH_ARB:
1828 case WGL_SHARE_STENCIL_ARB:
1829 case WGL_SHARE_ACCUM_ARB:
1830 /* no effect */
1831 break;
1833 case WGL_SUPPORT_GDI_ARB:
1834 if (value) goto cant_match;
1835 break;
1837 case WGL_SUPPORT_OPENGL_ARB:
1838 if (!value) goto cant_match;
1839 break;
1841 case WGL_DOUBLE_BUFFER_ARB:
1842 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1843 pf.double_buffer = (value != 0);
1844 valid.double_buffer = 1;
1845 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1846 break;
1848 case WGL_STEREO_ARB:
1849 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1850 pf.stereo = (value != 0);
1851 valid.stereo = 1;
1852 break;
1854 case WGL_PIXEL_TYPE_ARB:
1855 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1856 value = 1;
1857 else if (value == WGL_TYPE_RGBA_ARB)
1858 value = 0;
1859 else
1861 /* Mac contexts don't support rendering to unsigned floating
1862 point formats, even if GL_EXT_packed_float is supported.
1863 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1864 goto cant_match;
1866 if (float_color != -1 && float_color != value) goto cant_match;
1867 if (srgb && value) goto cant_match;
1868 float_color = value;
1869 break;
1871 case WGL_COLOR_BITS_ARB:
1872 if (color_bits < value) color_bits = value;
1873 break;
1875 case WGL_RED_BITS_ARB:
1876 if (srgb && value > 8) goto cant_match;
1877 if (red_bits < value) red_bits = value;
1878 break;
1880 case WGL_GREEN_BITS_ARB:
1881 if (srgb && value > 8) goto cant_match;
1882 if (green_bits < value) green_bits = value;
1883 break;
1885 case WGL_BLUE_BITS_ARB:
1886 if (srgb && value > 8) goto cant_match;
1887 if (blue_bits < value) blue_bits = value;
1888 break;
1890 case WGL_ALPHA_BITS_ARB:
1891 if (alpha_bits < value) alpha_bits = value;
1892 break;
1894 case WGL_ACCUM_BITS_ARB:
1895 if (accum_bits < value) accum_bits = value;
1896 break;
1898 case WGL_ACCUM_RED_BITS_ARB:
1899 if (accum_red_bits < value) accum_red_bits = value;
1900 break;
1902 case WGL_ACCUM_GREEN_BITS_ARB:
1903 if (accum_green_bits < value) accum_green_bits = value;
1904 break;
1906 case WGL_ACCUM_BLUE_BITS_ARB:
1907 if (accum_blue_bits < value) accum_blue_bits = value;
1908 break;
1910 case WGL_ACCUM_ALPHA_BITS_ARB:
1911 if (accum_alpha_bits < value) accum_alpha_bits = value;
1912 break;
1914 case WGL_DEPTH_BITS_ARB:
1915 if (value > 255) goto cant_match;
1916 if (pf.depth_bits < value) pf.depth_bits = value;
1917 break;
1919 case WGL_STENCIL_BITS_ARB:
1920 if (value > 255) goto cant_match;
1921 if (pf.stencil_bits < value) pf.stencil_bits = value;
1922 break;
1924 case WGL_AUX_BUFFERS_ARB:
1925 if (value > 7) goto cant_match;
1926 if (pf.aux_buffers < value) pf.aux_buffers = value;
1927 break;
1929 case WGL_SAMPLE_BUFFERS_ARB:
1930 if (value > 1) goto cant_match;
1931 if (pf.sample_buffers < value) pf.sample_buffers = value;
1932 break;
1934 case WGL_SAMPLES_ARB:
1935 if (value > 31) goto cant_match;
1936 if (pf.samples < value) pf.samples = value;
1937 break;
1939 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1940 /* sRGB is only supported for 8-bit integer color components */
1941 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1942 goto cant_match;
1943 srgb = TRUE;
1944 break;
1946 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1947 case WGL_RED_SHIFT_ARB:
1948 case WGL_GREEN_SHIFT_ARB:
1949 case WGL_BLUE_SHIFT_ARB:
1950 case WGL_ALPHA_SHIFT_ARB:
1951 case WGL_TRANSPARENT_ARB:
1952 case WGL_TRANSPARENT_RED_VALUE_ARB:
1953 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1954 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1955 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1956 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1957 /* ignored */
1958 break;
1960 case WGL_DRAW_TO_PBUFFER_ARB:
1961 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1962 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1963 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1964 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1965 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1966 pf.pbuffer = (value != 0);
1967 valid.pbuffer = 1;
1968 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1969 !alpha_bits)
1970 alpha_bits = 1;
1971 break;
1973 default:
1974 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
1975 return GL_FALSE;
1979 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",
1980 valid.window ? (pf.window ? "1" : "0") : "?",
1981 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
1982 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
1983 color_bits,
1984 float_color == -1 ? "?" : float_color ? "f" : "",
1985 red_bits,
1986 green_bits,
1987 blue_bits,
1988 alpha_bits,
1989 (int)srgb,
1990 accum_bits,
1991 accum_red_bits,
1992 accum_green_bits,
1993 accum_blue_bits,
1994 accum_alpha_bits,
1995 pf.depth_bits,
1996 pf.stencil_bits,
1997 pf.aux_buffers,
1998 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
1999 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2000 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2001 pf.sample_buffers,
2002 pf.samples);
2004 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2006 const struct color_mode *mode;
2008 if (valid.window && pixel_formats[i].window != pf.window) continue;
2009 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2010 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2011 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2012 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2013 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2015 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2016 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2017 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2018 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2019 if (pixel_formats[i].samples < pf.samples) continue;
2021 mode = &color_modes[pixel_formats[i].color_mode];
2022 /* If the mode doesn't have alpha, check requested color bits against
2023 bits per pixel instead of the mode's color bits. On Windows, color
2024 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2025 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2026 expects that to match such a pixel format, we need to accommodate that. */
2027 if (mode->alpha_bits)
2029 if (mode->color_bits < color_bits)
2030 continue;
2032 else
2034 if (mode->bits_per_pixel < color_bits)
2035 continue;
2037 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2038 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2039 continue;
2040 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2041 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2042 continue;
2044 if (pixel_formats[i].accum_mode)
2046 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2047 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2048 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2049 mode->alpha_bits < accum_alpha_bits)
2050 continue;
2052 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2053 continue;
2055 piFormats[found++] = i + 1;
2056 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2059 cant_match:
2060 *nNumFormats = found;
2062 return TRUE;
2066 /**********************************************************************
2067 * macdrv_wglCreatePbufferARB
2069 * WGL_ARB_pbuffer: wglCreatePbufferARB
2071 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2072 const int *piAttribList)
2074 struct wgl_pbuffer* pbuffer;
2075 GLenum target = 0;
2076 GLenum internalFormat = 0;
2077 CGLError err;
2079 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2080 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2082 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2084 WARN("invalid pixel format %d\n", iPixelFormat);
2085 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2086 return NULL;
2089 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2090 pbuffer->format = iPixelFormat;
2092 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2094 int attr = piAttribList[0];
2095 int value = piAttribList[1];
2097 switch (attr)
2099 case WGL_PBUFFER_LARGEST_ARB:
2100 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2101 break;
2103 case WGL_TEXTURE_FORMAT_ARB:
2104 switch (value)
2106 case WGL_TEXTURE_RGBA_ARB:
2107 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2108 internalFormat = GL_RGBA;
2109 break;
2110 case WGL_TEXTURE_RGB_ARB:
2111 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2112 internalFormat = GL_RGB;
2113 break;
2114 case WGL_NO_TEXTURE_ARB:
2115 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2116 internalFormat = 0;
2117 break;
2118 default:
2119 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2120 SetLastError(ERROR_INVALID_DATA);
2121 goto done;
2123 break;
2125 case WGL_TEXTURE_TARGET_ARB:
2126 pbuffer->face = 0;
2127 switch (value)
2129 case WGL_NO_TEXTURE_ARB:
2130 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2131 target = 0;
2132 break;
2133 case WGL_TEXTURE_CUBE_MAP_ARB:
2134 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2135 target = GL_TEXTURE_CUBE_MAP;
2136 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2137 break;
2138 case WGL_TEXTURE_1D_ARB:
2139 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2140 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2141 goto done;
2142 case WGL_TEXTURE_2D_ARB:
2143 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2144 target = GL_TEXTURE_2D;
2145 break;
2146 case WGL_TEXTURE_RECTANGLE_NV:
2147 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2148 target = GL_TEXTURE_RECTANGLE;
2149 break;
2150 default:
2151 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2152 SetLastError(ERROR_INVALID_DATA);
2153 goto done;
2155 break;
2157 case WGL_MIPMAP_TEXTURE_ARB:
2158 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2159 pbuffer->max_level = 0;
2160 if (value)
2162 int size = min(iWidth, iHeight) / 2;
2163 while (size)
2165 pbuffer->max_level++;
2166 size /= 2;
2169 break;
2171 default:
2172 WARN("unknown attribute 0x%x\n", attr);
2173 SetLastError(ERROR_INVALID_DATA);
2174 goto done;
2178 if (!target || !internalFormat)
2180 pbuffer->no_texture = TRUE;
2181 /* no actual way to turn off ability to texture; use most permissive target */
2182 target = GL_TEXTURE_RECTANGLE;
2183 internalFormat = GL_RGB;
2186 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2187 if (err != kCGLNoError)
2189 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2190 pbuffer->pbuffer = NULL;
2191 if (err == kCGLBadAlloc)
2192 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2193 else
2194 SetLastError(ERROR_INVALID_DATA);
2197 done:
2198 if (!pbuffer->pbuffer)
2200 HeapFree(GetProcessHeap(), 0, pbuffer);
2201 return NULL;
2204 TRACE(" -> %p\n", pbuffer);
2205 return pbuffer;
2209 /**********************************************************************
2210 * macdrv_wglDestroyPbufferARB
2212 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2214 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2216 TRACE("pbuffer %p\n", pbuffer);
2217 if (pbuffer && pbuffer->pbuffer)
2218 CGLReleasePBuffer(pbuffer->pbuffer);
2219 HeapFree(GetProcessHeap(), 0, pbuffer);
2220 return GL_TRUE;
2224 /**********************************************************************
2225 * macdrv_wglGetExtensionsStringARB
2227 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2229 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2231 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2232 this can be specific to the CGL renderer like we're supposed to do. */
2233 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2234 return gl_info.wglExtensions;
2238 /**********************************************************************
2239 * macdrv_wglGetExtensionsStringEXT
2241 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2243 static const char *macdrv_wglGetExtensionsStringEXT(void)
2245 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2246 return gl_info.wglExtensions;
2250 /**********************************************************************
2251 * macdrv_wglGetPbufferDCARB
2253 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2255 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2257 HDC hdc;
2258 struct wgl_pbuffer *prev;
2260 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2261 if (!hdc) return 0;
2263 EnterCriticalSection(&dc_pbuffers_section);
2264 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2265 if (prev)
2267 CGLReleasePBuffer(prev->pbuffer);
2268 HeapFree(GetProcessHeap(), 0, prev);
2270 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2271 LeaveCriticalSection(&dc_pbuffers_section);
2273 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2274 return hdc;
2278 /**********************************************************************
2279 * macdrv_wglGetPixelFormatAttribivARB
2281 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2283 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2284 UINT nAttributes, const int *piAttributes, int *piValues)
2286 const pixel_format *pf;
2287 UINT i;
2289 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2290 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2292 if (!nAttributes) return GL_TRUE;
2294 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2296 piValues[0] = nb_formats;
2297 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2298 return GL_TRUE;
2301 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2302 if (!pf)
2304 WARN("invalid pixel format %d\n", iPixelFormat);
2305 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2306 return GL_FALSE;
2309 for (i = 0; i < nAttributes; ++i)
2311 switch (piAttributes[i])
2313 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2314 piValues[i] = nb_formats;
2315 break;
2317 case WGL_DRAW_TO_WINDOW_ARB:
2318 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2319 break;
2321 case WGL_DRAW_TO_BITMAP_ARB:
2322 piValues[i] = GL_FALSE;
2323 break;
2325 case WGL_ACCELERATION_ARB:
2326 if (iLayerPlane) goto invalid_layer;
2327 if (pf->accelerated)
2328 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2329 else
2330 piValues[i] = WGL_NO_ACCELERATION_ARB;
2331 break;
2333 case WGL_NEED_PALETTE_ARB:
2334 case WGL_NEED_SYSTEM_PALETTE_ARB:
2335 case WGL_SWAP_LAYER_BUFFERS_ARB:
2336 piValues[i] = GL_FALSE;
2337 break;
2339 case WGL_SWAP_METHOD_ARB:
2340 if (pf->double_buffer && pf->backing_store)
2341 piValues[i] = WGL_SWAP_COPY_ARB;
2342 else
2343 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2344 break;
2346 case WGL_NUMBER_OVERLAYS_ARB:
2347 case WGL_NUMBER_UNDERLAYS_ARB:
2348 piValues[i] = 0;
2349 break;
2351 case WGL_TRANSPARENT_ARB:
2352 if (iLayerPlane) goto invalid_layer;
2353 piValues[i] = GL_FALSE;
2354 break;
2356 case WGL_TRANSPARENT_RED_VALUE_ARB:
2357 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2358 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2359 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2360 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2361 if (iLayerPlane) goto invalid_layer;
2362 piValues[i] = 0;
2363 break;
2365 case WGL_SHARE_DEPTH_ARB:
2366 case WGL_SHARE_STENCIL_ARB:
2367 case WGL_SHARE_ACCUM_ARB:
2368 if (iLayerPlane) goto invalid_layer;
2369 piValues[i] = GL_TRUE;
2370 break;
2372 case WGL_SUPPORT_GDI_ARB:
2373 if (iLayerPlane) goto invalid_layer;
2374 piValues[i] = GL_FALSE;
2375 break;
2377 case WGL_SUPPORT_OPENGL_ARB:
2378 if (iLayerPlane) goto invalid_layer;
2379 piValues[i] = GL_TRUE;
2380 break;
2382 case WGL_DOUBLE_BUFFER_ARB:
2383 if (iLayerPlane) goto invalid_layer;
2384 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2385 break;
2387 case WGL_STEREO_ARB:
2388 if (iLayerPlane) goto invalid_layer;
2389 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2390 break;
2392 case WGL_PIXEL_TYPE_ARB:
2393 if (iLayerPlane) goto invalid_layer;
2394 if (color_modes[pf->color_mode].is_float)
2395 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2396 else
2397 piValues[i] = WGL_TYPE_RGBA_ARB;
2398 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2399 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2400 However, Mac contexts don't support rendering to unsigned floating-point
2401 formats, even when GL_EXT_packed_float is supported. */
2402 break;
2404 case WGL_COLOR_BITS_ARB:
2405 if (iLayerPlane) goto invalid_layer;
2406 /* If the mode doesn't have alpha, return bits per pixel instead
2407 of color bits. On Windows, color bits sometimes exceeds r+g+b
2408 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2409 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2410 pixel format, we need to accommodate that. */
2411 if (color_modes[pf->color_mode].alpha_bits)
2412 piValues[i] = color_modes[pf->color_mode].color_bits;
2413 else
2414 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2415 break;
2417 case WGL_RED_BITS_ARB:
2418 if (iLayerPlane) goto invalid_layer;
2419 piValues[i] = color_modes[pf->color_mode].red_bits;
2420 break;
2422 case WGL_RED_SHIFT_ARB:
2423 if (iLayerPlane) goto invalid_layer;
2424 piValues[i] = color_modes[pf->color_mode].red_shift;
2425 break;
2427 case WGL_GREEN_BITS_ARB:
2428 if (iLayerPlane) goto invalid_layer;
2429 piValues[i] = color_modes[pf->color_mode].green_bits;
2430 break;
2432 case WGL_GREEN_SHIFT_ARB:
2433 if (iLayerPlane) goto invalid_layer;
2434 piValues[i] = color_modes[pf->color_mode].green_shift;
2435 break;
2437 case WGL_BLUE_BITS_ARB:
2438 if (iLayerPlane) goto invalid_layer;
2439 piValues[i] = color_modes[pf->color_mode].blue_bits;
2440 break;
2442 case WGL_BLUE_SHIFT_ARB:
2443 if (iLayerPlane) goto invalid_layer;
2444 piValues[i] = color_modes[pf->color_mode].blue_shift;
2445 break;
2447 case WGL_ALPHA_BITS_ARB:
2448 if (iLayerPlane) goto invalid_layer;
2449 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2450 break;
2452 case WGL_ALPHA_SHIFT_ARB:
2453 if (iLayerPlane) goto invalid_layer;
2454 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2455 break;
2457 case WGL_ACCUM_BITS_ARB:
2458 if (iLayerPlane) goto invalid_layer;
2459 if (pf->accum_mode)
2460 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2461 else
2462 piValues[i] = 0;
2463 break;
2465 case WGL_ACCUM_RED_BITS_ARB:
2466 if (iLayerPlane) goto invalid_layer;
2467 if (pf->accum_mode)
2468 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2469 else
2470 piValues[i] = 0;
2471 break;
2473 case WGL_ACCUM_GREEN_BITS_ARB:
2474 if (iLayerPlane) goto invalid_layer;
2475 if (pf->accum_mode)
2476 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2477 else
2478 piValues[i] = 0;
2479 break;
2481 case WGL_ACCUM_BLUE_BITS_ARB:
2482 if (iLayerPlane) goto invalid_layer;
2483 if (pf->accum_mode)
2484 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2485 else
2486 piValues[i] = 0;
2487 break;
2489 case WGL_ACCUM_ALPHA_BITS_ARB:
2490 if (iLayerPlane) goto invalid_layer;
2491 if (pf->accum_mode)
2492 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2493 else
2494 piValues[i] = 0;
2495 break;
2497 case WGL_DEPTH_BITS_ARB:
2498 if (iLayerPlane) goto invalid_layer;
2499 piValues[i] = pf->depth_bits;
2500 break;
2502 case WGL_STENCIL_BITS_ARB:
2503 if (iLayerPlane) goto invalid_layer;
2504 piValues[i] = pf->stencil_bits;
2505 break;
2507 case WGL_AUX_BUFFERS_ARB:
2508 if (iLayerPlane) goto invalid_layer;
2509 piValues[i] = pf->aux_buffers;
2510 break;
2512 case WGL_SAMPLE_BUFFERS_ARB:
2513 if (iLayerPlane) goto invalid_layer;
2514 piValues[i] = pf->sample_buffers;
2515 break;
2517 case WGL_SAMPLES_ARB:
2518 if (iLayerPlane) goto invalid_layer;
2519 piValues[i] = pf->samples;
2520 break;
2522 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2523 if (iLayerPlane) goto invalid_layer;
2524 /* sRGB is only supported for 8-bit integer color components */
2525 if (color_modes[pf->color_mode].red_bits == 8 &&
2526 color_modes[pf->color_mode].green_bits == 8 &&
2527 color_modes[pf->color_mode].blue_bits == 8 &&
2528 !color_modes[pf->color_mode].is_float)
2529 piValues[i] = GL_TRUE;
2530 else
2531 piValues[i] = GL_FALSE;
2532 break;
2534 case WGL_DRAW_TO_PBUFFER_ARB:
2535 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2536 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2537 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2538 break;
2540 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2541 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2542 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2543 break;
2545 case WGL_MAX_PBUFFER_WIDTH_ARB:
2546 piValues[i] = gl_info.max_viewport_dims[0];
2547 break;
2549 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2550 piValues[i] = gl_info.max_viewport_dims[1];
2551 break;
2553 case WGL_MAX_PBUFFER_PIXELS_ARB:
2554 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2555 break;
2557 default:
2558 WARN("invalid attribute %x\n", piAttributes[i]);
2559 return GL_FALSE;
2562 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2565 return GL_TRUE;
2567 invalid_layer:
2568 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2569 return GL_FALSE;
2573 /**********************************************************************
2574 * macdrv_wglGetPixelFormatAttribfvARB
2576 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2578 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2579 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2581 int *attr;
2582 int ret;
2584 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2585 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2587 /* Allocate a temporary array to store integer values */
2588 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2589 if (!attr)
2591 ERR("couldn't allocate %d array\n", nAttributes);
2592 return GL_FALSE;
2595 /* Piggy-back on wglGetPixelFormatAttribivARB */
2596 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2597 if (ret)
2599 UINT i;
2601 /* Convert integer values to float. Should also check for attributes
2602 that can give decimal values here */
2603 for (i = 0; i < nAttributes; i++)
2604 pfValues[i] = attr[i];
2607 HeapFree(GetProcessHeap(), 0, attr);
2608 return ret;
2612 /**********************************************************************
2613 * macdrv_wglGetSwapIntervalEXT
2615 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2617 static int macdrv_wglGetSwapIntervalEXT(void)
2619 struct wgl_context *context = NtCurrentTeb()->glContext;
2620 struct macdrv_win_data *data;
2621 long value;
2622 CGLError err;
2624 TRACE("\n");
2626 if ((data = get_win_data(context->draw_hwnd)))
2628 value = data->swap_interval;
2629 release_win_data(data);
2631 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
2632 set_swap_interval(context, value);
2634 else
2636 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2637 if (err != kCGLNoError)
2639 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2640 err, CGLErrorString(err));
2641 value = 1;
2645 return value;
2649 /***********************************************************************
2650 * macdrv_wglMakeContextCurrentARB
2652 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2654 * This is not supported directly by OpenGL on the Mac. We emulate it
2655 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2656 * temporarily swap the drawable. This follows the technique used in
2657 * the implementation of Mesa GLX for Apple.
2659 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2661 struct macdrv_win_data *data;
2662 HWND hwnd;
2664 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2665 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2667 if (!context)
2669 macdrv_make_context_current(NULL, NULL);
2670 NtCurrentTeb()->glContext = NULL;
2671 return TRUE;
2674 if ((hwnd = WindowFromDC(draw_hdc)))
2676 if (!(data = get_win_data(hwnd)))
2678 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2679 return FALSE;
2682 if (!data->pixel_format)
2684 WARN("no pixel format set\n");
2685 release_win_data(data);
2686 SetLastError(ERROR_INVALID_HANDLE);
2687 return FALSE;
2689 if (context->format != data->pixel_format)
2691 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2692 release_win_data(data);
2693 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2694 return FALSE;
2697 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
2698 set_swap_interval(context, data->swap_interval);
2700 context->draw_hwnd = hwnd;
2701 context->draw_view = data->gl_view;
2702 context->draw_pbuffer = NULL;
2703 release_win_data(data);
2705 else
2707 struct wgl_pbuffer *pbuffer;
2709 EnterCriticalSection(&dc_pbuffers_section);
2710 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2711 if (pbuffer)
2713 if (context->format != pbuffer->format)
2715 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2716 LeaveCriticalSection(&dc_pbuffers_section);
2717 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2718 return FALSE;
2721 else
2723 WARN("no window or pbuffer for DC\n");
2724 LeaveCriticalSection(&dc_pbuffers_section);
2725 SetLastError(ERROR_INVALID_HANDLE);
2726 return FALSE;
2729 context->draw_hwnd = NULL;
2730 context->draw_view = NULL;
2731 context->draw_pbuffer = pbuffer;
2732 LeaveCriticalSection(&dc_pbuffers_section);
2735 context->read_view = NULL;
2736 context->read_pbuffer = NULL;
2737 if (read_hdc && read_hdc != draw_hdc)
2739 if ((hwnd = WindowFromDC(read_hdc)))
2741 if ((data = get_win_data(hwnd)))
2743 if (data->gl_view != context->draw_view)
2744 context->read_view = data->gl_view;
2745 release_win_data(data);
2748 else
2750 EnterCriticalSection(&dc_pbuffers_section);
2751 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2752 LeaveCriticalSection(&dc_pbuffers_section);
2756 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2757 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2759 make_context_current(context, FALSE);
2760 context->has_been_current = TRUE;
2761 NtCurrentTeb()->glContext = context;
2763 return TRUE;
2767 /**********************************************************************
2768 * macdrv_wglQueryPbufferARB
2770 * WGL_ARB_pbuffer: wglQueryPbufferARB
2772 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2774 CGLError err;
2775 GLsizei width;
2776 GLsizei height;
2777 GLenum target;
2778 GLenum internalFormat;
2779 GLint mipmap;
2781 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2783 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2784 if (err != kCGLNoError)
2786 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2787 SetLastError(ERROR_INVALID_HANDLE);
2788 return GL_FALSE;
2791 switch (iAttribute)
2793 case WGL_PBUFFER_WIDTH_ARB:
2794 *piValue = width;
2795 break;
2796 case WGL_PBUFFER_HEIGHT_ARB:
2797 *piValue = height;
2798 break;
2799 case WGL_PBUFFER_LOST_ARB:
2800 /* Mac PBuffers can't be lost */
2801 *piValue = GL_FALSE;
2802 break;
2803 case WGL_TEXTURE_FORMAT_ARB:
2804 if (pbuffer->no_texture)
2805 *piValue = WGL_NO_TEXTURE_ARB;
2806 else switch (internalFormat)
2808 case GL_RGBA:
2809 *piValue = WGL_TEXTURE_RGBA_ARB;
2810 break;
2811 case GL_RGB:
2812 default:
2813 *piValue = WGL_TEXTURE_RGB_ARB;
2814 break;
2816 break;
2817 case WGL_TEXTURE_TARGET_ARB:
2818 if (pbuffer->no_texture)
2819 *piValue = WGL_NO_TEXTURE_ARB;
2820 else switch (target)
2822 case GL_TEXTURE_CUBE_MAP:
2823 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2824 break;
2825 case GL_TEXTURE_2D:
2826 *piValue = WGL_TEXTURE_2D_ARB;
2827 break;
2828 case GL_TEXTURE_RECTANGLE:
2829 default:
2830 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2831 break;
2833 break;
2834 case WGL_MIPMAP_TEXTURE_ARB:
2835 *piValue = (pbuffer->max_level > 0);
2836 break;
2837 case WGL_MIPMAP_LEVEL_ARB:
2838 *piValue = pbuffer->level;
2839 break;
2840 case WGL_CUBE_MAP_FACE_ARB:
2841 switch (pbuffer->face)
2843 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2844 default:
2845 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2846 break;
2847 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2848 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2849 break;
2850 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2851 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2852 break;
2853 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2854 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2855 break;
2856 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2857 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2858 break;
2859 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2860 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2861 break;
2863 break;
2864 default:
2865 WARN("invalid attribute 0x%x\n", iAttribute);
2866 SetLastError(ERROR_INVALID_DATA);
2867 return GL_FALSE;
2870 return GL_TRUE;
2874 /**********************************************************************
2875 * macdrv_wglReleasePbufferDCARB
2877 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2879 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2881 struct wgl_pbuffer *prev;
2883 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2885 EnterCriticalSection(&dc_pbuffers_section);
2887 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2888 if (prev)
2890 if (prev != pbuffer)
2891 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2892 CGLReleasePBuffer(prev->pbuffer);
2893 HeapFree(GetProcessHeap(), 0, prev);
2894 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2896 else hdc = 0;
2898 LeaveCriticalSection(&dc_pbuffers_section);
2900 return hdc && DeleteDC(hdc);
2904 /**********************************************************************
2905 * macdrv_wglReleaseTexImageARB
2907 * WGL_ARB_render_texture: wglReleaseTexImageARB
2909 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2911 struct wgl_context *context = NtCurrentTeb()->glContext;
2912 CGLError err;
2914 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2916 if (pbuffer->no_texture)
2918 SetLastError(ERROR_INVALID_OPERATION);
2919 return GL_FALSE;
2922 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2923 if (err != kCGLNoError)
2925 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2926 SetLastError(ERROR_INVALID_OPERATION);
2927 return GL_FALSE;
2930 return GL_TRUE;
2934 /**********************************************************************
2935 * macdrv_wglSetPbufferAttribARB
2937 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2939 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2941 struct wgl_context *context = NtCurrentTeb()->glContext;
2943 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2945 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2947 int attr = piAttribList[0];
2948 int value = piAttribList[1];
2949 switch (attr)
2951 case WGL_MIPMAP_LEVEL_ARB:
2952 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2953 pbuffer->level = value;
2954 break;
2955 case WGL_CUBE_MAP_FACE_ARB:
2956 switch (value)
2958 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2959 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2960 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2961 break;
2962 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2963 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2964 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2965 break;
2966 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2967 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2968 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2969 break;
2970 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2971 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2972 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2973 break;
2974 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2975 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2976 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2977 break;
2978 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2979 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2980 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2981 break;
2982 default:
2983 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2984 SetLastError(ERROR_INVALID_DATA);
2985 return GL_FALSE;
2987 break;
2988 default:
2989 WARN("invalide attribute 0x%x\n", attr);
2990 SetLastError(ERROR_INVALID_DATA);
2991 return GL_FALSE;
2995 if (context && context->draw_pbuffer == pbuffer)
2996 make_context_current(context, FALSE);
2998 return GL_TRUE;
3002 /**********************************************************************
3003 * macdrv_wglSetPixelFormatWINE
3005 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3007 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
3009 return set_pixel_format(hdc, fmt, TRUE);
3013 /**********************************************************************
3014 * macdrv_wglSwapIntervalEXT
3016 * WGL_EXT_swap_control: wglSwapIntervalEXT
3018 static BOOL macdrv_wglSwapIntervalEXT(int interval)
3020 struct wgl_context *context = NtCurrentTeb()->glContext;
3021 struct macdrv_win_data *data;
3023 TRACE("interval %d\n", interval);
3025 if (interval < 0)
3027 SetLastError(ERROR_INVALID_DATA);
3028 return FALSE;
3030 if (interval > 1)
3031 interval = 1;
3033 InterlockedExchange(&context->update_swap_interval, FALSE);
3034 if (!set_swap_interval(context, interval))
3036 SetLastError(ERROR_GEN_FAILURE);
3037 return FALSE;
3040 if ((data = get_win_data(context->draw_hwnd)))
3042 BOOL changed = data->swap_interval != interval;
3043 if (changed)
3044 data->swap_interval = interval;
3045 release_win_data(data);
3047 if (changed)
3049 struct wgl_context *ctx;
3051 EnterCriticalSection(&context_section);
3052 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
3054 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
3055 InterlockedExchange(&context->update_swap_interval, TRUE);
3057 LeaveCriticalSection(&context_section);
3061 return TRUE;
3065 static void register_extension(const char *ext)
3067 if (gl_info.wglExtensions[0])
3068 strcat(gl_info.wglExtensions, " ");
3069 strcat(gl_info.wglExtensions, ext);
3071 TRACE("'%s'\n", ext);
3074 static void load_extensions(void)
3077 * ARB Extensions
3079 register_extension("WGL_ARB_extensions_string");
3080 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
3082 register_extension("WGL_ARB_make_current_read");
3083 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
3084 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
3086 register_extension("WGL_ARB_pixel_format");
3087 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
3088 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
3089 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
3091 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
3093 register_extension("WGL_ARB_pixel_format_float");
3094 register_extension("WGL_ATI_pixel_format_float");
3097 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
3098 register_extension("WGL_ARB_multisample");
3100 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3101 register_extension("WGL_ARB_framebuffer_sRGB");
3103 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
3105 register_extension("WGL_ARB_pbuffer");
3106 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3107 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3108 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3109 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3110 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3112 register_extension("WGL_ARB_render_texture");
3113 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3114 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3115 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3117 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3118 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3119 register_extension("WGL_NV_render_texture_rectangle");
3122 /* TODO:
3123 WGL_ARB_create_context: wglCreateContextAttribsARB
3124 WGL_ARB_create_context_profile
3128 * EXT Extensions
3130 register_extension("WGL_EXT_extensions_string");
3131 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3133 if (allow_vsync)
3135 register_extension("WGL_EXT_swap_control");
3136 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3137 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3140 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3141 check for either, so register them separately. */
3142 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3143 register_extension("WGL_EXT_framebuffer_sRGB");
3145 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3146 register_extension("WGL_EXT_pixel_format_packed_float");
3149 * WINE-specific WGL Extensions
3152 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3153 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3155 register_extension("WGL_WINE_pixel_format_passthrough");
3156 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3160 static BOOL init_opengl(void)
3162 static BOOL init_done = FALSE;
3163 unsigned int i;
3164 char buffer[200];
3166 if (init_done) return (opengl_handle != NULL);
3167 init_done = TRUE;
3169 TRACE("()\n");
3171 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3172 if (!dc_pbuffers)
3174 WARN("CFDictionaryCreateMutable failed\n");
3175 return FALSE;
3178 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3179 if (!opengl_handle)
3181 ERR("Failed to load OpenGL: %s\n", buffer);
3182 ERR("OpenGL support is disabled.\n");
3183 return FALSE;
3186 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3188 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3190 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3191 goto failed;
3195 /* redirect some standard OpenGL functions */
3196 #define REDIRECT(func) \
3197 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3198 REDIRECT(glCopyPixels);
3199 REDIRECT(glGetString);
3200 REDIRECT(glReadPixels);
3201 REDIRECT(glViewport);
3202 if (skip_single_buffer_flushes || allow_vsync)
3203 REDIRECT(glFlush);
3204 if (allow_vsync)
3205 REDIRECT(glFinish);
3206 #undef REDIRECT
3208 /* redirect some OpenGL extension functions */
3209 #define REDIRECT(func) \
3210 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3211 REDIRECT(glCopyColorTable);
3212 #undef REDIRECT
3214 if (!init_gl_info())
3215 goto failed;
3217 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3218 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3220 load_extensions();
3221 if (!init_pixel_formats())
3222 goto failed;
3224 return TRUE;
3226 failed:
3227 wine_dlclose(opengl_handle, NULL, 0);
3228 opengl_handle = NULL;
3229 return FALSE;
3233 /***********************************************************************
3234 * sync_gl_view
3236 * Synchronize the Mac GL view position with the Windows child window
3237 * position.
3239 void sync_gl_view(struct macdrv_win_data *data)
3241 RECT rect;
3243 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3245 if (!data->gl_view) return;
3247 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3249 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3250 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3251 data->gl_rect = rect;
3256 static int get_dc_pixel_format(HDC hdc)
3258 int format;
3259 HWND hwnd;
3261 if ((hwnd = WindowFromDC(hdc)))
3263 struct macdrv_win_data *data;
3265 if (!(data = get_win_data(hwnd)))
3267 FIXME("DC for window %p of other process: not implemented\n", hwnd);
3268 return 0;
3271 format = data->pixel_format;
3272 release_win_data(data);
3274 else
3276 struct wgl_pbuffer *pbuffer;
3278 EnterCriticalSection(&dc_pbuffers_section);
3279 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3280 if (pbuffer)
3281 format = pbuffer->format;
3282 else
3284 WARN("no window or pbuffer for DC %p\n", hdc);
3285 format = 0;
3287 LeaveCriticalSection(&dc_pbuffers_section);
3290 return format;
3294 /**********************************************************************
3295 * create_context
3297 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
3299 const pixel_format *pf;
3300 CGLPixelFormatAttribute attribs[64];
3301 int n = 0;
3302 CGLPixelFormatObj pix;
3303 GLint virtualScreens;
3304 CGLError err;
3306 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
3307 if (!pf)
3309 ERR("Invalid pixel format %d, expect problems!\n", context->format);
3310 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3311 return FALSE;
3314 attribs[n++] = kCGLPFAMinimumPolicy;
3315 attribs[n++] = kCGLPFAClosestPolicy;
3317 if (pf->accelerated)
3319 attribs[n++] = kCGLPFAAccelerated;
3320 attribs[n++] = kCGLPFANoRecovery;
3322 else
3324 attribs[n++] = kCGLPFARendererID;
3325 attribs[n++] = kCGLRendererGenericFloatID;
3328 if (pf->double_buffer)
3329 attribs[n++] = kCGLPFADoubleBuffer;
3331 attribs[n++] = kCGLPFAAuxBuffers;
3332 attribs[n++] = pf->aux_buffers;
3334 attribs[n++] = kCGLPFAColorSize;
3335 attribs[n++] = color_modes[pf->color_mode].color_bits;
3336 attribs[n++] = kCGLPFAAlphaSize;
3337 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3338 if (color_modes[pf->color_mode].is_float)
3339 attribs[n++] = kCGLPFAColorFloat;
3341 attribs[n++] = kCGLPFADepthSize;
3342 attribs[n++] = pf->depth_bits;
3344 attribs[n++] = kCGLPFAStencilSize;
3345 attribs[n++] = pf->stencil_bits;
3347 if (pf->stereo)
3348 attribs[n++] = kCGLPFAStereo;
3350 if (pf->accum_mode)
3352 attribs[n++] = kCGLPFAAccumSize;
3353 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3356 if (pf->window)
3357 attribs[n++] = kCGLPFAWindow;
3358 if (pf->pbuffer)
3359 attribs[n++] = kCGLPFAPBuffer;
3361 if (pf->sample_buffers && pf->samples)
3363 attribs[n++] = kCGLPFASampleBuffers;
3364 attribs[n++] = pf->sample_buffers;
3365 attribs[n++] = kCGLPFASamples;
3366 attribs[n++] = pf->samples;
3369 if (pf->backing_store)
3370 attribs[n++] = kCGLPFABackingStore;
3372 attribs[n] = 0;
3374 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3375 if (err != kCGLNoError || !pix)
3377 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3378 return FALSE;
3381 err = CGLCreateContext(pix, share, &context->cglcontext);
3382 CGLReleasePixelFormat(pix);
3383 if (err != kCGLNoError || !context->cglcontext)
3385 context->cglcontext = NULL;
3386 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3387 return FALSE;
3390 context->context = macdrv_create_opengl_context(context->cglcontext);
3391 CGLReleaseContext(context->cglcontext);
3392 if (!context->context)
3394 WARN("macdrv_create_opengl_context() failed\n");
3395 return FALSE;
3398 if (allow_vsync)
3399 InterlockedExchange(&context->update_swap_interval, TRUE);
3401 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3403 return TRUE;
3407 /**********************************************************************
3408 * macdrv_wglDescribePixelFormat
3410 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3412 const pixel_format *pf;
3413 const struct color_mode *mode;
3415 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3417 if (!descr) return nb_displayable_formats;
3418 if (size < sizeof(*descr)) return 0;
3420 if (!(pf = get_pixel_format(fmt, FALSE)))
3421 return 0;
3423 memset(descr, 0, sizeof(*descr));
3424 descr->nSize = sizeof(*descr);
3425 descr->nVersion = 1;
3427 descr->dwFlags = PFD_SUPPORT_OPENGL;
3428 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3429 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3430 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3431 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3432 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3434 descr->iPixelType = PFD_TYPE_RGBA;
3436 mode = &color_modes[pf->color_mode];
3437 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3438 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3439 R8G8B8A0 pixel format). If an app depends on that and expects that
3440 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3441 if (mode->alpha_bits)
3442 descr->cColorBits = mode->color_bits;
3443 else
3444 descr->cColorBits = mode->bits_per_pixel;
3445 descr->cRedBits = mode->red_bits;
3446 descr->cRedShift = mode->red_shift;
3447 descr->cGreenBits = mode->green_bits;
3448 descr->cGreenShift = mode->green_shift;
3449 descr->cBlueBits = mode->blue_bits;
3450 descr->cBlueShift = mode->blue_shift;
3451 descr->cAlphaBits = mode->alpha_bits;
3452 descr->cAlphaShift = mode->alpha_shift;
3454 if (pf->accum_mode)
3456 mode = &color_modes[pf->accum_mode - 1];
3457 descr->cAccumBits = mode->color_bits;
3458 descr->cAccumRedBits = mode->red_bits;
3459 descr->cAccumGreenBits = mode->green_bits;
3460 descr->cAccumBlueBits = mode->blue_bits;
3461 descr->cAccumAlphaBits = mode->alpha_bits;
3464 descr->cDepthBits = pf->depth_bits;
3465 descr->cStencilBits = pf->stencil_bits;
3466 descr->cAuxBuffers = pf->aux_buffers;
3467 descr->iLayerType = PFD_MAIN_PLANE;
3469 TRACE("%s\n", debugstr_pf(pf));
3470 return nb_displayable_formats;
3473 /***********************************************************************
3474 * macdrv_wglCopyContext
3476 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3478 CGLError err;
3480 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3482 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3483 if (err != kCGLNoError)
3484 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3485 return (err == kCGLNoError);
3488 /***********************************************************************
3489 * macdrv_wglCreateContext
3491 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3493 int format;
3494 struct wgl_context *context;
3496 TRACE("hdc %p\n", hdc);
3498 format = get_dc_pixel_format(hdc);
3500 if (!is_valid_pixel_format(format))
3502 ERR("Invalid pixel format %d, expect problems!\n", format);
3503 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3504 return NULL;
3507 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3509 context->format = format;
3510 if (!create_context(context, NULL))
3512 HeapFree(GetProcessHeap(), 0, context);
3513 return NULL;
3516 EnterCriticalSection(&context_section);
3517 list_add_tail(&context_list, &context->entry);
3518 LeaveCriticalSection(&context_section);
3520 return context;
3523 /***********************************************************************
3524 * macdrv_wglDeleteContext
3526 static void macdrv_wglDeleteContext(struct wgl_context *context)
3528 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3530 EnterCriticalSection(&context_section);
3531 list_remove(&context->entry);
3532 LeaveCriticalSection(&context_section);
3534 macdrv_dispose_opengl_context(context->context);
3535 HeapFree(GetProcessHeap(), 0, context);
3538 /***********************************************************************
3539 * macdrv_wglGetPixelFormat
3541 static int macdrv_wglGetPixelFormat(HDC hdc)
3543 int format;
3545 format = get_dc_pixel_format(hdc);
3547 if (!is_valid_pixel_format(format)) /* not set yet */
3548 format = 0;
3549 else if (!is_displayable_pixel_format(format))
3551 /* Non-displayable formats can't be used with traditional WGL calls.
3552 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3553 format = 1;
3556 TRACE(" hdc %p -> %d\n", hdc, format);
3557 return format;
3560 /***********************************************************************
3561 * macdrv_wglGetProcAddress
3563 static PROC macdrv_wglGetProcAddress(const char *proc)
3565 void *ret;
3567 if (!strncmp(proc, "wgl", 3)) return NULL;
3568 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3569 if (ret)
3571 if (TRACE_ON(wgl))
3573 Dl_info info;
3574 if (dladdr(ret, &info))
3575 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3576 else
3577 TRACE("%s -> %p (no library info)\n", proc, ret);
3580 else
3581 WARN("failed to find proc %s\n", debugstr_a(proc));
3582 return ret;
3585 /***********************************************************************
3586 * macdrv_wglMakeCurrent
3588 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3590 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3591 (context ? context->cglcontext : NULL));
3593 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3596 /**********************************************************************
3597 * macdrv_wglSetPixelFormat
3599 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3601 return set_pixel_format(hdc, fmt, FALSE);
3604 /***********************************************************************
3605 * macdrv_wglShareLists
3607 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3609 macdrv_opengl_context saved_context;
3610 CGLContextObj saved_cglcontext;
3612 TRACE("org %p dest %p\n", org, dest);
3614 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3615 * at context creation time but in case of WGL it is done using wglShareLists.
3617 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3618 * and when a program requests sharing we recreate the destination context if it hasn't been made
3619 * current or when it hasn't shared display lists before.
3622 if (dest->has_been_current)
3624 WARN("could not share display lists, the destination context has been current already\n");
3625 return FALSE;
3627 else if (dest->sharing)
3629 WARN("could not share display lists because dest has already shared lists before\n");
3630 return FALSE;
3633 /* Re-create the Mac context and share display lists */
3634 saved_context = dest->context;
3635 saved_cglcontext = dest->cglcontext;
3636 dest->context = NULL;
3637 dest->cglcontext = NULL;
3638 if (!create_context(dest, org->cglcontext))
3640 dest->context = saved_context;
3641 dest->cglcontext = saved_cglcontext;
3642 return FALSE;
3645 /* Implicitly disposes of saved_cglcontext. */
3646 macdrv_dispose_opengl_context(saved_context);
3648 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3649 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3651 org->sharing = TRUE;
3652 dest->sharing = TRUE;
3654 return TRUE;
3657 /**********************************************************************
3658 * macdrv_wglSwapBuffers
3660 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3662 struct wgl_context *context = NtCurrentTeb()->glContext;
3663 BOOL match = FALSE;
3664 HWND hwnd;
3666 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3667 (context ? context->cglcontext : NULL));
3669 if (context)
3670 sync_swap_interval(context);
3672 if ((hwnd = WindowFromDC(hdc)))
3674 struct macdrv_win_data *data;
3676 if (!(data = get_win_data(hwnd)))
3678 SetLastError(ERROR_INVALID_HANDLE);
3679 return FALSE;
3682 if (context && context->draw_view == data->gl_view)
3683 match = TRUE;
3685 release_win_data(data);
3687 else
3689 struct wgl_pbuffer *pbuffer;
3691 EnterCriticalSection(&dc_pbuffers_section);
3692 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3693 LeaveCriticalSection(&dc_pbuffers_section);
3695 if (!pbuffer)
3697 SetLastError(ERROR_INVALID_HANDLE);
3698 return FALSE;
3701 if (context && context->draw_pbuffer == pbuffer)
3702 match = TRUE;
3705 if (match)
3706 macdrv_flush_opengl_context(context->context);
3707 else
3709 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3711 /* If there is a current context, then wglSwapBuffers should do an implicit
3712 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3713 in the other branch, but we have to do it explicitly here. */
3714 if (context)
3715 pglFlush();
3718 return TRUE;
3721 static struct opengl_funcs opengl_funcs =
3724 macdrv_wglCopyContext, /* p_wglCopyContext */
3725 macdrv_wglCreateContext, /* p_wglCreateContext */
3726 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3727 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3728 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3729 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3730 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3731 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3732 macdrv_wglShareLists, /* p_wglShareLists */
3733 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3737 /**********************************************************************
3738 * macdrv_wine_get_wgl_driver
3740 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3742 if (version != WINE_WGL_DRIVER_VERSION)
3744 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3745 return NULL;
3748 if (!init_opengl()) return (void *)-1;
3750 return &opengl_funcs;