winemac: Fix wglSwapBuffers() to operate on the HDC, not the current GL context.
[wine/multimedia.git] / dlls / winemac.drv / opengl.c
blobf1a3a79ca5b6b47de2f790d0c26f7bad9b5e325b
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 "wine/library.h"
30 #include "wine/debug.h"
31 #include "wine/wgl.h"
32 #include "wine/wgl_driver.h"
33 #include "wine/wglext.h"
35 #define __gl_h_
36 #define __gltypes_h_
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
40 #include <dlfcn.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
45 struct gl_info {
46 char *glVersion;
47 char *glExtensions;
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
54 static struct gl_info gl_info;
57 struct wgl_context
59 int format;
60 macdrv_opengl_context context;
61 CGLContextObj cglcontext;
62 macdrv_view draw_view;
63 struct wgl_pbuffer *draw_pbuffer;
64 macdrv_view read_view;
65 struct wgl_pbuffer *read_pbuffer;
66 BOOL has_been_current;
67 BOOL sharing;
68 DWORD last_flush_time;
72 struct wgl_pbuffer
74 CGLPBufferObj pbuffer;
75 int format;
76 BOOL no_texture;
77 int max_level;
78 GLint level;
79 GLenum face;
82 static CFMutableDictionaryRef dc_pbuffers;
84 static CRITICAL_SECTION dc_pbuffers_section;
85 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
87 0, 0, &dc_pbuffers_section,
88 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
89 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
91 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
94 static struct opengl_funcs opengl_funcs;
96 #define USE_GL_FUNC(name) #name,
97 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
98 #undef USE_GL_FUNC
101 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
102 GLsizei width);
103 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
104 static void (*pglFlush)(void);
105 static void (*pglFlushRenderAPPLE)(void);
106 static const GLubyte *(*pglGetString)(GLenum name);
107 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
108 GLenum format, GLenum type, void *pixels);
109 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
112 struct color_mode {
113 GLint mode;
114 int bits_per_pixel;
115 GLint color_bits; /* including alpha_bits */
116 int red_bits, red_shift;
117 int green_bits, green_shift;
118 int blue_bits, blue_shift;
119 GLint alpha_bits, alpha_shift;
120 BOOL is_float;
121 int color_ordering;
124 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
125 observations of the behavior of Windows systems, but also subjective judgments
126 about what color formats are more "normal" than others.
128 On at least some Windows systems, integer color formats are listed before
129 floating-point formats. Within the integer formats, higher color bits were
130 usually listed before lower color bits, while for floating-point formats it
131 was the reverse. However, that leads D3D to select 64-bit integer formats in
132 preference to 32-bit formats when the latter would be sufficient. It seems
133 that a 32-bit format is much more likely to be normally used in that case.
135 Also, there are certain odd color formats supported on the Mac which seem like
136 they would be less appropriate than more common ones. For instance, the color
137 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
138 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
139 components.
141 For two color formats which differ only in whether or not they have alpha bits,
142 we use the same ordering. pixel_format_comparator() gives alpha bits a
143 different weight than color formats.
145 static const struct color_mode color_modes[] = {
146 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
147 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
148 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
149 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
150 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
151 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
152 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
153 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
154 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
155 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
156 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
157 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
158 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
159 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
160 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
161 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
162 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
163 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
164 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
165 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
166 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
167 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
168 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
169 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
173 static const struct {
174 GLint mode;
175 int bits;
176 } depth_stencil_modes[] = {
177 { kCGL0Bit, 0 },
178 { kCGL1Bit, 1 },
179 { kCGL2Bit, 2 },
180 { kCGL3Bit, 3 },
181 { kCGL4Bit, 4 },
182 { kCGL5Bit, 5 },
183 { kCGL6Bit, 6 },
184 { kCGL8Bit, 8 },
185 { kCGL10Bit, 10 },
186 { kCGL12Bit, 12 },
187 { kCGL16Bit, 16 },
188 { kCGL24Bit, 24 },
189 { kCGL32Bit, 32 },
190 { kCGL48Bit, 48 },
191 { kCGL64Bit, 64 },
192 { kCGL96Bit, 96 },
193 { kCGL128Bit, 128 },
197 typedef struct {
198 GLint renderer_id;
199 GLint buffer_modes;
200 GLint color_modes;
201 GLint accum_modes;
202 GLint depth_modes;
203 GLint stencil_modes;
204 GLint max_aux_buffers;
205 GLint max_sample_buffers;
206 GLint max_samples;
207 BOOL offscreen;
208 BOOL accelerated;
209 BOOL backing_store;
210 BOOL window;
211 BOOL online;
212 } renderer_properties;
215 typedef struct {
216 unsigned int window:1;
217 unsigned int pbuffer:1;
218 unsigned int accelerated:1;
219 unsigned int color_mode:5; /* index into color_modes table */
220 unsigned int aux_buffers:3;
221 unsigned int depth_bits:8;
222 unsigned int stencil_bits:8;
223 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
224 unsigned int double_buffer:1;
225 unsigned int stereo:1;
226 unsigned int sample_buffers:1;
227 unsigned int samples:5;
228 unsigned int backing_store:1;
229 } pixel_format;
232 typedef union
234 pixel_format format;
235 UInt64 code;
236 } pixel_format_or_code;
237 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
240 static pixel_format *pixel_formats;
241 static int nb_formats, nb_displayable_formats;
244 static void *opengl_handle;
247 static const char* debugstr_attrib(int attrib, int value)
249 static const struct {
250 int attrib;
251 const char *name;
252 } attrib_names[] = {
253 #define ATTRIB(a) { a, #a }
254 ATTRIB(WGL_ACCELERATION_ARB),
255 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
256 ATTRIB(WGL_ACCUM_BITS_ARB),
257 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
258 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
259 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
260 ATTRIB(WGL_ALPHA_BITS_ARB),
261 ATTRIB(WGL_ALPHA_SHIFT_ARB),
262 ATTRIB(WGL_AUX_BUFFERS_ARB),
263 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
264 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
265 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
266 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
267 ATTRIB(WGL_BLUE_BITS_ARB),
268 ATTRIB(WGL_BLUE_SHIFT_ARB),
269 ATTRIB(WGL_COLOR_BITS_ARB),
270 ATTRIB(WGL_DEPTH_BITS_ARB),
271 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
272 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
273 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
274 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
275 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
276 ATTRIB(WGL_GREEN_BITS_ARB),
277 ATTRIB(WGL_GREEN_SHIFT_ARB),
278 ATTRIB(WGL_NEED_PALETTE_ARB),
279 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
280 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
281 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
282 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
283 ATTRIB(WGL_PIXEL_TYPE_ARB),
284 ATTRIB(WGL_RED_BITS_ARB),
285 ATTRIB(WGL_RED_SHIFT_ARB),
286 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
287 ATTRIB(WGL_SAMPLES_ARB),
288 ATTRIB(WGL_SHARE_ACCUM_ARB),
289 ATTRIB(WGL_SHARE_DEPTH_ARB),
290 ATTRIB(WGL_SHARE_STENCIL_ARB),
291 ATTRIB(WGL_STENCIL_BITS_ARB),
292 ATTRIB(WGL_STEREO_ARB),
293 ATTRIB(WGL_SUPPORT_GDI_ARB),
294 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
295 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
296 ATTRIB(WGL_SWAP_METHOD_ARB),
297 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
298 ATTRIB(WGL_TRANSPARENT_ARB),
299 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
300 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
301 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
302 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
303 #undef ATTRIB
305 int i;
306 const char *attrib_name = NULL;
307 const char *value_name = NULL;
309 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
311 if (attrib_names[i].attrib == attrib)
313 attrib_name = attrib_names[i].name;
314 break;
318 if (!attrib_name)
319 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
321 switch (attrib)
323 case WGL_ACCELERATION_ARB:
324 switch (value)
326 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
327 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
328 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
330 break;
331 case WGL_PIXEL_TYPE_ARB:
332 switch (value)
334 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
335 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
336 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
337 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
339 break;
340 case WGL_SWAP_METHOD_ARB:
341 switch (value)
343 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
344 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
345 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
347 break;
350 if (!value_name)
351 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
353 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
357 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
358 CGLRendererProperty property, GLint *value)
360 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
361 if (err != kCGLNoError)
362 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
363 return (err == kCGLNoError);
367 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
369 GLint value;
371 memset(properties, 0, sizeof(*properties));
373 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
374 properties->renderer_id = value & kCGLRendererIDMatchingMask;
376 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
377 properties->buffer_modes = value;
379 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
380 properties->color_modes = value;
382 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
383 properties->accum_modes = value;
385 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
386 properties->depth_modes = value;
388 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
389 properties->stencil_modes = value;
391 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
392 properties->max_aux_buffers = value;
394 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
395 properties->max_sample_buffers = value;
397 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
398 properties->max_samples = value;
400 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
401 properties->offscreen = (value != 0);
403 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
404 properties->accelerated = (value != 0);
406 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
407 properties->backing_store = (value != 0);
409 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
410 properties->window = (value != 0);
412 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
413 properties->online = (value != 0);
417 static void dump_renderer(const renderer_properties* renderer)
419 int i;
421 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
422 TRACE("Buffer modes:\n");
423 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
424 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
425 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
426 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
428 TRACE("Color buffer modes:\n");
429 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
431 if (renderer->color_modes & color_modes[i].mode)
433 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
434 if (color_modes[i].is_float)
435 TRACE(", Float");
436 TRACE("\n");
440 TRACE("Accumulation buffer sizes: { ");
441 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
443 if (renderer->accum_modes & color_modes[i].mode)
444 TRACE("%d, ", color_modes[i].color_bits);
446 TRACE("}\n");
448 TRACE("Depth buffer sizes: { ");
449 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
451 if (renderer->depth_modes & depth_stencil_modes[i].mode)
452 TRACE("%d, ", depth_stencil_modes[i].bits);
454 TRACE("}\n");
456 TRACE("Stencil buffer sizes: { ");
457 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
459 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
460 TRACE("%d, ", depth_stencil_modes[i].bits);
462 TRACE("}\n");
464 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
465 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
466 TRACE("Max. Samples: %d\n", renderer->max_samples);
467 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
468 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
469 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
470 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
471 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
475 static inline UInt64 code_for_pixel_format(const pixel_format* format)
477 pixel_format_or_code pfc;
479 pfc.code = 0;
480 pfc.format = *format;
481 return pfc.code;
485 static inline pixel_format pixel_format_for_code(UInt64 code)
487 pixel_format_or_code pfc;
489 pfc.code = code;
490 return pfc.format;
494 static const char *debugstr_pf(const pixel_format *pf)
496 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",
497 pf->window,
498 pf->pbuffer,
499 pf->accelerated,
500 color_modes[pf->color_mode].color_bits,
501 (color_modes[pf->color_mode].is_float ? "f" : ""),
502 color_modes[pf->color_mode].alpha_bits,
503 pf->depth_bits,
504 pf->stencil_bits,
505 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
506 pf->aux_buffers,
507 pf->backing_store,
508 pf->double_buffer,
509 pf->stereo,
510 pf->sample_buffers,
511 pf->samples,
512 code_for_pixel_format(pf));
516 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
518 int best = -1;
519 int i;
521 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
523 if ((modes & color_modes[i].mode) &&
524 color_modes[i].color_bits >= color_size &&
525 color_modes[i].alpha_bits >= alpha_size &&
526 !color_modes[i].is_float == !color_float)
528 if (best < 0) /* no existing best choice */
529 best = i;
530 else if (color_modes[i].color_bits == color_size &&
531 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
533 /* prefer it over a best which isn't exact or which has a higher bpp */
534 if (color_modes[best].color_bits != color_size ||
535 color_modes[best].alpha_bits != alpha_size ||
536 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
537 best = i;
539 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
540 (color_modes[i].color_bits == color_modes[best].color_bits &&
541 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
542 best = i;
546 if (best < 0)
548 /* Couldn't find a match. Return first one that renderer supports. */
549 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
551 if (modes & color_modes[i].mode)
552 return i;
556 return best;
560 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
562 int best = -1;
563 int i;
565 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
567 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
569 /* Prefer the fewest color bits, then prefer more alpha bits, then
570 prefer more bits per pixel. */
571 if (best < 0)
572 best = i;
573 else if (color_modes[i].color_bits < color_modes[best].color_bits)
574 best = i;
575 else if (color_modes[i].color_bits == color_modes[best].color_bits)
577 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
578 best = i;
579 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
580 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
581 best = i;
586 if (best < 0)
588 /* Couldn't find a match. Return last one that renderer supports. */
589 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
591 if (modes & color_modes[i].mode)
592 return i;
596 return best;
600 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
601 CFMutableSetRef pixel_format_set)
603 CGLPixelFormatAttribute attribs[64] = {
604 kCGLPFAMinimumPolicy,
605 kCGLPFAClosestPolicy,
606 kCGLPFARendererID, renderer.renderer_id,
607 kCGLPFASingleRenderer,
609 int n = 5, n_stack[16], n_stack_idx = -1;
610 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
611 new_pixel_formats = 0;
612 pixel_format request;
613 unsigned int double_buffer;
614 unsigned int accelerated = renderer.accelerated;
616 if (accelerated)
618 attribs[n++] = kCGLPFAAccelerated;
619 attribs[n++] = kCGLPFANoRecovery;
621 else if (!allow_software_rendering)
623 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
624 return;
627 n_stack[++n_stack_idx] = n;
628 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
630 unsigned int aux;
632 n = n_stack[n_stack_idx];
634 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
635 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
636 continue;
638 if (double_buffer)
639 attribs[n++] = kCGLPFADoubleBuffer;
640 memset(&request, 0, sizeof(request));
641 request.accelerated = accelerated;
642 request.double_buffer = double_buffer;
644 /* Don't bother with in-between aux buffers values: either 0 or max. */
645 n_stack[++n_stack_idx] = n;
646 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
648 unsigned int color_mode;
650 n = n_stack[n_stack_idx];
652 attribs[n++] = kCGLPFAAuxBuffers;
653 attribs[n++] = aux;
654 request.aux_buffers = aux;
656 n_stack[++n_stack_idx] = n;
657 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
659 unsigned int depth_mode;
661 n = n_stack[n_stack_idx];
663 if (!(renderer.color_modes & color_modes[color_mode].mode))
664 continue;
666 attribs[n++] = kCGLPFAColorSize;
667 attribs[n++] = color_modes[color_mode].color_bits;
668 attribs[n++] = kCGLPFAAlphaSize;
669 attribs[n++] = color_modes[color_mode].alpha_bits;
670 if (color_modes[color_mode].is_float)
671 attribs[n++] = kCGLPFAColorFloat;
672 request.color_mode = color_mode;
674 n_stack[++n_stack_idx] = n;
675 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
677 unsigned int stencil_mode;
679 n = n_stack[n_stack_idx];
681 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
682 continue;
684 attribs[n++] = kCGLPFADepthSize;
685 attribs[n++] = depth_stencil_modes[depth_mode].bits;
686 request.depth_bits = depth_stencil_modes[depth_mode].bits;
688 n_stack[++n_stack_idx] = n;
689 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
691 unsigned int stereo;
693 n = n_stack[n_stack_idx];
695 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
696 continue;
697 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
698 continue;
700 attribs[n++] = kCGLPFAStencilSize;
701 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
702 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
704 /* FIXME: Could trim search space a bit here depending on GPU.
705 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
706 n_stack[++n_stack_idx] = n;
707 for (stereo = 0; stereo <= 1; stereo++)
709 int accum_mode;
711 n = n_stack[n_stack_idx];
713 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
714 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
715 continue;
717 if (stereo)
718 attribs[n++] = kCGLPFAStereo;
719 request.stereo = stereo;
721 /* Starts at -1 for a 0 accum size */
722 n_stack[++n_stack_idx] = n;
723 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
725 unsigned int target_pass;
727 n = n_stack[n_stack_idx];
729 if (accum_mode >= 0)
731 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
732 continue;
734 attribs[n++] = kCGLPFAAccumSize;
735 attribs[n++] = color_modes[accum_mode].color_bits;
736 request.accum_mode = accum_mode + 1;
738 else
739 request.accum_mode = 0;
741 /* Targets to request are:
742 accelerated: window OR window + pbuffer
743 software: window + pbuffer */
744 n_stack[++n_stack_idx] = n;
745 for (target_pass = 0; target_pass <= accelerated; target_pass++)
747 unsigned int samples, max_samples;
749 n = n_stack[n_stack_idx];
751 attribs[n++] = kCGLPFAWindow;
752 request.window = 1;
754 if (!accelerated || target_pass > 0)
756 attribs[n++] = kCGLPFAPBuffer;
757 request.pbuffer = 1;
759 else
760 request.pbuffer = 0;
762 /* FIXME: Could trim search space a bit here depending on GPU.
763 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
764 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
765 n_stack[++n_stack_idx] = n;
766 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
767 for (samples = 1; samples <= max_samples; samples *= 2)
769 unsigned int backing_store, min_backing_store, max_backing_store;
771 n = n_stack[n_stack_idx];
773 if (samples > 1)
775 attribs[n++] = kCGLPFASampleBuffers;
776 attribs[n++] = renderer.max_sample_buffers;
777 attribs[n++] = kCGLPFASamples;
778 attribs[n++] = samples;
779 request.sample_buffers = renderer.max_sample_buffers;
780 request.samples = samples;
782 else
783 request.sample_buffers = request.samples = 0;
785 if (renderer.backing_store && double_buffer)
787 /* The software renderer seems to always preserve the backing store, whether
788 we ask for it or not. So don't bother not asking for it. */
789 min_backing_store = accelerated ? 0 : 1;
790 max_backing_store = 1;
792 else
793 min_backing_store = max_backing_store = 0;
794 n_stack[++n_stack_idx] = n;
795 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
797 CGLPixelFormatObj pix;
798 GLint virtualScreens;
799 CGLError err;
801 n = n_stack[n_stack_idx];
803 if (backing_store)
804 attribs[n++] = kCGLPFABackingStore;
805 request.backing_store = backing_store;
807 attribs[n] = 0;
809 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
810 if (err == kCGLNoError && pix)
812 pixel_format pf;
813 GLint value, color_size, alpha_size, color_float;
814 UInt64 pf_code;
815 CFNumberRef code_object;
816 BOOL dupe;
818 memset(&pf, 0, sizeof(pf));
820 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
821 pf.accelerated = value;
822 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
823 pf.aux_buffers = value;
824 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
825 pf.depth_bits = value;
826 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
827 pf.double_buffer = value;
828 if (pf.double_buffer &&
829 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
830 pf.backing_store = value;
831 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
832 pf.pbuffer = value;
833 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
834 pf.sample_buffers = value;
835 if (pf.sample_buffers &&
836 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
837 pf.samples = value;
838 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
839 pf.stencil_bits = value;
840 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
841 pf.stereo = value;
842 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
843 pf.window = value;
845 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
846 color_size = 0;
847 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
848 alpha_size = 0;
849 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
850 color_float = 0;
851 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
853 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
854 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
856 CGLReleasePixelFormat(pix);
858 pf_code = code_for_pixel_format(&pf);
860 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
861 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
862 dupe_pixel_formats++;
863 else
865 CFSetAddValue(pixel_format_set, code_object);
866 CFArrayAppendValue(pixel_format_array, code_object);
867 new_pixel_formats++;
869 CFRelease(code_object);
871 if (pf_code == code_for_pixel_format(&request))
872 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
873 else
875 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
876 dupe ? " (duplicate)" : "");
879 else
881 failed_pixel_formats++;
882 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
885 tried_pixel_formats++;
888 n_stack_idx--;
891 n_stack_idx--;
894 n_stack_idx--;
897 n_stack_idx--;
900 n_stack_idx--;
903 n_stack_idx--;
906 n_stack_idx--;
909 n_stack_idx--;
912 n_stack_idx--;
915 n_stack_idx--;
917 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
918 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
919 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
920 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
924 /* The docs for WGL_ARB_pixel_format say:
925 Indices are assigned to pixel formats in the following order:
926 1. Accelerated pixel formats that are displayable
927 2. Accelerated pixel formats that are displayable and which have
928 extended attributes
929 3. Generic pixel formats
930 4. Accelerated pixel formats that are non displayable
932 static int pixel_format_category(pixel_format pf)
934 /* non-displayable */
935 if (!pf.window)
936 return 4;
938 /* non-accelerated a.k.a. software a.k.a. generic */
939 if (!pf.accelerated)
940 return 3;
942 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
943 if (color_modes[pf.color_mode].is_float)
944 return 2;
946 /* accelerated, displayable, no extended attributes */
947 return 1;
951 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
953 CFNumberRef number1 = val1;
954 CFNumberRef number2 = val2;
955 UInt64 code1, code2;
956 pixel_format pf1, pf2;
957 int category1, category2;
959 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
960 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
961 pf1 = pixel_format_for_code(code1);
962 pf2 = pixel_format_for_code(code2);
963 category1 = pixel_format_category(pf1);
964 category2 = pixel_format_category(pf2);
966 if (category1 < category2)
967 return kCFCompareLessThan;
968 if (category1 > category2)
969 return kCFCompareGreaterThan;
971 /* Within a category, sort the "best" formats toward the front since that's
972 what wglChoosePixelFormatARB() has to do. The ordering implemented here
973 matches at least one Windows 7 machine's behavior.
975 /* Accelerated before unaccelerated. */
976 if (pf1.accelerated && !pf2.accelerated)
977 return kCFCompareLessThan;
978 if (!pf1.accelerated && pf2.accelerated)
979 return kCFCompareGreaterThan;
981 /* Explicit color mode ordering. */
982 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
983 return kCFCompareLessThan;
984 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
985 return kCFCompareGreaterThan;
987 /* Non-pbuffer-capable before pbuffer-capable. */
988 if (!pf1.pbuffer && pf2.pbuffer)
989 return kCFCompareLessThan;
990 if (pf1.pbuffer && !pf2.pbuffer)
991 return kCFCompareGreaterThan;
993 /* Fewer samples before more samples. */
994 if (pf1.samples < pf2.samples)
995 return kCFCompareLessThan;
996 if (pf1.samples > pf2.samples)
997 return kCFCompareGreaterThan;
999 /* Monoscopic before stereoscopic. (This is a guess.) */
1000 if (!pf1.stereo && pf2.stereo)
1001 return kCFCompareLessThan;
1002 if (pf1.stereo && !pf2.stereo)
1003 return kCFCompareGreaterThan;
1005 /* Single buffered before double buffered. */
1006 if (!pf1.double_buffer && pf2.double_buffer)
1007 return kCFCompareLessThan;
1008 if (pf1.double_buffer && !pf2.double_buffer)
1009 return kCFCompareGreaterThan;
1011 /* Possibly-optimized double buffering before backing-store-preserving
1012 double buffering. */
1013 if (!pf1.backing_store && pf2.backing_store)
1014 return kCFCompareLessThan;
1015 if (pf1.backing_store && !pf2.backing_store)
1016 return kCFCompareGreaterThan;
1018 /* Bigger depth buffer before smaller depth buffer. */
1019 if (pf1.depth_bits > pf2.depth_bits)
1020 return kCFCompareLessThan;
1021 if (pf1.depth_bits < pf2.depth_bits)
1022 return kCFCompareGreaterThan;
1024 /* Smaller stencil buffer before bigger stencil buffer. */
1025 if (pf1.stencil_bits < pf2.stencil_bits)
1026 return kCFCompareLessThan;
1027 if (pf1.stencil_bits > pf2.stencil_bits)
1028 return kCFCompareGreaterThan;
1030 /* Smaller alpha bits before larger alpha bits. */
1031 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1032 return kCFCompareLessThan;
1033 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1034 return kCFCompareGreaterThan;
1036 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1037 if (pf1.accum_mode)
1039 if (pf2.accum_mode)
1041 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1042 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1043 return kCFCompareLessThan;
1044 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1045 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1046 return kCFCompareGreaterThan;
1048 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1049 return kCFCompareLessThan;
1050 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1051 return kCFCompareGreaterThan;
1053 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1054 return kCFCompareLessThan;
1055 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1056 return kCFCompareGreaterThan;
1058 else
1059 return kCFCompareGreaterThan;
1061 else if (pf2.accum_mode)
1062 return kCFCompareLessThan;
1064 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1065 if (pf1.aux_buffers < pf2.aux_buffers)
1066 return kCFCompareLessThan;
1067 if (pf1.aux_buffers > pf2.aux_buffers)
1068 return kCFCompareGreaterThan;
1070 /* If we get here, arbitrarily sort based on code. */
1071 if (code1 < code2)
1072 return kCFCompareLessThan;
1073 if (code1 > code2)
1074 return kCFCompareGreaterThan;
1075 return kCFCompareEqualTo;
1079 static BOOL init_pixel_formats(void)
1081 BOOL ret = FALSE;
1082 CGLRendererInfoObj renderer_info;
1083 GLint rendererCount;
1084 CGLError err;
1085 CFMutableSetRef pixel_format_set;
1086 CFMutableArrayRef pixel_format_array;
1087 int i;
1088 CFRange range;
1090 TRACE("()\n");
1092 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1093 if (err)
1095 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1096 return FALSE;
1099 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1100 if (!pixel_format_set)
1102 WARN("CFSetCreateMutable failed\n");
1103 CGLDestroyRendererInfo(renderer_info);
1104 return FALSE;
1107 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1108 if (!pixel_format_array)
1110 WARN("CFArrayCreateMutable failed\n");
1111 CFRelease(pixel_format_set);
1112 CGLDestroyRendererInfo(renderer_info);
1113 return FALSE;
1116 for (i = 0; i < rendererCount; i++)
1118 renderer_properties renderer;
1120 get_renderer_properties(renderer_info, i, &renderer);
1121 if (TRACE_ON(wgl))
1123 TRACE("renderer_properties %d:\n", i);
1124 dump_renderer(&renderer);
1127 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1130 CFRelease(pixel_format_set);
1131 CGLDestroyRendererInfo(renderer_info);
1133 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1134 if (range.length)
1136 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1137 if (pixel_formats)
1139 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1140 for (i = 0; i < range.length; i++)
1142 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1143 UInt64 code;
1145 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1146 pixel_formats[i] = pixel_format_for_code(code);
1147 if (pixel_formats[i].window)
1148 nb_displayable_formats++;
1151 nb_formats = range.length;
1152 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1153 ret = TRUE;
1155 else
1156 WARN("failed to allocate pixel format list\n");
1158 else
1159 WARN("got no pixel formats\n");
1161 CFRelease(pixel_format_array);
1162 return ret;
1166 static inline BOOL is_valid_pixel_format(int format)
1168 return format > 0 && format <= nb_formats;
1172 static inline BOOL is_displayable_pixel_format(int format)
1174 return format > 0 && format <= nb_displayable_formats;
1178 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1180 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1181 * format in case of probing the number of pixel formats.
1183 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1185 TRACE("Returning format %d\n", format);
1186 return &pixel_formats[format - 1];
1188 return NULL;
1192 static BOOL init_gl_info(void)
1194 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1195 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1197 CGDirectDisplayID display = CGMainDisplayID();
1198 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1199 CGLPixelFormatAttribute attribs[] = {
1200 kCGLPFADisplayMask, displayMask,
1203 CGLPixelFormatObj pix;
1204 GLint virtualScreens;
1205 CGLError err;
1206 CGLContextObj context;
1207 CGLContextObj old_context = CGLGetCurrentContext();
1208 const char *str;
1209 size_t length;
1211 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1212 if (err != kCGLNoError || !pix)
1214 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1215 return FALSE;
1218 err = CGLCreateContext(pix, NULL, &context);
1219 CGLReleasePixelFormat(pix);
1220 if (err != kCGLNoError || !context)
1222 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1223 return FALSE;
1226 err = CGLSetCurrentContext(context);
1227 if (err != kCGLNoError)
1229 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1230 CGLReleaseContext(context);
1231 return FALSE;
1234 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1235 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1236 strcpy(gl_info.glVersion, str);
1237 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1238 length = strlen(str) + sizeof(legacy_extensions);
1239 if (allow_vsync)
1240 length += strlen(legacy_ext_swap_control);
1241 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1242 strcpy(gl_info.glExtensions, str);
1243 strcat(gl_info.glExtensions, legacy_extensions);
1244 if (allow_vsync)
1245 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1247 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1249 TRACE("GL version : %s\n", gl_info.glVersion);
1250 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1252 CGLSetCurrentContext(old_context);
1253 CGLReleaseContext(context);
1255 return TRUE;
1259 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1261 BOOL ret = TRUE;
1262 *rect = data->client_rect;
1264 if (data->cocoa_window)
1266 if (window)
1267 *window = data->cocoa_window;
1268 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1270 else
1272 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1273 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1274 struct macdrv_win_data *top_data = get_win_data(top);
1276 if (top_data && top_data->cocoa_window)
1278 if (window)
1279 *window = top_data->cocoa_window;
1280 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1281 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1283 else
1284 ret = FALSE;
1286 release_win_data(top_data);
1289 return ret;
1293 /***********************************************************************
1294 * set_win_format
1296 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1298 macdrv_window cocoa_window;
1300 TRACE("hwnd %p format %d\n", data->hwnd, format);
1302 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1304 ERR("no top-level parent with Cocoa window in this process\n");
1305 return FALSE;
1308 if (data->gl_view) macdrv_dispose_view(data->gl_view);
1309 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1311 if (!data->gl_view)
1313 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1314 return FALSE;
1317 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1318 wine_dbgstr_rect(&data->gl_rect));
1320 data->pixel_format = format;
1322 return TRUE;
1326 /**********************************************************************
1327 * set_pixel_format
1329 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1331 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1333 struct macdrv_win_data *data;
1334 const pixel_format *pf;
1335 HWND hwnd = WindowFromDC(hdc);
1336 BOOL ret = FALSE;
1338 TRACE("hdc %p format %d\n", hdc, fmt);
1340 if (!hwnd || hwnd == GetDesktopWindow())
1342 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1343 return FALSE;
1346 if (!(data = get_win_data(hwnd)))
1348 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1349 return FALSE;
1352 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1354 ret = (data->pixel_format == fmt);
1355 goto done;
1358 /* Check if fmt is in our list of supported formats to see if it is supported. */
1359 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1360 if (!pf)
1362 ERR("Invalid pixel format: %d\n", fmt);
1363 goto done;
1366 if (!pf->window)
1368 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1369 goto done;
1372 if (!set_win_format(data, fmt))
1374 WARN("Couldn't set format of the window, returning failure\n");
1375 goto done;
1378 TRACE("pixel format:\n");
1379 TRACE(" window: %u\n", (unsigned int)pf->window);
1380 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1381 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1382 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1383 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1384 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1385 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1386 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1387 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1388 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1389 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1390 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1391 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1392 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1393 ret = TRUE;
1395 done:
1396 release_win_data(data);
1397 if (ret) __wine_set_pixel_format(hwnd, fmt);
1398 return ret;
1402 /**********************************************************************
1403 * set_gl_view_parent
1405 void set_gl_view_parent(HWND hwnd, HWND parent)
1407 struct macdrv_win_data *data;
1409 if (!(data = get_win_data(hwnd))) return;
1411 if (data->gl_view)
1413 macdrv_window cocoa_window;
1415 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1417 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1419 ERR("no top-level parent with Cocoa window in this process\n");
1420 macdrv_dispose_view(data->gl_view);
1421 data->gl_view = NULL;
1422 release_win_data(data);
1423 __wine_set_pixel_format( hwnd, 0 );
1424 return;
1427 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1430 release_win_data(data);
1434 /**********************************************************************
1435 * make_context_current
1437 static void make_context_current(struct wgl_context *context, BOOL read)
1439 macdrv_view view;
1440 struct wgl_pbuffer *pbuffer;
1442 if (read)
1444 view = context->read_view;
1445 pbuffer = context->read_pbuffer;
1447 else
1449 view = context->draw_view;
1450 pbuffer = context->draw_pbuffer;
1453 if (view || !pbuffer)
1454 macdrv_make_context_current(context->context, view);
1455 else
1457 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1458 pbuffer->level, 0);
1459 CGLSetCurrentContext(context->cglcontext);
1464 /**********************************************************************
1465 * macdrv_glCopyColorTable
1467 * Hook into glCopyColorTable as part of the implementation of
1468 * wglMakeContextCurrentARB. If the context has a separate readable,
1469 * temporarily make that current, do glCopyColorTable, and then set it
1470 * back to the drawable. This is modeled after what Mesa GLX's Apple
1471 * implementation does.
1473 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1474 GLsizei width)
1476 struct wgl_context *context = NtCurrentTeb()->glContext;
1478 if (context->read_view || context->read_pbuffer)
1479 make_context_current(context, TRUE);
1481 pglCopyColorTable(target, internalformat, x, y, width);
1483 if (context->read_view || context->read_pbuffer)
1484 make_context_current(context, FALSE);
1488 /**********************************************************************
1489 * macdrv_glCopyPixels
1491 * Hook into glCopyPixels as part of the implementation of
1492 * wglMakeContextCurrentARB. If the context has a separate readable,
1493 * temporarily make that current, do glCopyPixels, and then set it back
1494 * to the drawable. This is modeled after what Mesa GLX's Apple
1495 * implementation does.
1497 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1499 struct wgl_context *context = NtCurrentTeb()->glContext;
1501 if (context->read_view || context->read_pbuffer)
1502 make_context_current(context, TRUE);
1504 pglCopyPixels(x, y, width, height, type);
1506 if (context->read_view || context->read_pbuffer)
1507 make_context_current(context, FALSE);
1511 static void macdrv_glFlush(void)
1513 struct wgl_context *context = NtCurrentTeb()->glContext;
1514 const pixel_format *pf = &pixel_formats[context->format - 1];
1515 DWORD now = GetTickCount();
1517 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1518 context->last_flush_time, now);
1519 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1521 TRACE("calling glFlushRenderAPPLE()\n");
1522 pglFlushRenderAPPLE();
1524 else
1526 TRACE("calling glFlush()\n");
1527 pglFlush();
1528 context->last_flush_time = now;
1533 /**********************************************************************
1534 * macdrv_glGetString
1536 * Hook into glGetString in order to return some legacy WGL extensions
1537 * that couldn't be advertised via the standard
1538 * WGL_ARB_extensions_string mechanism. Some programs, especially
1539 * older ones, expect to find certain older extensions, such as
1540 * WGL_EXT_extensions_string itself, in the standard GL extensions
1541 * string, and won't query any other WGL extensions unless they find
1542 * that particular extension there.
1544 static const GLubyte *macdrv_glGetString(GLenum name)
1546 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1547 return (const GLubyte *)gl_info.glExtensions;
1548 else
1549 return pglGetString(name);
1553 /**********************************************************************
1554 * macdrv_glReadPixels
1556 * Hook into glReadPixels as part of the implementation of
1557 * wglMakeContextCurrentARB. If the context has a separate readable,
1558 * temporarily make that current, do glReadPixels, and then set it back
1559 * to the drawable. This is modeled after what Mesa GLX's Apple
1560 * implementation does.
1562 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1563 GLenum format, GLenum type, void *pixels)
1565 struct wgl_context *context = NtCurrentTeb()->glContext;
1567 if (context->read_view || context->read_pbuffer)
1568 make_context_current(context, TRUE);
1570 pglReadPixels(x, y, width, height, format, type, pixels);
1572 if (context->read_view || context->read_pbuffer)
1573 make_context_current(context, FALSE);
1577 /**********************************************************************
1578 * macdrv_glViewport
1580 * Hook into glViewport as an opportunity to update the OpenGL context
1581 * if necessary. This is modeled after what Mesa GLX's Apple
1582 * implementation does.
1584 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1586 struct wgl_context *context = NtCurrentTeb()->glContext;
1588 macdrv_update_opengl_context(context->context);
1589 pglViewport(x, y, width, height);
1593 /***********************************************************************
1594 * macdrv_wglBindTexImageARB
1596 * WGL_ARB_render_texture: wglBindTexImageARB
1598 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1600 struct wgl_context *context = NtCurrentTeb()->glContext;
1601 GLenum source;
1602 CGLError err;
1604 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1606 if (pbuffer->no_texture)
1608 SetLastError(ERROR_INVALID_OPERATION);
1609 return GL_FALSE;
1612 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1613 opengl_funcs.gl.p_glFlush();
1615 switch (iBuffer)
1617 case WGL_FRONT_LEFT_ARB:
1618 if (pixel_formats[pbuffer->format - 1].stereo)
1619 source = GL_FRONT_LEFT;
1620 else
1621 source = GL_FRONT;
1622 break;
1623 case WGL_FRONT_RIGHT_ARB:
1624 source = GL_FRONT_RIGHT;
1625 break;
1626 case WGL_BACK_LEFT_ARB:
1627 if (pixel_formats[pbuffer->format - 1].stereo)
1628 source = GL_BACK_LEFT;
1629 else
1630 source = GL_BACK;
1631 break;
1632 case WGL_BACK_RIGHT_ARB:
1633 source = GL_BACK_RIGHT;
1634 break;
1635 case WGL_AUX0_ARB: source = GL_AUX0; break;
1636 case WGL_AUX1_ARB: source = GL_AUX1; break;
1637 case WGL_AUX2_ARB: source = GL_AUX2; break;
1638 case WGL_AUX3_ARB: source = GL_AUX3; break;
1640 case WGL_AUX4_ARB:
1641 case WGL_AUX5_ARB:
1642 case WGL_AUX6_ARB:
1643 case WGL_AUX7_ARB:
1644 case WGL_AUX8_ARB:
1645 case WGL_AUX9_ARB:
1646 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1647 SetLastError(ERROR_INVALID_DATA);
1648 return GL_FALSE;
1650 default:
1651 WARN("unknown source buffer 0x%x\n", iBuffer);
1652 SetLastError(ERROR_INVALID_DATA);
1653 return GL_FALSE;
1656 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1657 if (err != kCGLNoError)
1659 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1660 SetLastError(ERROR_INVALID_OPERATION);
1661 return GL_FALSE;
1664 return GL_TRUE;
1668 /***********************************************************************
1669 * macdrv_wglChoosePixelFormatARB
1671 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1673 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1674 const FLOAT *pfAttribFList, UINT nMaxFormats,
1675 int *piFormats, UINT *nNumFormats)
1677 pixel_format pf, valid;
1678 const int *iptr;
1679 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1680 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1681 int float_color;
1682 BOOL srgb;
1683 int i, found = 0;
1685 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1686 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1687 if (pfAttribFList)
1688 FIXME("unused pfAttribFList\n");
1690 memset(&pf, 0, sizeof(pf));
1691 memset(&valid, 0, sizeof(valid));
1692 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1693 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1694 float_color = -1;
1695 srgb = FALSE;
1697 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1699 int attr = iptr[0];
1700 int value = iptr[1];
1702 TRACE("%s\n", debugstr_attrib(attr, value));
1704 switch (attr)
1706 case WGL_DRAW_TO_WINDOW_ARB:
1707 if (valid.window && (!pf.window != !value)) goto cant_match;
1708 pf.window = (value != 0);
1709 valid.window = 1;
1710 break;
1712 case WGL_DRAW_TO_BITMAP_ARB:
1713 goto cant_match;
1715 case WGL_ACCELERATION_ARB:
1716 if (value == WGL_FULL_ACCELERATION_ARB)
1717 value = 1;
1718 else if (value == WGL_NO_ACCELERATION_ARB)
1719 value = 0;
1720 else
1721 goto cant_match;
1722 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1723 pf.accelerated = value;
1724 valid.accelerated = 1;
1725 break;
1727 case WGL_NEED_PALETTE_ARB:
1728 case WGL_NEED_SYSTEM_PALETTE_ARB:
1729 case WGL_SWAP_LAYER_BUFFERS_ARB:
1730 if (value) goto cant_match;
1731 break;
1733 case WGL_SWAP_METHOD_ARB:
1734 if (value == WGL_SWAP_COPY_ARB)
1735 value = 1;
1736 else if (value == WGL_SWAP_UNDEFINED_ARB)
1737 value = 0;
1738 else
1739 goto cant_match;
1740 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1741 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1742 pf.backing_store = value;
1743 valid.backing_store = 1;
1744 break;
1746 case WGL_NUMBER_OVERLAYS_ARB:
1747 case WGL_NUMBER_UNDERLAYS_ARB:
1748 if (value) goto cant_match;
1749 break;
1751 case WGL_SHARE_DEPTH_ARB:
1752 case WGL_SHARE_STENCIL_ARB:
1753 case WGL_SHARE_ACCUM_ARB:
1754 /* no effect */
1755 break;
1757 case WGL_SUPPORT_GDI_ARB:
1758 if (value) goto cant_match;
1759 break;
1761 case WGL_SUPPORT_OPENGL_ARB:
1762 if (!value) goto cant_match;
1763 break;
1765 case WGL_DOUBLE_BUFFER_ARB:
1766 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1767 pf.double_buffer = (value != 0);
1768 valid.double_buffer = 1;
1769 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1770 break;
1772 case WGL_STEREO_ARB:
1773 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1774 pf.stereo = (value != 0);
1775 valid.stereo = 1;
1776 break;
1778 case WGL_PIXEL_TYPE_ARB:
1779 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1780 value = 1;
1781 else if (value == WGL_TYPE_RGBA_ARB)
1782 value = 0;
1783 else
1785 /* Mac contexts don't support rendering to unsigned floating
1786 point formats, even if GL_EXT_packed_float is supported.
1787 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1788 goto cant_match;
1790 if (float_color != -1 && float_color != value) goto cant_match;
1791 if (srgb && value) goto cant_match;
1792 float_color = value;
1793 break;
1795 case WGL_COLOR_BITS_ARB:
1796 if (color_bits < value) color_bits = value;
1797 break;
1799 case WGL_RED_BITS_ARB:
1800 if (srgb && value > 8) goto cant_match;
1801 if (red_bits < value) red_bits = value;
1802 break;
1804 case WGL_GREEN_BITS_ARB:
1805 if (srgb && value > 8) goto cant_match;
1806 if (green_bits < value) green_bits = value;
1807 break;
1809 case WGL_BLUE_BITS_ARB:
1810 if (srgb && value > 8) goto cant_match;
1811 if (blue_bits < value) blue_bits = value;
1812 break;
1814 case WGL_ALPHA_BITS_ARB:
1815 if (alpha_bits < value) alpha_bits = value;
1816 break;
1818 case WGL_ACCUM_BITS_ARB:
1819 if (accum_bits < value) accum_bits = value;
1820 break;
1822 case WGL_ACCUM_RED_BITS_ARB:
1823 if (accum_red_bits < value) accum_red_bits = value;
1824 break;
1826 case WGL_ACCUM_GREEN_BITS_ARB:
1827 if (accum_green_bits < value) accum_green_bits = value;
1828 break;
1830 case WGL_ACCUM_BLUE_BITS_ARB:
1831 if (accum_blue_bits < value) accum_blue_bits = value;
1832 break;
1834 case WGL_ACCUM_ALPHA_BITS_ARB:
1835 if (accum_alpha_bits < value) accum_alpha_bits = value;
1836 break;
1838 case WGL_DEPTH_BITS_ARB:
1839 if (value > 255) goto cant_match;
1840 if (pf.depth_bits < value) pf.depth_bits = value;
1841 break;
1843 case WGL_STENCIL_BITS_ARB:
1844 if (value > 255) goto cant_match;
1845 if (pf.stencil_bits < value) pf.stencil_bits = value;
1846 break;
1848 case WGL_AUX_BUFFERS_ARB:
1849 if (value > 7) goto cant_match;
1850 if (pf.aux_buffers < value) pf.aux_buffers = value;
1851 break;
1853 case WGL_SAMPLE_BUFFERS_ARB:
1854 if (value > 1) goto cant_match;
1855 if (pf.sample_buffers < value) pf.sample_buffers = value;
1856 break;
1858 case WGL_SAMPLES_ARB:
1859 if (value > 31) goto cant_match;
1860 if (pf.samples < value) pf.samples = value;
1861 break;
1863 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1864 /* sRGB is only supported for 8-bit integer color components */
1865 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1866 goto cant_match;
1867 srgb = TRUE;
1868 break;
1870 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1871 case WGL_RED_SHIFT_ARB:
1872 case WGL_GREEN_SHIFT_ARB:
1873 case WGL_BLUE_SHIFT_ARB:
1874 case WGL_ALPHA_SHIFT_ARB:
1875 case WGL_TRANSPARENT_ARB:
1876 case WGL_TRANSPARENT_RED_VALUE_ARB:
1877 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1878 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1879 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1880 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1881 /* ignored */
1882 break;
1884 case WGL_DRAW_TO_PBUFFER_ARB:
1885 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1886 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1887 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1888 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1889 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1890 pf.pbuffer = (value != 0);
1891 valid.pbuffer = 1;
1892 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1893 !alpha_bits)
1894 alpha_bits = 1;
1895 break;
1897 default:
1898 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
1899 return GL_FALSE;
1903 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",
1904 valid.window ? (pf.window ? "1" : "0") : "?",
1905 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
1906 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
1907 color_bits,
1908 float_color == -1 ? "?" : float_color ? "f" : "",
1909 red_bits,
1910 green_bits,
1911 blue_bits,
1912 alpha_bits,
1913 (int)srgb,
1914 accum_bits,
1915 accum_red_bits,
1916 accum_green_bits,
1917 accum_blue_bits,
1918 accum_alpha_bits,
1919 pf.depth_bits,
1920 pf.stencil_bits,
1921 pf.aux_buffers,
1922 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
1923 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
1924 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
1925 pf.sample_buffers,
1926 pf.samples);
1928 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
1930 const struct color_mode *mode;
1932 if (valid.window && pixel_formats[i].window != pf.window) continue;
1933 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
1934 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
1935 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
1936 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
1937 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
1939 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
1940 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
1941 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
1942 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
1943 if (pixel_formats[i].samples < pf.samples) continue;
1945 mode = &color_modes[pixel_formats[i].color_mode];
1946 /* If the mode doesn't have alpha, check requested color bits against
1947 bits per pixel instead of the mode's color bits. On Windows, color
1948 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1949 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1950 expects that to match such a pixel format, we need to accommodate that. */
1951 if (mode->alpha_bits)
1953 if (mode->color_bits < color_bits)
1954 continue;
1956 else
1958 if (mode->bits_per_pixel < color_bits)
1959 continue;
1961 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
1962 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
1963 continue;
1964 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
1965 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
1966 continue;
1968 if (pixel_formats[i].accum_mode)
1970 mode = &color_modes[pixel_formats[i].accum_mode - 1];
1971 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
1972 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
1973 mode->alpha_bits < accum_alpha_bits)
1974 continue;
1976 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
1977 continue;
1979 piFormats[found++] = i + 1;
1980 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
1983 cant_match:
1984 *nNumFormats = found;
1986 return TRUE;
1990 /**********************************************************************
1991 * macdrv_wglCreatePbufferARB
1993 * WGL_ARB_pbuffer: wglCreatePbufferARB
1995 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
1996 const int *piAttribList)
1998 struct wgl_pbuffer* pbuffer;
1999 GLenum target = 0;
2000 GLenum internalFormat = 0;
2001 CGLError err;
2003 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2004 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2006 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2008 WARN("invalid pixel format %d\n", iPixelFormat);
2009 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2010 return NULL;
2013 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2014 pbuffer->format = iPixelFormat;
2016 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2018 int attr = piAttribList[0];
2019 int value = piAttribList[1];
2021 switch (attr)
2023 case WGL_PBUFFER_LARGEST_ARB:
2024 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2025 break;
2027 case WGL_TEXTURE_FORMAT_ARB:
2028 switch (value)
2030 case WGL_TEXTURE_RGBA_ARB:
2031 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2032 internalFormat = GL_RGBA;
2033 break;
2034 case WGL_TEXTURE_RGB_ARB:
2035 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2036 internalFormat = GL_RGB;
2037 break;
2038 case WGL_NO_TEXTURE_ARB:
2039 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2040 internalFormat = 0;
2041 break;
2042 default:
2043 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2044 SetLastError(ERROR_INVALID_DATA);
2045 goto done;
2047 break;
2049 case WGL_TEXTURE_TARGET_ARB:
2050 pbuffer->face = 0;
2051 switch (value)
2053 case WGL_NO_TEXTURE_ARB:
2054 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2055 target = 0;
2056 break;
2057 case WGL_TEXTURE_CUBE_MAP_ARB:
2058 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2059 target = GL_TEXTURE_CUBE_MAP;
2060 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2061 break;
2062 case WGL_TEXTURE_1D_ARB:
2063 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2064 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2065 goto done;
2066 case WGL_TEXTURE_2D_ARB:
2067 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2068 target = GL_TEXTURE_2D;
2069 break;
2070 case WGL_TEXTURE_RECTANGLE_NV:
2071 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2072 target = GL_TEXTURE_RECTANGLE;
2073 break;
2074 default:
2075 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2076 SetLastError(ERROR_INVALID_DATA);
2077 goto done;
2079 break;
2081 case WGL_MIPMAP_TEXTURE_ARB:
2082 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2083 pbuffer->max_level = 0;
2084 if (value)
2086 int size = min(iWidth, iHeight) / 2;
2087 while (size)
2089 pbuffer->max_level++;
2090 size /= 2;
2093 break;
2095 default:
2096 WARN("unknown attribute 0x%x\n", attr);
2097 SetLastError(ERROR_INVALID_DATA);
2098 goto done;
2102 if (!target || !internalFormat)
2104 pbuffer->no_texture = TRUE;
2105 /* no actual way to turn off ability to texture; use most permissive target */
2106 target = GL_TEXTURE_RECTANGLE;
2107 internalFormat = GL_RGB;
2110 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2111 if (err != kCGLNoError)
2113 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2114 pbuffer->pbuffer = NULL;
2115 if (err == kCGLBadAlloc)
2116 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2117 else
2118 SetLastError(ERROR_INVALID_DATA);
2121 done:
2122 if (!pbuffer->pbuffer)
2124 HeapFree(GetProcessHeap(), 0, pbuffer);
2125 return NULL;
2128 TRACE(" -> %p\n", pbuffer);
2129 return pbuffer;
2133 /**********************************************************************
2134 * macdrv_wglDestroyPbufferARB
2136 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2138 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2140 TRACE("pbuffer %p\n", pbuffer);
2141 if (pbuffer && pbuffer->pbuffer)
2142 CGLReleasePBuffer(pbuffer->pbuffer);
2143 HeapFree(GetProcessHeap(), 0, pbuffer);
2144 return GL_TRUE;
2148 /**********************************************************************
2149 * macdrv_wglGetExtensionsStringARB
2151 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2153 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2155 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2156 this can be specific to the CGL renderer like we're supposed to do. */
2157 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2158 return gl_info.wglExtensions;
2162 /**********************************************************************
2163 * macdrv_wglGetExtensionsStringEXT
2165 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2167 static const char *macdrv_wglGetExtensionsStringEXT(void)
2169 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2170 return gl_info.wglExtensions;
2174 /**********************************************************************
2175 * macdrv_wglGetPbufferDCARB
2177 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2179 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2181 HDC hdc;
2182 struct wgl_pbuffer *prev;
2184 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2185 if (!hdc) return 0;
2187 EnterCriticalSection(&dc_pbuffers_section);
2188 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2189 if (prev)
2191 CGLReleasePBuffer(prev->pbuffer);
2192 HeapFree(GetProcessHeap(), 0, prev);
2194 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2195 LeaveCriticalSection(&dc_pbuffers_section);
2197 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2198 return hdc;
2202 /**********************************************************************
2203 * macdrv_wglGetPixelFormatAttribivARB
2205 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2207 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2208 UINT nAttributes, const int *piAttributes, int *piValues)
2210 const pixel_format *pf;
2211 UINT i;
2213 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2214 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2216 if (!nAttributes) return GL_TRUE;
2218 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2220 piValues[0] = nb_formats;
2221 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2222 return GL_TRUE;
2225 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2226 if (!pf)
2228 WARN("invalid pixel format %d\n", iPixelFormat);
2229 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2230 return GL_FALSE;
2233 for (i = 0; i < nAttributes; ++i)
2235 switch (piAttributes[i])
2237 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2238 piValues[i] = nb_formats;
2239 break;
2241 case WGL_DRAW_TO_WINDOW_ARB:
2242 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2243 break;
2245 case WGL_DRAW_TO_BITMAP_ARB:
2246 piValues[i] = GL_FALSE;
2247 break;
2249 case WGL_ACCELERATION_ARB:
2250 if (iLayerPlane) goto invalid_layer;
2251 if (pf->accelerated)
2252 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2253 else
2254 piValues[i] = WGL_NO_ACCELERATION_ARB;
2255 break;
2257 case WGL_NEED_PALETTE_ARB:
2258 case WGL_NEED_SYSTEM_PALETTE_ARB:
2259 case WGL_SWAP_LAYER_BUFFERS_ARB:
2260 piValues[i] = GL_FALSE;
2261 break;
2263 case WGL_SWAP_METHOD_ARB:
2264 if (pf->double_buffer && pf->backing_store)
2265 piValues[i] = WGL_SWAP_COPY_ARB;
2266 else
2267 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2268 break;
2270 case WGL_NUMBER_OVERLAYS_ARB:
2271 case WGL_NUMBER_UNDERLAYS_ARB:
2272 piValues[i] = 0;
2273 break;
2275 case WGL_TRANSPARENT_ARB:
2276 if (iLayerPlane) goto invalid_layer;
2277 piValues[i] = GL_FALSE;
2278 break;
2280 case WGL_TRANSPARENT_RED_VALUE_ARB:
2281 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2282 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2283 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2284 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2285 if (iLayerPlane) goto invalid_layer;
2286 piValues[i] = 0;
2287 break;
2289 case WGL_SHARE_DEPTH_ARB:
2290 case WGL_SHARE_STENCIL_ARB:
2291 case WGL_SHARE_ACCUM_ARB:
2292 if (iLayerPlane) goto invalid_layer;
2293 piValues[i] = GL_TRUE;
2294 break;
2296 case WGL_SUPPORT_GDI_ARB:
2297 if (iLayerPlane) goto invalid_layer;
2298 piValues[i] = GL_FALSE;
2299 break;
2301 case WGL_SUPPORT_OPENGL_ARB:
2302 if (iLayerPlane) goto invalid_layer;
2303 piValues[i] = GL_TRUE;
2304 break;
2306 case WGL_DOUBLE_BUFFER_ARB:
2307 if (iLayerPlane) goto invalid_layer;
2308 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2309 break;
2311 case WGL_STEREO_ARB:
2312 if (iLayerPlane) goto invalid_layer;
2313 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2314 break;
2316 case WGL_PIXEL_TYPE_ARB:
2317 if (iLayerPlane) goto invalid_layer;
2318 if (color_modes[pf->color_mode].is_float)
2319 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2320 else
2321 piValues[i] = WGL_TYPE_RGBA_ARB;
2322 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2323 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2324 However, Mac contexts don't support rendering to unsigned floating-point
2325 formats, even when GL_EXT_packed_float is supported. */
2326 break;
2328 case WGL_COLOR_BITS_ARB:
2329 if (iLayerPlane) goto invalid_layer;
2330 /* If the mode doesn't have alpha, return bits per pixel instead
2331 of color bits. On Windows, color bits sometimes exceeds r+g+b
2332 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2333 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2334 pixel format, we need to accommodate that. */
2335 if (color_modes[pf->color_mode].alpha_bits)
2336 piValues[i] = color_modes[pf->color_mode].color_bits;
2337 else
2338 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2339 break;
2341 case WGL_RED_BITS_ARB:
2342 if (iLayerPlane) goto invalid_layer;
2343 piValues[i] = color_modes[pf->color_mode].red_bits;
2344 break;
2346 case WGL_RED_SHIFT_ARB:
2347 if (iLayerPlane) goto invalid_layer;
2348 piValues[i] = color_modes[pf->color_mode].red_shift;
2349 break;
2351 case WGL_GREEN_BITS_ARB:
2352 if (iLayerPlane) goto invalid_layer;
2353 piValues[i] = color_modes[pf->color_mode].green_bits;
2354 break;
2356 case WGL_GREEN_SHIFT_ARB:
2357 if (iLayerPlane) goto invalid_layer;
2358 piValues[i] = color_modes[pf->color_mode].green_shift;
2359 break;
2361 case WGL_BLUE_BITS_ARB:
2362 if (iLayerPlane) goto invalid_layer;
2363 piValues[i] = color_modes[pf->color_mode].blue_bits;
2364 break;
2366 case WGL_BLUE_SHIFT_ARB:
2367 if (iLayerPlane) goto invalid_layer;
2368 piValues[i] = color_modes[pf->color_mode].blue_shift;
2369 break;
2371 case WGL_ALPHA_BITS_ARB:
2372 if (iLayerPlane) goto invalid_layer;
2373 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2374 break;
2376 case WGL_ALPHA_SHIFT_ARB:
2377 if (iLayerPlane) goto invalid_layer;
2378 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2379 break;
2381 case WGL_ACCUM_BITS_ARB:
2382 if (iLayerPlane) goto invalid_layer;
2383 if (pf->accum_mode)
2384 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2385 else
2386 piValues[i] = 0;
2387 break;
2389 case WGL_ACCUM_RED_BITS_ARB:
2390 if (iLayerPlane) goto invalid_layer;
2391 if (pf->accum_mode)
2392 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2393 else
2394 piValues[i] = 0;
2395 break;
2397 case WGL_ACCUM_GREEN_BITS_ARB:
2398 if (iLayerPlane) goto invalid_layer;
2399 if (pf->accum_mode)
2400 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2401 else
2402 piValues[i] = 0;
2403 break;
2405 case WGL_ACCUM_BLUE_BITS_ARB:
2406 if (iLayerPlane) goto invalid_layer;
2407 if (pf->accum_mode)
2408 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2409 else
2410 piValues[i] = 0;
2411 break;
2413 case WGL_ACCUM_ALPHA_BITS_ARB:
2414 if (iLayerPlane) goto invalid_layer;
2415 if (pf->accum_mode)
2416 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2417 else
2418 piValues[i] = 0;
2419 break;
2421 case WGL_DEPTH_BITS_ARB:
2422 if (iLayerPlane) goto invalid_layer;
2423 piValues[i] = pf->depth_bits;
2424 break;
2426 case WGL_STENCIL_BITS_ARB:
2427 if (iLayerPlane) goto invalid_layer;
2428 piValues[i] = pf->stencil_bits;
2429 break;
2431 case WGL_AUX_BUFFERS_ARB:
2432 if (iLayerPlane) goto invalid_layer;
2433 piValues[i] = pf->aux_buffers;
2434 break;
2436 case WGL_SAMPLE_BUFFERS_ARB:
2437 if (iLayerPlane) goto invalid_layer;
2438 piValues[i] = pf->sample_buffers;
2439 break;
2441 case WGL_SAMPLES_ARB:
2442 if (iLayerPlane) goto invalid_layer;
2443 piValues[i] = pf->samples;
2444 break;
2446 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2447 if (iLayerPlane) goto invalid_layer;
2448 /* sRGB is only supported for 8-bit integer color components */
2449 if (color_modes[pf->color_mode].red_bits == 8 &&
2450 color_modes[pf->color_mode].green_bits == 8 &&
2451 color_modes[pf->color_mode].blue_bits == 8 &&
2452 !color_modes[pf->color_mode].is_float)
2453 piValues[i] = GL_TRUE;
2454 else
2455 piValues[i] = GL_FALSE;
2456 break;
2458 case WGL_DRAW_TO_PBUFFER_ARB:
2459 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2460 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2461 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2462 break;
2464 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2465 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2466 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2467 break;
2469 case WGL_MAX_PBUFFER_WIDTH_ARB:
2470 piValues[i] = gl_info.max_viewport_dims[0];
2471 break;
2473 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2474 piValues[i] = gl_info.max_viewport_dims[1];
2475 break;
2477 case WGL_MAX_PBUFFER_PIXELS_ARB:
2478 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2479 break;
2481 default:
2482 WARN("invalid attribute %x\n", piAttributes[i]);
2483 return GL_FALSE;
2486 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2489 return GL_TRUE;
2491 invalid_layer:
2492 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2493 return GL_FALSE;
2497 /**********************************************************************
2498 * macdrv_wglGetPixelFormatAttribfvARB
2500 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2502 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2503 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2505 int *attr;
2506 int ret;
2508 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2509 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2511 /* Allocate a temporary array to store integer values */
2512 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2513 if (!attr)
2515 ERR("couldn't allocate %d array\n", nAttributes);
2516 return GL_FALSE;
2519 /* Piggy-back on wglGetPixelFormatAttribivARB */
2520 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2521 if (ret)
2523 UINT i;
2525 /* Convert integer values to float. Should also check for attributes
2526 that can give decimal values here */
2527 for (i = 0; i < nAttributes; i++)
2528 pfValues[i] = attr[i];
2531 HeapFree(GetProcessHeap(), 0, attr);
2532 return ret;
2536 /**********************************************************************
2537 * macdrv_wglGetSwapIntervalEXT
2539 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2541 static int macdrv_wglGetSwapIntervalEXT(void)
2543 struct wgl_context *context = NtCurrentTeb()->glContext;
2544 long value;
2545 CGLError err;
2547 TRACE("\n");
2549 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2550 if (err != kCGLNoError)
2552 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2553 err, CGLErrorString(err));
2554 value = 1;
2557 return value;
2561 /***********************************************************************
2562 * macdrv_wglMakeContextCurrentARB
2564 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2566 * This is not supported directly by OpenGL on the Mac. We emulate it
2567 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2568 * temporarily swap the drawable. This follows the technique used in
2569 * the implementation of Mesa GLX for Apple.
2571 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2573 struct macdrv_win_data *data;
2574 HWND hwnd;
2576 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2577 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2579 if (!context)
2581 macdrv_make_context_current(NULL, NULL);
2582 NtCurrentTeb()->glContext = NULL;
2583 return TRUE;
2586 if ((hwnd = WindowFromDC(draw_hdc)))
2588 if (!(data = get_win_data(hwnd)))
2590 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2591 return FALSE;
2594 if (!data->pixel_format)
2596 WARN("no pixel format set\n");
2597 release_win_data(data);
2598 SetLastError(ERROR_INVALID_HANDLE);
2599 return FALSE;
2601 if (context->format != data->pixel_format)
2603 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2604 release_win_data(data);
2605 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2606 return FALSE;
2609 context->draw_view = data->gl_view;
2610 context->draw_pbuffer = NULL;
2611 release_win_data(data);
2613 else
2615 struct wgl_pbuffer *pbuffer;
2617 EnterCriticalSection(&dc_pbuffers_section);
2618 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2619 if (pbuffer)
2621 if (context->format != pbuffer->format)
2623 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2624 LeaveCriticalSection(&dc_pbuffers_section);
2625 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2626 return FALSE;
2629 else
2631 WARN("no window or pbuffer for DC\n");
2632 LeaveCriticalSection(&dc_pbuffers_section);
2633 SetLastError(ERROR_INVALID_HANDLE);
2634 return FALSE;
2637 context->draw_view = NULL;
2638 context->draw_pbuffer = pbuffer;
2639 LeaveCriticalSection(&dc_pbuffers_section);
2642 context->read_view = NULL;
2643 context->read_pbuffer = NULL;
2644 if (read_hdc && read_hdc != draw_hdc)
2646 if ((hwnd = WindowFromDC(read_hdc)))
2648 if ((data = get_win_data(hwnd)))
2650 if (data->gl_view != context->draw_view)
2651 context->read_view = data->gl_view;
2652 release_win_data(data);
2655 else
2657 EnterCriticalSection(&dc_pbuffers_section);
2658 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2659 LeaveCriticalSection(&dc_pbuffers_section);
2663 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2664 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2666 make_context_current(context, FALSE);
2667 context->has_been_current = TRUE;
2668 NtCurrentTeb()->glContext = context;
2670 return TRUE;
2674 /**********************************************************************
2675 * macdrv_wglQueryPbufferARB
2677 * WGL_ARB_pbuffer: wglQueryPbufferARB
2679 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2681 CGLError err;
2682 GLsizei width;
2683 GLsizei height;
2684 GLenum target;
2685 GLenum internalFormat;
2686 GLint mipmap;
2688 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2690 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2691 if (err != kCGLNoError)
2693 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2694 SetLastError(ERROR_INVALID_HANDLE);
2695 return GL_FALSE;
2698 switch (iAttribute)
2700 case WGL_PBUFFER_WIDTH_ARB:
2701 *piValue = width;
2702 break;
2703 case WGL_PBUFFER_HEIGHT_ARB:
2704 *piValue = height;
2705 break;
2706 case WGL_PBUFFER_LOST_ARB:
2707 /* Mac PBuffers can't be lost */
2708 *piValue = GL_FALSE;
2709 break;
2710 case WGL_TEXTURE_FORMAT_ARB:
2711 if (pbuffer->no_texture)
2712 *piValue = WGL_NO_TEXTURE_ARB;
2713 else switch (internalFormat)
2715 case GL_RGBA:
2716 *piValue = WGL_TEXTURE_RGBA_ARB;
2717 break;
2718 case GL_RGB:
2719 default:
2720 *piValue = WGL_TEXTURE_RGB_ARB;
2721 break;
2723 break;
2724 case WGL_TEXTURE_TARGET_ARB:
2725 if (pbuffer->no_texture)
2726 *piValue = WGL_NO_TEXTURE_ARB;
2727 else switch (target)
2729 case GL_TEXTURE_CUBE_MAP:
2730 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2731 break;
2732 case GL_TEXTURE_2D:
2733 *piValue = WGL_TEXTURE_2D_ARB;
2734 break;
2735 case GL_TEXTURE_RECTANGLE:
2736 default:
2737 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2738 break;
2740 break;
2741 case WGL_MIPMAP_TEXTURE_ARB:
2742 *piValue = (pbuffer->max_level > 0);
2743 break;
2744 case WGL_MIPMAP_LEVEL_ARB:
2745 *piValue = pbuffer->level;
2746 break;
2747 case WGL_CUBE_MAP_FACE_ARB:
2748 switch (pbuffer->face)
2750 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2751 default:
2752 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2753 break;
2754 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2755 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2756 break;
2757 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2758 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2759 break;
2760 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2761 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2762 break;
2763 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2764 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2765 break;
2766 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2767 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2768 break;
2770 break;
2771 default:
2772 WARN("invalid attribute 0x%x\n", iAttribute);
2773 SetLastError(ERROR_INVALID_DATA);
2774 return GL_FALSE;
2777 return GL_TRUE;
2781 /**********************************************************************
2782 * macdrv_wglReleasePbufferDCARB
2784 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2786 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2788 struct wgl_pbuffer *prev;
2790 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2792 EnterCriticalSection(&dc_pbuffers_section);
2794 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2795 if (prev)
2797 if (prev != pbuffer)
2798 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2799 CGLReleasePBuffer(prev->pbuffer);
2800 HeapFree(GetProcessHeap(), 0, prev);
2801 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2803 else hdc = 0;
2805 LeaveCriticalSection(&dc_pbuffers_section);
2807 return hdc && DeleteDC(hdc);
2811 /**********************************************************************
2812 * macdrv_wglReleaseTexImageARB
2814 * WGL_ARB_render_texture: wglReleaseTexImageARB
2816 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2818 struct wgl_context *context = NtCurrentTeb()->glContext;
2819 CGLError err;
2821 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2823 if (pbuffer->no_texture)
2825 SetLastError(ERROR_INVALID_OPERATION);
2826 return GL_FALSE;
2829 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2830 if (err != kCGLNoError)
2832 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2833 SetLastError(ERROR_INVALID_OPERATION);
2834 return GL_FALSE;
2837 return GL_TRUE;
2841 /**********************************************************************
2842 * macdrv_wglSetPbufferAttribARB
2844 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2846 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2848 struct wgl_context *context = NtCurrentTeb()->glContext;
2850 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2852 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2854 int attr = piAttribList[0];
2855 int value = piAttribList[1];
2856 switch (attr)
2858 case WGL_MIPMAP_LEVEL_ARB:
2859 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2860 pbuffer->level = value;
2861 break;
2862 case WGL_CUBE_MAP_FACE_ARB:
2863 switch (value)
2865 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2866 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2867 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2868 break;
2869 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2870 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2871 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2872 break;
2873 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2874 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2875 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2876 break;
2877 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2878 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2879 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2880 break;
2881 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2882 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2883 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2884 break;
2885 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2886 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2887 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2888 break;
2889 default:
2890 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2891 SetLastError(ERROR_INVALID_DATA);
2892 return GL_FALSE;
2894 break;
2895 default:
2896 WARN("invalide attribute 0x%x\n", attr);
2897 SetLastError(ERROR_INVALID_DATA);
2898 return GL_FALSE;
2902 if (context && context->draw_pbuffer == pbuffer)
2903 make_context_current(context, FALSE);
2905 return GL_TRUE;
2909 /**********************************************************************
2910 * macdrv_wglSetPixelFormatWINE
2912 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2914 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
2916 return set_pixel_format(hdc, fmt, TRUE);
2920 /**********************************************************************
2921 * macdrv_wglSwapIntervalEXT
2923 * WGL_EXT_swap_control: wglSwapIntervalEXT
2925 static BOOL macdrv_wglSwapIntervalEXT(int interval)
2927 struct wgl_context *context = NtCurrentTeb()->glContext;
2928 long value;
2929 CGLError err;
2931 TRACE("interval %d\n", interval);
2933 if (interval < 0)
2935 SetLastError(ERROR_INVALID_DATA);
2936 return FALSE;
2939 if (!pixel_formats[context->format - 1].double_buffer)
2940 interval = 0;
2941 else if (interval > 1)
2942 interval = 1;
2944 value = interval;
2945 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2946 if (err != kCGLNoError)
2948 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2949 err, CGLErrorString(err));
2950 SetLastError(ERROR_GEN_FAILURE);
2951 return FALSE;
2954 return TRUE;
2958 static void register_extension(const char *ext)
2960 if (gl_info.wglExtensions[0])
2961 strcat(gl_info.wglExtensions, " ");
2962 strcat(gl_info.wglExtensions, ext);
2964 TRACE("'%s'\n", ext);
2967 static void load_extensions(void)
2970 * ARB Extensions
2972 register_extension("WGL_ARB_extensions_string");
2973 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
2975 register_extension("WGL_ARB_make_current_read");
2976 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
2977 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
2979 register_extension("WGL_ARB_pixel_format");
2980 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
2981 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
2982 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
2984 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
2986 register_extension("WGL_ARB_pixel_format_float");
2987 register_extension("WGL_ATI_pixel_format_float");
2990 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
2991 register_extension("WGL_ARB_multisample");
2993 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2994 register_extension("WGL_ARB_framebuffer_sRGB");
2996 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
2998 register_extension("WGL_ARB_pbuffer");
2999 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3000 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3001 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3002 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3003 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3005 register_extension("WGL_ARB_render_texture");
3006 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3007 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3008 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3010 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3011 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3012 register_extension("WGL_NV_render_texture_rectangle");
3015 /* TODO:
3016 WGL_ARB_create_context: wglCreateContextAttribsARB
3017 WGL_ARB_create_context_profile
3021 * EXT Extensions
3023 register_extension("WGL_EXT_extensions_string");
3024 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3026 if (allow_vsync)
3028 register_extension("WGL_EXT_swap_control");
3029 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3030 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3033 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3034 check for either, so register them separately. */
3035 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3036 register_extension("WGL_EXT_framebuffer_sRGB");
3038 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3039 register_extension("WGL_EXT_pixel_format_packed_float");
3042 * WINE-specific WGL Extensions
3045 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3046 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3048 register_extension("WGL_WINE_pixel_format_passthrough");
3049 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3053 static BOOL init_opengl(void)
3055 static BOOL init_done = FALSE;
3056 unsigned int i;
3057 char buffer[200];
3059 if (init_done) return (opengl_handle != NULL);
3060 init_done = TRUE;
3062 TRACE("()\n");
3064 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3065 if (!dc_pbuffers)
3067 WARN("CFDictionaryCreateMutable failed\n");
3068 return FALSE;
3071 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3072 if (!opengl_handle)
3074 ERR("Failed to load OpenGL: %s\n", buffer);
3075 ERR("OpenGL support is disabled.\n");
3076 return FALSE;
3079 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3081 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3083 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3084 goto failed;
3088 /* redirect some standard OpenGL functions */
3089 #define REDIRECT(func) \
3090 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3091 REDIRECT(glCopyPixels);
3092 REDIRECT(glGetString);
3093 REDIRECT(glReadPixels);
3094 REDIRECT(glViewport);
3095 if (skip_single_buffer_flushes)
3096 REDIRECT(glFlush);
3097 #undef REDIRECT
3099 /* redirect some OpenGL extension functions */
3100 #define REDIRECT(func) \
3101 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3102 REDIRECT(glCopyColorTable);
3103 #undef REDIRECT
3105 if (!init_gl_info())
3106 goto failed;
3108 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3109 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3111 load_extensions();
3112 if (!init_pixel_formats())
3113 goto failed;
3115 return TRUE;
3117 failed:
3118 wine_dlclose(opengl_handle, NULL, 0);
3119 opengl_handle = NULL;
3120 return FALSE;
3124 /***********************************************************************
3125 * sync_gl_view
3127 * Synchronize the Mac GL view position with the Windows child window
3128 * position.
3130 void sync_gl_view(struct macdrv_win_data *data)
3132 RECT rect;
3134 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3136 if (!data->gl_view) return;
3138 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3140 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3141 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3142 data->gl_rect = rect;
3147 static int get_dc_pixel_format(HDC hdc)
3149 int format;
3150 HWND hwnd;
3152 if ((hwnd = WindowFromDC(hdc)))
3154 struct macdrv_win_data *data;
3156 if (!(data = get_win_data(hwnd)))
3158 FIXME("DC for window %p of other process: not implemented\n", hwnd);
3159 return 0;
3162 format = data->pixel_format;
3163 release_win_data(data);
3165 else
3167 struct wgl_pbuffer *pbuffer;
3169 EnterCriticalSection(&dc_pbuffers_section);
3170 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3171 if (pbuffer)
3172 format = pbuffer->format;
3173 else
3175 WARN("no window or pbuffer for DC %p\n", hdc);
3176 format = 0;
3178 LeaveCriticalSection(&dc_pbuffers_section);
3181 return format;
3185 /**********************************************************************
3186 * create_context
3188 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
3190 const pixel_format *pf;
3191 CGLPixelFormatAttribute attribs[64];
3192 int n = 0;
3193 CGLPixelFormatObj pix;
3194 GLint virtualScreens;
3195 CGLError err;
3196 long swap_interval;
3198 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
3199 if (!pf)
3201 ERR("Invalid pixel format %d, expect problems!\n", context->format);
3202 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3203 return FALSE;
3206 attribs[n++] = kCGLPFAMinimumPolicy;
3207 attribs[n++] = kCGLPFAClosestPolicy;
3209 if (pf->accelerated)
3211 attribs[n++] = kCGLPFAAccelerated;
3212 attribs[n++] = kCGLPFANoRecovery;
3214 else
3216 attribs[n++] = kCGLPFARendererID;
3217 attribs[n++] = kCGLRendererGenericFloatID;
3220 if (pf->double_buffer)
3221 attribs[n++] = kCGLPFADoubleBuffer;
3223 attribs[n++] = kCGLPFAAuxBuffers;
3224 attribs[n++] = pf->aux_buffers;
3226 attribs[n++] = kCGLPFAColorSize;
3227 attribs[n++] = color_modes[pf->color_mode].color_bits;
3228 attribs[n++] = kCGLPFAAlphaSize;
3229 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3230 if (color_modes[pf->color_mode].is_float)
3231 attribs[n++] = kCGLPFAColorFloat;
3233 attribs[n++] = kCGLPFADepthSize;
3234 attribs[n++] = pf->depth_bits;
3236 attribs[n++] = kCGLPFAStencilSize;
3237 attribs[n++] = pf->stencil_bits;
3239 if (pf->stereo)
3240 attribs[n++] = kCGLPFAStereo;
3242 if (pf->accum_mode)
3244 attribs[n++] = kCGLPFAAccumSize;
3245 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3248 if (pf->window)
3249 attribs[n++] = kCGLPFAWindow;
3250 if (pf->pbuffer)
3251 attribs[n++] = kCGLPFAPBuffer;
3253 if (pf->sample_buffers && pf->samples)
3255 attribs[n++] = kCGLPFASampleBuffers;
3256 attribs[n++] = pf->sample_buffers;
3257 attribs[n++] = kCGLPFASamples;
3258 attribs[n++] = pf->samples;
3261 if (pf->backing_store)
3262 attribs[n++] = kCGLPFABackingStore;
3264 attribs[n] = 0;
3266 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3267 if (err != kCGLNoError || !pix)
3269 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3270 return FALSE;
3273 err = CGLCreateContext(pix, share, &context->cglcontext);
3274 CGLReleasePixelFormat(pix);
3275 if (err != kCGLNoError || !context->cglcontext)
3277 context->cglcontext = NULL;
3278 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3279 return FALSE;
3282 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3283 a context is 1. CGL contexts default to 0, so we need to set it. This
3284 only make sense for double-buffered contexts, though. In theory, for
3285 single-buffered contexts, there's no such thing as a swap. But OS X
3286 will synchronize flushes of single-buffered contexts if this is set. */
3287 if (pf->double_buffer && allow_vsync)
3288 swap_interval = 1;
3289 else
3290 swap_interval = 0;
3291 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&swap_interval);
3292 if (err != kCGLNoError)
3293 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err, CGLErrorString(err));
3295 context->context = macdrv_create_opengl_context(context->cglcontext);
3296 CGLReleaseContext(context->cglcontext);
3297 if (!context->context)
3299 WARN("macdrv_create_opengl_context() failed\n");
3300 return FALSE;
3303 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3305 return TRUE;
3309 /**********************************************************************
3310 * macdrv_wglDescribePixelFormat
3312 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3314 const pixel_format *pf;
3315 const struct color_mode *mode;
3317 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3319 if (!descr) return nb_displayable_formats;
3320 if (size < sizeof(*descr)) return 0;
3322 if (!(pf = get_pixel_format(fmt, FALSE)))
3323 return 0;
3325 memset(descr, 0, sizeof(*descr));
3326 descr->nSize = sizeof(*descr);
3327 descr->nVersion = 1;
3329 descr->dwFlags = PFD_SUPPORT_OPENGL;
3330 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3331 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3332 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3333 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3334 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3336 descr->iPixelType = PFD_TYPE_RGBA;
3338 mode = &color_modes[pf->color_mode];
3339 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3340 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3341 R8G8B8A0 pixel format). If an app depends on that and expects that
3342 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3343 if (mode->alpha_bits)
3344 descr->cColorBits = mode->color_bits;
3345 else
3346 descr->cColorBits = mode->bits_per_pixel;
3347 descr->cRedBits = mode->red_bits;
3348 descr->cRedShift = mode->red_shift;
3349 descr->cGreenBits = mode->green_bits;
3350 descr->cGreenShift = mode->green_shift;
3351 descr->cBlueBits = mode->blue_bits;
3352 descr->cBlueShift = mode->blue_shift;
3353 descr->cAlphaBits = mode->alpha_bits;
3354 descr->cAlphaShift = mode->alpha_shift;
3356 if (pf->accum_mode)
3358 mode = &color_modes[pf->accum_mode - 1];
3359 descr->cAccumBits = mode->color_bits;
3360 descr->cAccumRedBits = mode->red_bits;
3361 descr->cAccumGreenBits = mode->green_bits;
3362 descr->cAccumBlueBits = mode->blue_bits;
3363 descr->cAccumAlphaBits = mode->alpha_bits;
3366 descr->cDepthBits = pf->depth_bits;
3367 descr->cStencilBits = pf->stencil_bits;
3368 descr->cAuxBuffers = pf->aux_buffers;
3369 descr->iLayerType = PFD_MAIN_PLANE;
3371 TRACE("%s\n", debugstr_pf(pf));
3372 return nb_displayable_formats;
3375 /***********************************************************************
3376 * macdrv_wglCopyContext
3378 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3380 CGLError err;
3382 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3384 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3385 if (err != kCGLNoError)
3386 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3387 return (err == kCGLNoError);
3390 /***********************************************************************
3391 * macdrv_wglCreateContext
3393 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3395 int format;
3396 struct wgl_context *context;
3398 TRACE("hdc %p\n", hdc);
3400 format = get_dc_pixel_format(hdc);
3402 if (!is_valid_pixel_format(format))
3404 ERR("Invalid pixel format %d, expect problems!\n", format);
3405 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3406 return NULL;
3409 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3411 context->format = format;
3412 if (!create_context(context, NULL))
3414 HeapFree(GetProcessHeap(), 0, context);
3415 return NULL;
3418 return context;
3421 /***********************************************************************
3422 * macdrv_wglDeleteContext
3424 static void macdrv_wglDeleteContext(struct wgl_context *context)
3426 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3427 macdrv_dispose_opengl_context(context->context);
3428 HeapFree(GetProcessHeap(), 0, context);
3431 /***********************************************************************
3432 * macdrv_wglGetPixelFormat
3434 static int macdrv_wglGetPixelFormat(HDC hdc)
3436 int format;
3438 format = get_dc_pixel_format(hdc);
3440 if (!is_valid_pixel_format(format)) /* not set yet */
3441 format = 0;
3442 else if (!is_displayable_pixel_format(format))
3444 /* Non-displayable formats can't be used with traditional WGL calls.
3445 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3446 format = 1;
3449 TRACE(" hdc %p -> %d\n", hdc, format);
3450 return format;
3453 /***********************************************************************
3454 * macdrv_wglGetProcAddress
3456 static PROC macdrv_wglGetProcAddress(const char *proc)
3458 void *ret;
3460 if (!strncmp(proc, "wgl", 3)) return NULL;
3461 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3462 if (ret)
3464 if (TRACE_ON(wgl))
3466 Dl_info info;
3467 if (dladdr(ret, &info))
3468 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3469 else
3470 TRACE("%s -> %p (no library info)\n", proc, ret);
3473 else
3474 WARN("failed to find proc %s\n", debugstr_a(proc));
3475 return ret;
3478 /***********************************************************************
3479 * macdrv_wglMakeCurrent
3481 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3483 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3484 (context ? context->cglcontext : NULL));
3486 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3489 /**********************************************************************
3490 * macdrv_wglSetPixelFormat
3492 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3494 return set_pixel_format(hdc, fmt, FALSE);
3497 /***********************************************************************
3498 * macdrv_wglShareLists
3500 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3502 macdrv_opengl_context saved_context;
3503 CGLContextObj saved_cglcontext;
3505 TRACE("org %p dest %p\n", org, dest);
3507 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3508 * at context creation time but in case of WGL it is done using wglShareLists.
3510 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3511 * and when a program requests sharing we recreate the destination context if it hasn't been made
3512 * current or when it hasn't shared display lists before.
3515 if (dest->has_been_current)
3517 WARN("could not share display lists, the destination context has been current already\n");
3518 return FALSE;
3520 else if (dest->sharing)
3522 WARN("could not share display lists because dest has already shared lists before\n");
3523 return FALSE;
3526 /* Re-create the Mac context and share display lists */
3527 saved_context = dest->context;
3528 saved_cglcontext = dest->cglcontext;
3529 dest->context = NULL;
3530 dest->cglcontext = NULL;
3531 if (!create_context(dest, org->cglcontext))
3533 dest->context = saved_context;
3534 dest->cglcontext = saved_cglcontext;
3535 return FALSE;
3538 /* Implicitly disposes of saved_cglcontext. */
3539 macdrv_dispose_opengl_context(saved_context);
3541 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3542 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3544 org->sharing = TRUE;
3545 dest->sharing = TRUE;
3547 return TRUE;
3550 /**********************************************************************
3551 * macdrv_wglSwapBuffers
3553 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3555 struct wgl_context *context = NtCurrentTeb()->glContext;
3556 BOOL match = FALSE;
3557 HWND hwnd;
3559 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3560 (context ? context->cglcontext : NULL));
3562 if ((hwnd = WindowFromDC(hdc)))
3564 struct macdrv_win_data *data;
3566 if (!(data = get_win_data(hwnd)))
3568 SetLastError(ERROR_INVALID_HANDLE);
3569 return FALSE;
3572 if (context && context->draw_view == data->gl_view)
3573 match = TRUE;
3575 release_win_data(data);
3577 else
3579 struct wgl_pbuffer *pbuffer;
3581 EnterCriticalSection(&dc_pbuffers_section);
3582 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3583 LeaveCriticalSection(&dc_pbuffers_section);
3585 if (!pbuffer)
3587 SetLastError(ERROR_INVALID_HANDLE);
3588 return FALSE;
3591 if (context && context->draw_pbuffer == pbuffer)
3592 match = TRUE;
3595 if (match)
3596 macdrv_flush_opengl_context(context->context);
3597 else
3599 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3601 /* If there is a current context, then wglSwapBuffers should do an implicit
3602 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3603 in the other branch, but we have to do it explicitly here. */
3604 if (context)
3605 pglFlush();
3608 return TRUE;
3611 static struct opengl_funcs opengl_funcs =
3614 macdrv_wglCopyContext, /* p_wglCopyContext */
3615 macdrv_wglCreateContext, /* p_wglCreateContext */
3616 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3617 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3618 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3619 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3620 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3621 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3622 macdrv_wglShareLists, /* p_wglShareLists */
3623 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3627 /**********************************************************************
3628 * macdrv_wine_get_wgl_driver
3630 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3632 if (version != WINE_WGL_DRIVER_VERSION)
3634 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3635 return NULL;
3638 if (!init_opengl()) return (void *)-1;
3640 return &opengl_funcs;