dwrite: Break out basic IDWriteFont creation from requiring a logfont.
[wine/multimedia.git] / dlls / winemac.drv / opengl.c
blob01878221cf09f3455ce1ee11313b4f25530640bd
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 TRACE("hwnd %p format %d\n", data->hwnd, format);
1316 if (!data->gl_view)
1318 macdrv_window cocoa_window;
1320 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1322 ERR("no top-level parent with Cocoa window in this process\n");
1323 return FALSE;
1326 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));
1337 data->pixel_format = format;
1339 return TRUE;
1343 /**********************************************************************
1344 * set_pixel_format
1346 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1348 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1350 struct macdrv_win_data *data;
1351 const pixel_format *pf;
1352 HWND hwnd = WindowFromDC(hdc);
1353 BOOL ret = FALSE;
1355 TRACE("hdc %p format %d\n", hdc, fmt);
1357 if (!hwnd || hwnd == GetDesktopWindow())
1359 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1360 return FALSE;
1363 if (!(data = get_win_data(hwnd)))
1365 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1366 return FALSE;
1369 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1371 ret = (data->pixel_format == fmt);
1372 goto done;
1375 /* Check if fmt is in our list of supported formats to see if it is supported. */
1376 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1377 if (!pf)
1379 ERR("Invalid pixel format: %d\n", fmt);
1380 goto done;
1383 if (!pf->window)
1385 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1386 goto done;
1389 if (!set_win_format(data, fmt))
1391 WARN("Couldn't set format of the window, returning failure\n");
1392 goto done;
1395 TRACE("pixel format:\n");
1396 TRACE(" window: %u\n", (unsigned int)pf->window);
1397 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1398 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1399 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1400 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1401 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1402 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1403 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1404 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1405 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1406 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1407 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1408 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1409 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1410 ret = TRUE;
1412 done:
1413 release_win_data(data);
1414 if (ret) __wine_set_pixel_format(hwnd, fmt);
1415 return ret;
1419 /**********************************************************************
1420 * set_gl_view_parent
1422 void set_gl_view_parent(HWND hwnd, HWND parent)
1424 struct macdrv_win_data *data;
1426 if (!(data = get_win_data(hwnd))) return;
1428 if (data->gl_view)
1430 macdrv_window cocoa_window;
1432 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1434 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1436 ERR("no top-level parent with Cocoa window in this process\n");
1437 macdrv_dispose_view(data->gl_view);
1438 data->gl_view = NULL;
1439 release_win_data(data);
1440 __wine_set_pixel_format( hwnd, 0 );
1441 return;
1444 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1447 release_win_data(data);
1451 /**********************************************************************
1452 * make_context_current
1454 static void make_context_current(struct wgl_context *context, BOOL read)
1456 macdrv_view view;
1457 struct wgl_pbuffer *pbuffer;
1459 if (read)
1461 view = context->read_view;
1462 pbuffer = context->read_pbuffer;
1464 else
1466 view = context->draw_view;
1467 pbuffer = context->draw_pbuffer;
1470 if (view || !pbuffer)
1471 macdrv_make_context_current(context->context, view);
1472 else
1474 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1475 pbuffer->level, 0);
1476 CGLSetCurrentContext(context->cglcontext);
1481 /**********************************************************************
1482 * set_swap_interval
1484 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1486 CGLError err;
1488 /* In theory, for single-buffered contexts, there's no such thing as a swap
1489 so the swap interval shouldn't matter. But OS X will synchronize flushes
1490 of single-buffered contexts if the interval is set to non-zero. */
1491 if (interval && !pixel_formats[context->format - 1].double_buffer)
1492 interval = 0;
1494 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1495 if (err != kCGLNoError)
1496 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1498 return err == kCGLNoError;
1502 /**********************************************************************
1503 * sync_swap_interval
1505 static void sync_swap_interval(struct wgl_context *context)
1507 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1509 int interval;
1511 if (context->draw_hwnd)
1513 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1514 if (data)
1516 interval = data->swap_interval;
1517 release_win_data(data);
1519 else /* window was destroyed? */
1520 interval = 1;
1522 else /* pbuffer */
1523 interval = 0;
1525 set_swap_interval(context, interval);
1530 /**********************************************************************
1531 * macdrv_glCopyColorTable
1533 * Hook into glCopyColorTable as part of the implementation of
1534 * wglMakeContextCurrentARB. If the context has a separate readable,
1535 * temporarily make that current, do glCopyColorTable, and then set it
1536 * back to the drawable. This is modeled after what Mesa GLX's Apple
1537 * implementation does.
1539 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1540 GLsizei width)
1542 struct wgl_context *context = NtCurrentTeb()->glContext;
1544 if (context->read_view || context->read_pbuffer)
1545 make_context_current(context, TRUE);
1547 pglCopyColorTable(target, internalformat, x, y, width);
1549 if (context->read_view || context->read_pbuffer)
1550 make_context_current(context, FALSE);
1554 /**********************************************************************
1555 * macdrv_glCopyPixels
1557 * Hook into glCopyPixels as part of the implementation of
1558 * wglMakeContextCurrentARB. If the context has a separate readable,
1559 * temporarily make that current, do glCopyPixels, and then set it back
1560 * to the drawable. This is modeled after what Mesa GLX's Apple
1561 * implementation does.
1563 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1565 struct wgl_context *context = NtCurrentTeb()->glContext;
1567 if (context->read_view || context->read_pbuffer)
1568 make_context_current(context, TRUE);
1570 pglCopyPixels(x, y, width, height, type);
1572 if (context->read_view || context->read_pbuffer)
1573 make_context_current(context, FALSE);
1577 /**********************************************************************
1578 * macdrv_glFinish
1580 static void macdrv_glFinish(void)
1582 struct wgl_context *context = NtCurrentTeb()->glContext;
1584 sync_swap_interval(context);
1585 pglFinish();
1589 /**********************************************************************
1590 * macdrv_glFlush
1592 static void macdrv_glFlush(void)
1594 struct wgl_context *context = NtCurrentTeb()->glContext;
1596 sync_swap_interval(context);
1598 if (skip_single_buffer_flushes)
1600 const pixel_format *pf = &pixel_formats[context->format - 1];
1601 DWORD now = GetTickCount();
1603 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1604 context->last_flush_time, now);
1605 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1607 TRACE("calling glFlushRenderAPPLE()\n");
1608 pglFlushRenderAPPLE();
1609 return;
1611 else
1613 TRACE("calling glFlush()\n");
1614 context->last_flush_time = now;
1618 pglFlush();
1622 /**********************************************************************
1623 * macdrv_glGetString
1625 * Hook into glGetString in order to return some legacy WGL extensions
1626 * that couldn't be advertised via the standard
1627 * WGL_ARB_extensions_string mechanism. Some programs, especially
1628 * older ones, expect to find certain older extensions, such as
1629 * WGL_EXT_extensions_string itself, in the standard GL extensions
1630 * string, and won't query any other WGL extensions unless they find
1631 * that particular extension there.
1633 static const GLubyte *macdrv_glGetString(GLenum name)
1635 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1636 return (const GLubyte *)gl_info.glExtensions;
1637 else
1638 return pglGetString(name);
1642 /**********************************************************************
1643 * macdrv_glReadPixels
1645 * Hook into glReadPixels as part of the implementation of
1646 * wglMakeContextCurrentARB. If the context has a separate readable,
1647 * temporarily make that current, do glReadPixels, and then set it back
1648 * to the drawable. This is modeled after what Mesa GLX's Apple
1649 * implementation does.
1651 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1652 GLenum format, GLenum type, void *pixels)
1654 struct wgl_context *context = NtCurrentTeb()->glContext;
1656 if (context->read_view || context->read_pbuffer)
1657 make_context_current(context, TRUE);
1659 pglReadPixels(x, y, width, height, format, type, pixels);
1661 if (context->read_view || context->read_pbuffer)
1662 make_context_current(context, FALSE);
1666 /**********************************************************************
1667 * macdrv_glViewport
1669 * Hook into glViewport as an opportunity to update the OpenGL context
1670 * if necessary. This is modeled after what Mesa GLX's Apple
1671 * implementation does.
1673 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1675 struct wgl_context *context = NtCurrentTeb()->glContext;
1677 macdrv_update_opengl_context(context->context);
1678 pglViewport(x, y, width, height);
1682 /***********************************************************************
1683 * macdrv_wglBindTexImageARB
1685 * WGL_ARB_render_texture: wglBindTexImageARB
1687 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1689 struct wgl_context *context = NtCurrentTeb()->glContext;
1690 GLenum source;
1691 CGLError err;
1693 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1695 if (pbuffer->no_texture)
1697 SetLastError(ERROR_INVALID_OPERATION);
1698 return GL_FALSE;
1701 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1702 opengl_funcs.gl.p_glFlush();
1704 switch (iBuffer)
1706 case WGL_FRONT_LEFT_ARB:
1707 if (pixel_formats[pbuffer->format - 1].stereo)
1708 source = GL_FRONT_LEFT;
1709 else
1710 source = GL_FRONT;
1711 break;
1712 case WGL_FRONT_RIGHT_ARB:
1713 source = GL_FRONT_RIGHT;
1714 break;
1715 case WGL_BACK_LEFT_ARB:
1716 if (pixel_formats[pbuffer->format - 1].stereo)
1717 source = GL_BACK_LEFT;
1718 else
1719 source = GL_BACK;
1720 break;
1721 case WGL_BACK_RIGHT_ARB:
1722 source = GL_BACK_RIGHT;
1723 break;
1724 case WGL_AUX0_ARB: source = GL_AUX0; break;
1725 case WGL_AUX1_ARB: source = GL_AUX1; break;
1726 case WGL_AUX2_ARB: source = GL_AUX2; break;
1727 case WGL_AUX3_ARB: source = GL_AUX3; break;
1729 case WGL_AUX4_ARB:
1730 case WGL_AUX5_ARB:
1731 case WGL_AUX6_ARB:
1732 case WGL_AUX7_ARB:
1733 case WGL_AUX8_ARB:
1734 case WGL_AUX9_ARB:
1735 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1736 SetLastError(ERROR_INVALID_DATA);
1737 return GL_FALSE;
1739 default:
1740 WARN("unknown source buffer 0x%x\n", iBuffer);
1741 SetLastError(ERROR_INVALID_DATA);
1742 return GL_FALSE;
1745 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1746 if (err != kCGLNoError)
1748 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1749 SetLastError(ERROR_INVALID_OPERATION);
1750 return GL_FALSE;
1753 return GL_TRUE;
1757 /***********************************************************************
1758 * macdrv_wglChoosePixelFormatARB
1760 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1762 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1763 const FLOAT *pfAttribFList, UINT nMaxFormats,
1764 int *piFormats, UINT *nNumFormats)
1766 pixel_format pf, valid;
1767 const int *iptr;
1768 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1769 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1770 int float_color;
1771 BOOL srgb;
1772 int i, found = 0;
1774 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1775 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1776 if (pfAttribFList)
1777 FIXME("unused pfAttribFList\n");
1779 memset(&pf, 0, sizeof(pf));
1780 memset(&valid, 0, sizeof(valid));
1781 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1782 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1783 float_color = -1;
1784 srgb = FALSE;
1786 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1788 int attr = iptr[0];
1789 int value = iptr[1];
1791 TRACE("%s\n", debugstr_attrib(attr, value));
1793 switch (attr)
1795 case WGL_DRAW_TO_WINDOW_ARB:
1796 if (valid.window && (!pf.window != !value)) goto cant_match;
1797 pf.window = (value != 0);
1798 valid.window = 1;
1799 break;
1801 case WGL_DRAW_TO_BITMAP_ARB:
1802 goto cant_match;
1804 case WGL_ACCELERATION_ARB:
1805 if (value == WGL_FULL_ACCELERATION_ARB)
1806 value = 1;
1807 else if (value == WGL_NO_ACCELERATION_ARB)
1808 value = 0;
1809 else
1810 goto cant_match;
1811 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1812 pf.accelerated = value;
1813 valid.accelerated = 1;
1814 break;
1816 case WGL_NEED_PALETTE_ARB:
1817 case WGL_NEED_SYSTEM_PALETTE_ARB:
1818 case WGL_SWAP_LAYER_BUFFERS_ARB:
1819 if (value) goto cant_match;
1820 break;
1822 case WGL_SWAP_METHOD_ARB:
1823 if (value == WGL_SWAP_COPY_ARB)
1824 value = 1;
1825 else if (value == WGL_SWAP_UNDEFINED_ARB)
1826 value = 0;
1827 else
1828 goto cant_match;
1829 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1830 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1831 pf.backing_store = value;
1832 valid.backing_store = 1;
1833 break;
1835 case WGL_NUMBER_OVERLAYS_ARB:
1836 case WGL_NUMBER_UNDERLAYS_ARB:
1837 if (value) goto cant_match;
1838 break;
1840 case WGL_SHARE_DEPTH_ARB:
1841 case WGL_SHARE_STENCIL_ARB:
1842 case WGL_SHARE_ACCUM_ARB:
1843 /* no effect */
1844 break;
1846 case WGL_SUPPORT_GDI_ARB:
1847 if (value) goto cant_match;
1848 break;
1850 case WGL_SUPPORT_OPENGL_ARB:
1851 if (!value) goto cant_match;
1852 break;
1854 case WGL_DOUBLE_BUFFER_ARB:
1855 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1856 pf.double_buffer = (value != 0);
1857 valid.double_buffer = 1;
1858 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1859 break;
1861 case WGL_STEREO_ARB:
1862 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1863 pf.stereo = (value != 0);
1864 valid.stereo = 1;
1865 break;
1867 case WGL_PIXEL_TYPE_ARB:
1868 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1869 value = 1;
1870 else if (value == WGL_TYPE_RGBA_ARB)
1871 value = 0;
1872 else
1874 /* Mac contexts don't support rendering to unsigned floating
1875 point formats, even if GL_EXT_packed_float is supported.
1876 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1877 goto cant_match;
1879 if (float_color != -1 && float_color != value) goto cant_match;
1880 if (srgb && value) goto cant_match;
1881 float_color = value;
1882 break;
1884 case WGL_COLOR_BITS_ARB:
1885 if (color_bits < value) color_bits = value;
1886 break;
1888 case WGL_RED_BITS_ARB:
1889 if (srgb && value > 8) goto cant_match;
1890 if (red_bits < value) red_bits = value;
1891 break;
1893 case WGL_GREEN_BITS_ARB:
1894 if (srgb && value > 8) goto cant_match;
1895 if (green_bits < value) green_bits = value;
1896 break;
1898 case WGL_BLUE_BITS_ARB:
1899 if (srgb && value > 8) goto cant_match;
1900 if (blue_bits < value) blue_bits = value;
1901 break;
1903 case WGL_ALPHA_BITS_ARB:
1904 if (alpha_bits < value) alpha_bits = value;
1905 break;
1907 case WGL_ACCUM_BITS_ARB:
1908 if (accum_bits < value) accum_bits = value;
1909 break;
1911 case WGL_ACCUM_RED_BITS_ARB:
1912 if (accum_red_bits < value) accum_red_bits = value;
1913 break;
1915 case WGL_ACCUM_GREEN_BITS_ARB:
1916 if (accum_green_bits < value) accum_green_bits = value;
1917 break;
1919 case WGL_ACCUM_BLUE_BITS_ARB:
1920 if (accum_blue_bits < value) accum_blue_bits = value;
1921 break;
1923 case WGL_ACCUM_ALPHA_BITS_ARB:
1924 if (accum_alpha_bits < value) accum_alpha_bits = value;
1925 break;
1927 case WGL_DEPTH_BITS_ARB:
1928 if (value > 255) goto cant_match;
1929 if (pf.depth_bits < value) pf.depth_bits = value;
1930 break;
1932 case WGL_STENCIL_BITS_ARB:
1933 if (value > 255) goto cant_match;
1934 if (pf.stencil_bits < value) pf.stencil_bits = value;
1935 break;
1937 case WGL_AUX_BUFFERS_ARB:
1938 if (value > 7) goto cant_match;
1939 if (pf.aux_buffers < value) pf.aux_buffers = value;
1940 break;
1942 case WGL_SAMPLE_BUFFERS_ARB:
1943 if (value > 1) goto cant_match;
1944 if (pf.sample_buffers < value) pf.sample_buffers = value;
1945 break;
1947 case WGL_SAMPLES_ARB:
1948 if (value > 31) goto cant_match;
1949 if (pf.samples < value) pf.samples = value;
1950 break;
1952 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1953 /* sRGB is only supported for 8-bit integer color components */
1954 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1955 goto cant_match;
1956 srgb = TRUE;
1957 break;
1959 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1960 case WGL_RED_SHIFT_ARB:
1961 case WGL_GREEN_SHIFT_ARB:
1962 case WGL_BLUE_SHIFT_ARB:
1963 case WGL_ALPHA_SHIFT_ARB:
1964 case WGL_TRANSPARENT_ARB:
1965 case WGL_TRANSPARENT_RED_VALUE_ARB:
1966 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1967 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1968 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1969 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1970 /* ignored */
1971 break;
1973 case WGL_DRAW_TO_PBUFFER_ARB:
1974 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1975 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1976 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1977 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1978 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1979 pf.pbuffer = (value != 0);
1980 valid.pbuffer = 1;
1981 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1982 !alpha_bits)
1983 alpha_bits = 1;
1984 break;
1986 default:
1987 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
1988 return GL_FALSE;
1992 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",
1993 valid.window ? (pf.window ? "1" : "0") : "?",
1994 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
1995 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
1996 color_bits,
1997 float_color == -1 ? "?" : float_color ? "f" : "",
1998 red_bits,
1999 green_bits,
2000 blue_bits,
2001 alpha_bits,
2002 (int)srgb,
2003 accum_bits,
2004 accum_red_bits,
2005 accum_green_bits,
2006 accum_blue_bits,
2007 accum_alpha_bits,
2008 pf.depth_bits,
2009 pf.stencil_bits,
2010 pf.aux_buffers,
2011 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2012 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2013 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2014 pf.sample_buffers,
2015 pf.samples);
2017 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2019 const struct color_mode *mode;
2021 if (valid.window && pixel_formats[i].window != pf.window) continue;
2022 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2023 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2024 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2025 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2026 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2028 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2029 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2030 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2031 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2032 if (pixel_formats[i].samples < pf.samples) continue;
2034 mode = &color_modes[pixel_formats[i].color_mode];
2035 /* If the mode doesn't have alpha, check requested color bits against
2036 bits per pixel instead of the mode's color bits. On Windows, color
2037 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2038 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2039 expects that to match such a pixel format, we need to accommodate that. */
2040 if (mode->alpha_bits)
2042 if (mode->color_bits < color_bits)
2043 continue;
2045 else
2047 if (mode->bits_per_pixel < color_bits)
2048 continue;
2050 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2051 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2052 continue;
2053 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2054 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2055 continue;
2057 if (pixel_formats[i].accum_mode)
2059 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2060 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2061 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2062 mode->alpha_bits < accum_alpha_bits)
2063 continue;
2065 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2066 continue;
2068 piFormats[found++] = i + 1;
2069 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2072 cant_match:
2073 *nNumFormats = found;
2075 return TRUE;
2079 /**********************************************************************
2080 * macdrv_wglCreatePbufferARB
2082 * WGL_ARB_pbuffer: wglCreatePbufferARB
2084 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2085 const int *piAttribList)
2087 struct wgl_pbuffer* pbuffer;
2088 GLenum target = 0;
2089 GLenum internalFormat = 0;
2090 CGLError err;
2092 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2093 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2095 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2097 WARN("invalid pixel format %d\n", iPixelFormat);
2098 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2099 return NULL;
2102 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2103 pbuffer->format = iPixelFormat;
2105 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2107 int attr = piAttribList[0];
2108 int value = piAttribList[1];
2110 switch (attr)
2112 case WGL_PBUFFER_LARGEST_ARB:
2113 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2114 break;
2116 case WGL_TEXTURE_FORMAT_ARB:
2117 switch (value)
2119 case WGL_TEXTURE_RGBA_ARB:
2120 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2121 internalFormat = GL_RGBA;
2122 break;
2123 case WGL_TEXTURE_RGB_ARB:
2124 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2125 internalFormat = GL_RGB;
2126 break;
2127 case WGL_NO_TEXTURE_ARB:
2128 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2129 internalFormat = 0;
2130 break;
2131 default:
2132 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2133 SetLastError(ERROR_INVALID_DATA);
2134 goto done;
2136 break;
2138 case WGL_TEXTURE_TARGET_ARB:
2139 pbuffer->face = 0;
2140 switch (value)
2142 case WGL_NO_TEXTURE_ARB:
2143 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2144 target = 0;
2145 break;
2146 case WGL_TEXTURE_CUBE_MAP_ARB:
2147 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2148 target = GL_TEXTURE_CUBE_MAP;
2149 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2150 break;
2151 case WGL_TEXTURE_1D_ARB:
2152 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2153 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2154 goto done;
2155 case WGL_TEXTURE_2D_ARB:
2156 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2157 target = GL_TEXTURE_2D;
2158 break;
2159 case WGL_TEXTURE_RECTANGLE_NV:
2160 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2161 target = GL_TEXTURE_RECTANGLE;
2162 break;
2163 default:
2164 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2165 SetLastError(ERROR_INVALID_DATA);
2166 goto done;
2168 break;
2170 case WGL_MIPMAP_TEXTURE_ARB:
2171 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2172 pbuffer->max_level = 0;
2173 if (value)
2175 int size = min(iWidth, iHeight) / 2;
2176 while (size)
2178 pbuffer->max_level++;
2179 size /= 2;
2182 break;
2184 default:
2185 WARN("unknown attribute 0x%x\n", attr);
2186 SetLastError(ERROR_INVALID_DATA);
2187 goto done;
2191 if (!target || !internalFormat)
2193 pbuffer->no_texture = TRUE;
2194 /* no actual way to turn off ability to texture; use most permissive target */
2195 target = GL_TEXTURE_RECTANGLE;
2196 internalFormat = GL_RGB;
2199 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2200 if (err != kCGLNoError)
2202 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2203 pbuffer->pbuffer = NULL;
2204 if (err == kCGLBadAlloc)
2205 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2206 else
2207 SetLastError(ERROR_INVALID_DATA);
2210 done:
2211 if (!pbuffer->pbuffer)
2213 HeapFree(GetProcessHeap(), 0, pbuffer);
2214 return NULL;
2217 TRACE(" -> %p\n", pbuffer);
2218 return pbuffer;
2222 /**********************************************************************
2223 * macdrv_wglDestroyPbufferARB
2225 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2227 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2229 TRACE("pbuffer %p\n", pbuffer);
2230 if (pbuffer && pbuffer->pbuffer)
2231 CGLReleasePBuffer(pbuffer->pbuffer);
2232 HeapFree(GetProcessHeap(), 0, pbuffer);
2233 return GL_TRUE;
2237 /**********************************************************************
2238 * macdrv_wglGetExtensionsStringARB
2240 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2242 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2244 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2245 this can be specific to the CGL renderer like we're supposed to do. */
2246 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2247 return gl_info.wglExtensions;
2251 /**********************************************************************
2252 * macdrv_wglGetExtensionsStringEXT
2254 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2256 static const char *macdrv_wglGetExtensionsStringEXT(void)
2258 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2259 return gl_info.wglExtensions;
2263 /**********************************************************************
2264 * macdrv_wglGetPbufferDCARB
2266 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2268 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2270 HDC hdc;
2271 struct wgl_pbuffer *prev;
2273 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2274 if (!hdc) return 0;
2276 EnterCriticalSection(&dc_pbuffers_section);
2277 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2278 if (prev)
2280 CGLReleasePBuffer(prev->pbuffer);
2281 HeapFree(GetProcessHeap(), 0, prev);
2283 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2284 LeaveCriticalSection(&dc_pbuffers_section);
2286 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2287 return hdc;
2291 /**********************************************************************
2292 * macdrv_wglGetPixelFormatAttribivARB
2294 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2296 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2297 UINT nAttributes, const int *piAttributes, int *piValues)
2299 const pixel_format *pf;
2300 UINT i;
2302 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2303 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2305 if (!nAttributes) return GL_TRUE;
2307 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2309 piValues[0] = nb_formats;
2310 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2311 return GL_TRUE;
2314 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2315 if (!pf)
2317 WARN("invalid pixel format %d\n", iPixelFormat);
2318 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2319 return GL_FALSE;
2322 for (i = 0; i < nAttributes; ++i)
2324 switch (piAttributes[i])
2326 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2327 piValues[i] = nb_formats;
2328 break;
2330 case WGL_DRAW_TO_WINDOW_ARB:
2331 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2332 break;
2334 case WGL_DRAW_TO_BITMAP_ARB:
2335 piValues[i] = GL_FALSE;
2336 break;
2338 case WGL_ACCELERATION_ARB:
2339 if (iLayerPlane) goto invalid_layer;
2340 if (pf->accelerated)
2341 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2342 else
2343 piValues[i] = WGL_NO_ACCELERATION_ARB;
2344 break;
2346 case WGL_NEED_PALETTE_ARB:
2347 case WGL_NEED_SYSTEM_PALETTE_ARB:
2348 case WGL_SWAP_LAYER_BUFFERS_ARB:
2349 piValues[i] = GL_FALSE;
2350 break;
2352 case WGL_SWAP_METHOD_ARB:
2353 if (pf->double_buffer && pf->backing_store)
2354 piValues[i] = WGL_SWAP_COPY_ARB;
2355 else
2356 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2357 break;
2359 case WGL_NUMBER_OVERLAYS_ARB:
2360 case WGL_NUMBER_UNDERLAYS_ARB:
2361 piValues[i] = 0;
2362 break;
2364 case WGL_TRANSPARENT_ARB:
2365 if (iLayerPlane) goto invalid_layer;
2366 piValues[i] = GL_FALSE;
2367 break;
2369 case WGL_TRANSPARENT_RED_VALUE_ARB:
2370 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2371 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2372 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2373 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2374 if (iLayerPlane) goto invalid_layer;
2375 piValues[i] = 0;
2376 break;
2378 case WGL_SHARE_DEPTH_ARB:
2379 case WGL_SHARE_STENCIL_ARB:
2380 case WGL_SHARE_ACCUM_ARB:
2381 if (iLayerPlane) goto invalid_layer;
2382 piValues[i] = GL_TRUE;
2383 break;
2385 case WGL_SUPPORT_GDI_ARB:
2386 if (iLayerPlane) goto invalid_layer;
2387 piValues[i] = GL_FALSE;
2388 break;
2390 case WGL_SUPPORT_OPENGL_ARB:
2391 if (iLayerPlane) goto invalid_layer;
2392 piValues[i] = GL_TRUE;
2393 break;
2395 case WGL_DOUBLE_BUFFER_ARB:
2396 if (iLayerPlane) goto invalid_layer;
2397 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2398 break;
2400 case WGL_STEREO_ARB:
2401 if (iLayerPlane) goto invalid_layer;
2402 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2403 break;
2405 case WGL_PIXEL_TYPE_ARB:
2406 if (iLayerPlane) goto invalid_layer;
2407 if (color_modes[pf->color_mode].is_float)
2408 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2409 else
2410 piValues[i] = WGL_TYPE_RGBA_ARB;
2411 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2412 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2413 However, Mac contexts don't support rendering to unsigned floating-point
2414 formats, even when GL_EXT_packed_float is supported. */
2415 break;
2417 case WGL_COLOR_BITS_ARB:
2418 if (iLayerPlane) goto invalid_layer;
2419 /* If the mode doesn't have alpha, return bits per pixel instead
2420 of color bits. On Windows, color bits sometimes exceeds r+g+b
2421 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2422 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2423 pixel format, we need to accommodate that. */
2424 if (color_modes[pf->color_mode].alpha_bits)
2425 piValues[i] = color_modes[pf->color_mode].color_bits;
2426 else
2427 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2428 break;
2430 case WGL_RED_BITS_ARB:
2431 if (iLayerPlane) goto invalid_layer;
2432 piValues[i] = color_modes[pf->color_mode].red_bits;
2433 break;
2435 case WGL_RED_SHIFT_ARB:
2436 if (iLayerPlane) goto invalid_layer;
2437 piValues[i] = color_modes[pf->color_mode].red_shift;
2438 break;
2440 case WGL_GREEN_BITS_ARB:
2441 if (iLayerPlane) goto invalid_layer;
2442 piValues[i] = color_modes[pf->color_mode].green_bits;
2443 break;
2445 case WGL_GREEN_SHIFT_ARB:
2446 if (iLayerPlane) goto invalid_layer;
2447 piValues[i] = color_modes[pf->color_mode].green_shift;
2448 break;
2450 case WGL_BLUE_BITS_ARB:
2451 if (iLayerPlane) goto invalid_layer;
2452 piValues[i] = color_modes[pf->color_mode].blue_bits;
2453 break;
2455 case WGL_BLUE_SHIFT_ARB:
2456 if (iLayerPlane) goto invalid_layer;
2457 piValues[i] = color_modes[pf->color_mode].blue_shift;
2458 break;
2460 case WGL_ALPHA_BITS_ARB:
2461 if (iLayerPlane) goto invalid_layer;
2462 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2463 break;
2465 case WGL_ALPHA_SHIFT_ARB:
2466 if (iLayerPlane) goto invalid_layer;
2467 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2468 break;
2470 case WGL_ACCUM_BITS_ARB:
2471 if (iLayerPlane) goto invalid_layer;
2472 if (pf->accum_mode)
2473 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2474 else
2475 piValues[i] = 0;
2476 break;
2478 case WGL_ACCUM_RED_BITS_ARB:
2479 if (iLayerPlane) goto invalid_layer;
2480 if (pf->accum_mode)
2481 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2482 else
2483 piValues[i] = 0;
2484 break;
2486 case WGL_ACCUM_GREEN_BITS_ARB:
2487 if (iLayerPlane) goto invalid_layer;
2488 if (pf->accum_mode)
2489 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2490 else
2491 piValues[i] = 0;
2492 break;
2494 case WGL_ACCUM_BLUE_BITS_ARB:
2495 if (iLayerPlane) goto invalid_layer;
2496 if (pf->accum_mode)
2497 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2498 else
2499 piValues[i] = 0;
2500 break;
2502 case WGL_ACCUM_ALPHA_BITS_ARB:
2503 if (iLayerPlane) goto invalid_layer;
2504 if (pf->accum_mode)
2505 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2506 else
2507 piValues[i] = 0;
2508 break;
2510 case WGL_DEPTH_BITS_ARB:
2511 if (iLayerPlane) goto invalid_layer;
2512 piValues[i] = pf->depth_bits;
2513 break;
2515 case WGL_STENCIL_BITS_ARB:
2516 if (iLayerPlane) goto invalid_layer;
2517 piValues[i] = pf->stencil_bits;
2518 break;
2520 case WGL_AUX_BUFFERS_ARB:
2521 if (iLayerPlane) goto invalid_layer;
2522 piValues[i] = pf->aux_buffers;
2523 break;
2525 case WGL_SAMPLE_BUFFERS_ARB:
2526 if (iLayerPlane) goto invalid_layer;
2527 piValues[i] = pf->sample_buffers;
2528 break;
2530 case WGL_SAMPLES_ARB:
2531 if (iLayerPlane) goto invalid_layer;
2532 piValues[i] = pf->samples;
2533 break;
2535 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2536 if (iLayerPlane) goto invalid_layer;
2537 /* sRGB is only supported for 8-bit integer color components */
2538 if (color_modes[pf->color_mode].red_bits == 8 &&
2539 color_modes[pf->color_mode].green_bits == 8 &&
2540 color_modes[pf->color_mode].blue_bits == 8 &&
2541 !color_modes[pf->color_mode].is_float)
2542 piValues[i] = GL_TRUE;
2543 else
2544 piValues[i] = GL_FALSE;
2545 break;
2547 case WGL_DRAW_TO_PBUFFER_ARB:
2548 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2549 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2550 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2551 break;
2553 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2554 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2555 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2556 break;
2558 case WGL_MAX_PBUFFER_WIDTH_ARB:
2559 piValues[i] = gl_info.max_viewport_dims[0];
2560 break;
2562 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2563 piValues[i] = gl_info.max_viewport_dims[1];
2564 break;
2566 case WGL_MAX_PBUFFER_PIXELS_ARB:
2567 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2568 break;
2570 default:
2571 WARN("invalid attribute %x\n", piAttributes[i]);
2572 return GL_FALSE;
2575 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2578 return GL_TRUE;
2580 invalid_layer:
2581 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2582 return GL_FALSE;
2586 /**********************************************************************
2587 * macdrv_wglGetPixelFormatAttribfvARB
2589 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2591 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2592 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2594 int *attr;
2595 int ret;
2597 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2598 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2600 /* Allocate a temporary array to store integer values */
2601 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2602 if (!attr)
2604 ERR("couldn't allocate %d array\n", nAttributes);
2605 return GL_FALSE;
2608 /* Piggy-back on wglGetPixelFormatAttribivARB */
2609 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2610 if (ret)
2612 UINT i;
2614 /* Convert integer values to float. Should also check for attributes
2615 that can give decimal values here */
2616 for (i = 0; i < nAttributes; i++)
2617 pfValues[i] = attr[i];
2620 HeapFree(GetProcessHeap(), 0, attr);
2621 return ret;
2625 /**********************************************************************
2626 * macdrv_wglGetSwapIntervalEXT
2628 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2630 static int macdrv_wglGetSwapIntervalEXT(void)
2632 struct wgl_context *context = NtCurrentTeb()->glContext;
2633 struct macdrv_win_data *data;
2634 long value;
2635 CGLError err;
2637 TRACE("\n");
2639 if ((data = get_win_data(context->draw_hwnd)))
2641 value = data->swap_interval;
2642 release_win_data(data);
2644 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
2645 set_swap_interval(context, value);
2647 else
2649 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2650 if (err != kCGLNoError)
2652 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2653 err, CGLErrorString(err));
2654 value = 1;
2658 return value;
2662 /***********************************************************************
2663 * macdrv_wglMakeContextCurrentARB
2665 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2667 * This is not supported directly by OpenGL on the Mac. We emulate it
2668 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2669 * temporarily swap the drawable. This follows the technique used in
2670 * the implementation of Mesa GLX for Apple.
2672 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2674 struct macdrv_win_data *data;
2675 HWND hwnd;
2677 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2678 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2680 if (!context)
2682 macdrv_make_context_current(NULL, NULL);
2683 NtCurrentTeb()->glContext = NULL;
2684 return TRUE;
2687 if ((hwnd = WindowFromDC(draw_hdc)))
2689 if (!(data = get_win_data(hwnd)))
2691 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2692 return FALSE;
2695 if (!data->pixel_format)
2697 WARN("no pixel format set\n");
2698 release_win_data(data);
2699 SetLastError(ERROR_INVALID_HANDLE);
2700 return FALSE;
2702 if (context->format != data->pixel_format)
2704 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2705 release_win_data(data);
2706 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2707 return FALSE;
2710 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
2711 set_swap_interval(context, data->swap_interval);
2713 context->draw_hwnd = hwnd;
2714 context->draw_view = data->gl_view;
2715 context->draw_pbuffer = NULL;
2716 release_win_data(data);
2718 else
2720 struct wgl_pbuffer *pbuffer;
2722 EnterCriticalSection(&dc_pbuffers_section);
2723 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2724 if (pbuffer)
2726 if (context->format != pbuffer->format)
2728 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2729 LeaveCriticalSection(&dc_pbuffers_section);
2730 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2731 return FALSE;
2734 if (allow_vsync &&
2735 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
2736 set_swap_interval(context, 0);
2738 else
2740 WARN("no window or pbuffer for DC\n");
2741 LeaveCriticalSection(&dc_pbuffers_section);
2742 SetLastError(ERROR_INVALID_HANDLE);
2743 return FALSE;
2746 context->draw_hwnd = NULL;
2747 context->draw_view = NULL;
2748 context->draw_pbuffer = pbuffer;
2749 LeaveCriticalSection(&dc_pbuffers_section);
2752 context->read_view = NULL;
2753 context->read_pbuffer = NULL;
2754 if (read_hdc && read_hdc != draw_hdc)
2756 if ((hwnd = WindowFromDC(read_hdc)))
2758 if ((data = get_win_data(hwnd)))
2760 if (data->gl_view != context->draw_view)
2761 context->read_view = data->gl_view;
2762 release_win_data(data);
2765 else
2767 EnterCriticalSection(&dc_pbuffers_section);
2768 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2769 LeaveCriticalSection(&dc_pbuffers_section);
2773 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2774 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2776 make_context_current(context, FALSE);
2777 context->has_been_current = TRUE;
2778 NtCurrentTeb()->glContext = context;
2780 return TRUE;
2784 /**********************************************************************
2785 * macdrv_wglQueryPbufferARB
2787 * WGL_ARB_pbuffer: wglQueryPbufferARB
2789 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2791 CGLError err;
2792 GLsizei width;
2793 GLsizei height;
2794 GLenum target;
2795 GLenum internalFormat;
2796 GLint mipmap;
2798 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2800 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2801 if (err != kCGLNoError)
2803 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2804 SetLastError(ERROR_INVALID_HANDLE);
2805 return GL_FALSE;
2808 switch (iAttribute)
2810 case WGL_PBUFFER_WIDTH_ARB:
2811 *piValue = width;
2812 break;
2813 case WGL_PBUFFER_HEIGHT_ARB:
2814 *piValue = height;
2815 break;
2816 case WGL_PBUFFER_LOST_ARB:
2817 /* Mac PBuffers can't be lost */
2818 *piValue = GL_FALSE;
2819 break;
2820 case WGL_TEXTURE_FORMAT_ARB:
2821 if (pbuffer->no_texture)
2822 *piValue = WGL_NO_TEXTURE_ARB;
2823 else switch (internalFormat)
2825 case GL_RGBA:
2826 *piValue = WGL_TEXTURE_RGBA_ARB;
2827 break;
2828 case GL_RGB:
2829 default:
2830 *piValue = WGL_TEXTURE_RGB_ARB;
2831 break;
2833 break;
2834 case WGL_TEXTURE_TARGET_ARB:
2835 if (pbuffer->no_texture)
2836 *piValue = WGL_NO_TEXTURE_ARB;
2837 else switch (target)
2839 case GL_TEXTURE_CUBE_MAP:
2840 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2841 break;
2842 case GL_TEXTURE_2D:
2843 *piValue = WGL_TEXTURE_2D_ARB;
2844 break;
2845 case GL_TEXTURE_RECTANGLE:
2846 default:
2847 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2848 break;
2850 break;
2851 case WGL_MIPMAP_TEXTURE_ARB:
2852 *piValue = (pbuffer->max_level > 0);
2853 break;
2854 case WGL_MIPMAP_LEVEL_ARB:
2855 *piValue = pbuffer->level;
2856 break;
2857 case WGL_CUBE_MAP_FACE_ARB:
2858 switch (pbuffer->face)
2860 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2861 default:
2862 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2863 break;
2864 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2865 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2866 break;
2867 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2868 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2869 break;
2870 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2871 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2872 break;
2873 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2874 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2875 break;
2876 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2877 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2878 break;
2880 break;
2881 default:
2882 WARN("invalid attribute 0x%x\n", iAttribute);
2883 SetLastError(ERROR_INVALID_DATA);
2884 return GL_FALSE;
2887 return GL_TRUE;
2891 /**********************************************************************
2892 * macdrv_wglReleasePbufferDCARB
2894 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2896 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2898 struct wgl_pbuffer *prev;
2900 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2902 EnterCriticalSection(&dc_pbuffers_section);
2904 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2905 if (prev)
2907 if (prev != pbuffer)
2908 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2909 CGLReleasePBuffer(prev->pbuffer);
2910 HeapFree(GetProcessHeap(), 0, prev);
2911 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2913 else hdc = 0;
2915 LeaveCriticalSection(&dc_pbuffers_section);
2917 return hdc && DeleteDC(hdc);
2921 /**********************************************************************
2922 * macdrv_wglReleaseTexImageARB
2924 * WGL_ARB_render_texture: wglReleaseTexImageARB
2926 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2928 struct wgl_context *context = NtCurrentTeb()->glContext;
2929 CGLError err;
2931 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2933 if (pbuffer->no_texture)
2935 SetLastError(ERROR_INVALID_OPERATION);
2936 return GL_FALSE;
2939 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2940 if (err != kCGLNoError)
2942 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2943 SetLastError(ERROR_INVALID_OPERATION);
2944 return GL_FALSE;
2947 return GL_TRUE;
2951 /**********************************************************************
2952 * macdrv_wglSetPbufferAttribARB
2954 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2956 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2958 struct wgl_context *context = NtCurrentTeb()->glContext;
2960 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2962 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2964 int attr = piAttribList[0];
2965 int value = piAttribList[1];
2966 switch (attr)
2968 case WGL_MIPMAP_LEVEL_ARB:
2969 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2970 pbuffer->level = value;
2971 break;
2972 case WGL_CUBE_MAP_FACE_ARB:
2973 switch (value)
2975 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2976 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2977 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2978 break;
2979 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2980 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2981 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2982 break;
2983 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2984 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2985 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2986 break;
2987 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2988 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2989 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2990 break;
2991 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2992 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2993 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2994 break;
2995 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2996 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2997 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2998 break;
2999 default:
3000 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
3001 SetLastError(ERROR_INVALID_DATA);
3002 return GL_FALSE;
3004 break;
3005 default:
3006 WARN("invalide attribute 0x%x\n", attr);
3007 SetLastError(ERROR_INVALID_DATA);
3008 return GL_FALSE;
3012 if (context && context->draw_pbuffer == pbuffer)
3013 make_context_current(context, FALSE);
3015 return GL_TRUE;
3019 /**********************************************************************
3020 * macdrv_wglSetPixelFormatWINE
3022 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3024 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
3026 return set_pixel_format(hdc, fmt, TRUE);
3030 /**********************************************************************
3031 * macdrv_wglSwapIntervalEXT
3033 * WGL_EXT_swap_control: wglSwapIntervalEXT
3035 static BOOL macdrv_wglSwapIntervalEXT(int interval)
3037 struct wgl_context *context = NtCurrentTeb()->glContext;
3038 BOOL changed = FALSE;
3040 TRACE("interval %d\n", interval);
3042 if (interval < 0)
3044 SetLastError(ERROR_INVALID_DATA);
3045 return FALSE;
3047 if (interval > 1)
3048 interval = 1;
3050 if (context->draw_hwnd)
3052 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
3053 if (data)
3055 changed = data->swap_interval != interval;
3056 if (changed)
3057 data->swap_interval = interval;
3058 release_win_data(data);
3061 else /* pbuffer */
3062 interval = 0;
3064 InterlockedExchange(&context->update_swap_interval, FALSE);
3065 if (!set_swap_interval(context, interval))
3067 SetLastError(ERROR_GEN_FAILURE);
3068 return FALSE;
3071 if (changed)
3073 struct wgl_context *ctx;
3075 EnterCriticalSection(&context_section);
3076 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
3078 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
3079 InterlockedExchange(&context->update_swap_interval, TRUE);
3081 LeaveCriticalSection(&context_section);
3084 return TRUE;
3088 static void register_extension(const char *ext)
3090 if (gl_info.wglExtensions[0])
3091 strcat(gl_info.wglExtensions, " ");
3092 strcat(gl_info.wglExtensions, ext);
3094 TRACE("'%s'\n", ext);
3097 static void load_extensions(void)
3100 * ARB Extensions
3102 register_extension("WGL_ARB_extensions_string");
3103 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
3105 register_extension("WGL_ARB_make_current_read");
3106 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
3107 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
3109 register_extension("WGL_ARB_pixel_format");
3110 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
3111 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
3112 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
3114 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
3116 register_extension("WGL_ARB_pixel_format_float");
3117 register_extension("WGL_ATI_pixel_format_float");
3120 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
3121 register_extension("WGL_ARB_multisample");
3123 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3124 register_extension("WGL_ARB_framebuffer_sRGB");
3126 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
3128 register_extension("WGL_ARB_pbuffer");
3129 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3130 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3131 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3132 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3133 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3135 register_extension("WGL_ARB_render_texture");
3136 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3137 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3138 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3140 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3141 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3142 register_extension("WGL_NV_render_texture_rectangle");
3145 /* TODO:
3146 WGL_ARB_create_context: wglCreateContextAttribsARB
3147 WGL_ARB_create_context_profile
3151 * EXT Extensions
3153 register_extension("WGL_EXT_extensions_string");
3154 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3156 if (allow_vsync)
3158 register_extension("WGL_EXT_swap_control");
3159 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3160 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3163 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3164 check for either, so register them separately. */
3165 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3166 register_extension("WGL_EXT_framebuffer_sRGB");
3168 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3169 register_extension("WGL_EXT_pixel_format_packed_float");
3172 * WINE-specific WGL Extensions
3175 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3176 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3178 register_extension("WGL_WINE_pixel_format_passthrough");
3179 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3183 static BOOL init_opengl(void)
3185 static BOOL init_done = FALSE;
3186 unsigned int i;
3187 char buffer[200];
3189 if (init_done) return (opengl_handle != NULL);
3190 init_done = TRUE;
3192 TRACE("()\n");
3194 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3195 if (!dc_pbuffers)
3197 WARN("CFDictionaryCreateMutable failed\n");
3198 return FALSE;
3201 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3202 if (!opengl_handle)
3204 ERR("Failed to load OpenGL: %s\n", buffer);
3205 ERR("OpenGL support is disabled.\n");
3206 return FALSE;
3209 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3211 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3213 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3214 goto failed;
3218 /* redirect some standard OpenGL functions */
3219 #define REDIRECT(func) \
3220 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3221 REDIRECT(glCopyPixels);
3222 REDIRECT(glGetString);
3223 REDIRECT(glReadPixels);
3224 REDIRECT(glViewport);
3225 if (skip_single_buffer_flushes || allow_vsync)
3226 REDIRECT(glFlush);
3227 if (allow_vsync)
3228 REDIRECT(glFinish);
3229 #undef REDIRECT
3231 /* redirect some OpenGL extension functions */
3232 #define REDIRECT(func) \
3233 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3234 REDIRECT(glCopyColorTable);
3235 #undef REDIRECT
3237 if (!init_gl_info())
3238 goto failed;
3240 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3241 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3243 load_extensions();
3244 if (!init_pixel_formats())
3245 goto failed;
3247 return TRUE;
3249 failed:
3250 wine_dlclose(opengl_handle, NULL, 0);
3251 opengl_handle = NULL;
3252 return FALSE;
3256 /***********************************************************************
3257 * sync_gl_view
3259 * Synchronize the Mac GL view position with the Windows child window
3260 * position.
3262 void sync_gl_view(struct macdrv_win_data *data)
3264 RECT rect;
3266 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3268 if (!data->gl_view) return;
3270 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3272 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3273 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3274 data->gl_rect = rect;
3279 static int get_dc_pixel_format(HDC hdc)
3281 int format;
3282 HWND hwnd;
3284 if ((hwnd = WindowFromDC(hdc)))
3286 struct macdrv_win_data *data;
3288 if (!(data = get_win_data(hwnd)))
3290 FIXME("DC for window %p of other process: not implemented\n", hwnd);
3291 return 0;
3294 format = data->pixel_format;
3295 release_win_data(data);
3297 else
3299 struct wgl_pbuffer *pbuffer;
3301 EnterCriticalSection(&dc_pbuffers_section);
3302 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3303 if (pbuffer)
3304 format = pbuffer->format;
3305 else
3307 WARN("no window or pbuffer for DC %p\n", hdc);
3308 format = 0;
3310 LeaveCriticalSection(&dc_pbuffers_section);
3313 return format;
3317 /**********************************************************************
3318 * create_context
3320 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
3322 const pixel_format *pf;
3323 CGLPixelFormatAttribute attribs[64];
3324 int n = 0;
3325 CGLPixelFormatObj pix;
3326 GLint virtualScreens;
3327 CGLError err;
3329 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
3330 if (!pf)
3332 ERR("Invalid pixel format %d, expect problems!\n", context->format);
3333 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3334 return FALSE;
3337 attribs[n++] = kCGLPFAMinimumPolicy;
3338 attribs[n++] = kCGLPFAClosestPolicy;
3340 if (pf->accelerated)
3342 attribs[n++] = kCGLPFAAccelerated;
3343 attribs[n++] = kCGLPFANoRecovery;
3345 else
3347 attribs[n++] = kCGLPFARendererID;
3348 attribs[n++] = kCGLRendererGenericFloatID;
3351 if (pf->double_buffer)
3352 attribs[n++] = kCGLPFADoubleBuffer;
3354 attribs[n++] = kCGLPFAAuxBuffers;
3355 attribs[n++] = pf->aux_buffers;
3357 attribs[n++] = kCGLPFAColorSize;
3358 attribs[n++] = color_modes[pf->color_mode].color_bits;
3359 attribs[n++] = kCGLPFAAlphaSize;
3360 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3361 if (color_modes[pf->color_mode].is_float)
3362 attribs[n++] = kCGLPFAColorFloat;
3364 attribs[n++] = kCGLPFADepthSize;
3365 attribs[n++] = pf->depth_bits;
3367 attribs[n++] = kCGLPFAStencilSize;
3368 attribs[n++] = pf->stencil_bits;
3370 if (pf->stereo)
3371 attribs[n++] = kCGLPFAStereo;
3373 if (pf->accum_mode)
3375 attribs[n++] = kCGLPFAAccumSize;
3376 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3379 if (pf->window)
3380 attribs[n++] = kCGLPFAWindow;
3381 if (pf->pbuffer)
3382 attribs[n++] = kCGLPFAPBuffer;
3384 if (pf->sample_buffers && pf->samples)
3386 attribs[n++] = kCGLPFASampleBuffers;
3387 attribs[n++] = pf->sample_buffers;
3388 attribs[n++] = kCGLPFASamples;
3389 attribs[n++] = pf->samples;
3392 if (pf->backing_store)
3393 attribs[n++] = kCGLPFABackingStore;
3395 attribs[n] = 0;
3397 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3398 if (err != kCGLNoError || !pix)
3400 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3401 return FALSE;
3404 err = CGLCreateContext(pix, share, &context->cglcontext);
3405 CGLReleasePixelFormat(pix);
3406 if (err != kCGLNoError || !context->cglcontext)
3408 context->cglcontext = NULL;
3409 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3410 return FALSE;
3413 context->context = macdrv_create_opengl_context(context->cglcontext);
3414 CGLReleaseContext(context->cglcontext);
3415 if (!context->context)
3417 WARN("macdrv_create_opengl_context() failed\n");
3418 return FALSE;
3421 if (allow_vsync)
3422 InterlockedExchange(&context->update_swap_interval, TRUE);
3424 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3426 return TRUE;
3430 /**********************************************************************
3431 * macdrv_wglDescribePixelFormat
3433 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3435 const pixel_format *pf;
3436 const struct color_mode *mode;
3438 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3440 if (!descr) return nb_displayable_formats;
3441 if (size < sizeof(*descr)) return 0;
3443 if (!(pf = get_pixel_format(fmt, FALSE)))
3444 return 0;
3446 memset(descr, 0, sizeof(*descr));
3447 descr->nSize = sizeof(*descr);
3448 descr->nVersion = 1;
3450 descr->dwFlags = PFD_SUPPORT_OPENGL;
3451 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3452 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3453 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3454 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3455 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3457 descr->iPixelType = PFD_TYPE_RGBA;
3459 mode = &color_modes[pf->color_mode];
3460 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3461 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3462 R8G8B8A0 pixel format). If an app depends on that and expects that
3463 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3464 if (mode->alpha_bits)
3465 descr->cColorBits = mode->color_bits;
3466 else
3467 descr->cColorBits = mode->bits_per_pixel;
3468 descr->cRedBits = mode->red_bits;
3469 descr->cRedShift = mode->red_shift;
3470 descr->cGreenBits = mode->green_bits;
3471 descr->cGreenShift = mode->green_shift;
3472 descr->cBlueBits = mode->blue_bits;
3473 descr->cBlueShift = mode->blue_shift;
3474 descr->cAlphaBits = mode->alpha_bits;
3475 descr->cAlphaShift = mode->alpha_shift;
3477 if (pf->accum_mode)
3479 mode = &color_modes[pf->accum_mode - 1];
3480 descr->cAccumBits = mode->color_bits;
3481 descr->cAccumRedBits = mode->red_bits;
3482 descr->cAccumGreenBits = mode->green_bits;
3483 descr->cAccumBlueBits = mode->blue_bits;
3484 descr->cAccumAlphaBits = mode->alpha_bits;
3487 descr->cDepthBits = pf->depth_bits;
3488 descr->cStencilBits = pf->stencil_bits;
3489 descr->cAuxBuffers = pf->aux_buffers;
3490 descr->iLayerType = PFD_MAIN_PLANE;
3492 TRACE("%s\n", debugstr_pf(pf));
3493 return nb_displayable_formats;
3496 /***********************************************************************
3497 * macdrv_wglCopyContext
3499 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3501 CGLError err;
3503 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3505 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3506 if (err != kCGLNoError)
3507 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3508 return (err == kCGLNoError);
3511 /***********************************************************************
3512 * macdrv_wglCreateContext
3514 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3516 int format;
3517 struct wgl_context *context;
3519 TRACE("hdc %p\n", hdc);
3521 format = get_dc_pixel_format(hdc);
3523 if (!is_valid_pixel_format(format))
3525 ERR("Invalid pixel format %d, expect problems!\n", format);
3526 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3527 return NULL;
3530 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3532 context->format = format;
3533 if (!create_context(context, NULL))
3535 HeapFree(GetProcessHeap(), 0, context);
3536 return NULL;
3539 EnterCriticalSection(&context_section);
3540 list_add_tail(&context_list, &context->entry);
3541 LeaveCriticalSection(&context_section);
3543 return context;
3546 /***********************************************************************
3547 * macdrv_wglDeleteContext
3549 static void macdrv_wglDeleteContext(struct wgl_context *context)
3551 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3553 EnterCriticalSection(&context_section);
3554 list_remove(&context->entry);
3555 LeaveCriticalSection(&context_section);
3557 macdrv_dispose_opengl_context(context->context);
3558 HeapFree(GetProcessHeap(), 0, context);
3561 /***********************************************************************
3562 * macdrv_wglGetPixelFormat
3564 static int macdrv_wglGetPixelFormat(HDC hdc)
3566 int format;
3568 format = get_dc_pixel_format(hdc);
3570 if (!is_valid_pixel_format(format)) /* not set yet */
3571 format = 0;
3572 else if (!is_displayable_pixel_format(format))
3574 /* Non-displayable formats can't be used with traditional WGL calls.
3575 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3576 format = 1;
3579 TRACE(" hdc %p -> %d\n", hdc, format);
3580 return format;
3583 /***********************************************************************
3584 * macdrv_wglGetProcAddress
3586 static PROC macdrv_wglGetProcAddress(const char *proc)
3588 void *ret;
3590 if (!strncmp(proc, "wgl", 3)) return NULL;
3591 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3592 if (ret)
3594 if (TRACE_ON(wgl))
3596 Dl_info info;
3597 if (dladdr(ret, &info))
3598 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3599 else
3600 TRACE("%s -> %p (no library info)\n", proc, ret);
3603 else
3604 WARN("failed to find proc %s\n", debugstr_a(proc));
3605 return ret;
3608 /***********************************************************************
3609 * macdrv_wglMakeCurrent
3611 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3613 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3614 (context ? context->cglcontext : NULL));
3616 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3619 /**********************************************************************
3620 * macdrv_wglSetPixelFormat
3622 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3624 return set_pixel_format(hdc, fmt, FALSE);
3627 /***********************************************************************
3628 * macdrv_wglShareLists
3630 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3632 macdrv_opengl_context saved_context;
3633 CGLContextObj saved_cglcontext;
3635 TRACE("org %p dest %p\n", org, dest);
3637 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3638 * at context creation time but in case of WGL it is done using wglShareLists.
3640 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3641 * and when a program requests sharing we recreate the destination context if it hasn't been made
3642 * current or when it hasn't shared display lists before.
3645 if (dest->has_been_current)
3647 WARN("could not share display lists, the destination context has been current already\n");
3648 return FALSE;
3650 else if (dest->sharing)
3652 WARN("could not share display lists because dest has already shared lists before\n");
3653 return FALSE;
3656 /* Re-create the Mac context and share display lists */
3657 saved_context = dest->context;
3658 saved_cglcontext = dest->cglcontext;
3659 dest->context = NULL;
3660 dest->cglcontext = NULL;
3661 if (!create_context(dest, org->cglcontext))
3663 dest->context = saved_context;
3664 dest->cglcontext = saved_cglcontext;
3665 return FALSE;
3668 /* Implicitly disposes of saved_cglcontext. */
3669 macdrv_dispose_opengl_context(saved_context);
3671 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3672 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3674 org->sharing = TRUE;
3675 dest->sharing = TRUE;
3677 return TRUE;
3680 /**********************************************************************
3681 * macdrv_wglSwapBuffers
3683 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3685 struct wgl_context *context = NtCurrentTeb()->glContext;
3686 BOOL match = FALSE;
3687 HWND hwnd;
3689 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3690 (context ? context->cglcontext : NULL));
3692 if (context)
3693 sync_swap_interval(context);
3695 if ((hwnd = WindowFromDC(hdc)))
3697 struct macdrv_win_data *data;
3699 if (!(data = get_win_data(hwnd)))
3701 SetLastError(ERROR_INVALID_HANDLE);
3702 return FALSE;
3705 if (context && context->draw_view == data->gl_view)
3706 match = TRUE;
3708 release_win_data(data);
3710 else
3712 struct wgl_pbuffer *pbuffer;
3714 EnterCriticalSection(&dc_pbuffers_section);
3715 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3716 LeaveCriticalSection(&dc_pbuffers_section);
3718 if (!pbuffer)
3720 SetLastError(ERROR_INVALID_HANDLE);
3721 return FALSE;
3724 if (context && context->draw_pbuffer == pbuffer)
3725 match = TRUE;
3728 if (match)
3729 macdrv_flush_opengl_context(context->context);
3730 else
3732 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3734 /* If there is a current context, then wglSwapBuffers should do an implicit
3735 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3736 in the other branch, but we have to do it explicitly here. */
3737 if (context)
3738 pglFlush();
3741 return TRUE;
3744 static struct opengl_funcs opengl_funcs =
3747 macdrv_wglCopyContext, /* p_wglCopyContext */
3748 macdrv_wglCreateContext, /* p_wglCreateContext */
3749 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3750 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3751 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3752 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3753 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3754 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3755 macdrv_wglShareLists, /* p_wglShareLists */
3756 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3760 /**********************************************************************
3761 * macdrv_wine_get_wgl_driver
3763 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3765 if (version != WINE_WGL_DRIVER_VERSION)
3767 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3768 return NULL;
3771 if (!init_opengl()) return (void *)-1;
3773 return &opengl_funcs;