po: Fix the 'All key' Korean translation.
[wine.git] / dlls / winemac.drv / opengl.c
blob0922371a230b1a779fe98be90701c97319f863fa
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 HDC hdc;
60 int format;
61 macdrv_opengl_context context;
62 CGLContextObj cglcontext;
63 macdrv_view draw_view;
64 struct wgl_pbuffer *draw_pbuffer;
65 macdrv_view read_view;
66 struct wgl_pbuffer *read_pbuffer;
67 BOOL has_been_current;
68 BOOL sharing;
69 DWORD last_flush_time;
73 struct wgl_pbuffer
75 CGLPBufferObj pbuffer;
76 int format;
77 BOOL no_texture;
78 int max_level;
79 GLint level;
80 GLenum face;
83 static CFMutableDictionaryRef dc_pbuffers;
85 static CRITICAL_SECTION dc_pbuffers_section;
86 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
88 0, 0, &dc_pbuffers_section,
89 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
90 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
92 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
95 static struct opengl_funcs opengl_funcs;
97 #define USE_GL_FUNC(name) #name,
98 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
99 #undef USE_GL_FUNC
102 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
103 GLsizei width);
104 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
105 static void (*pglFlush)(void);
106 static void (*pglFlushRenderAPPLE)(void);
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;
622 n_stack[++n_stack_idx] = n;
623 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
625 unsigned int aux;
627 n = n_stack[n_stack_idx];
629 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
630 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
631 continue;
633 if (double_buffer)
634 attribs[n++] = kCGLPFADoubleBuffer;
635 memset(&request, 0, sizeof(request));
636 request.accelerated = accelerated;
637 request.double_buffer = double_buffer;
639 /* Don't bother with in-between aux buffers values: either 0 or max. */
640 n_stack[++n_stack_idx] = n;
641 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
643 unsigned int color_mode;
645 n = n_stack[n_stack_idx];
647 attribs[n++] = kCGLPFAAuxBuffers;
648 attribs[n++] = aux;
649 request.aux_buffers = aux;
651 n_stack[++n_stack_idx] = n;
652 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
654 unsigned int depth_mode;
656 n = n_stack[n_stack_idx];
658 if (!(renderer.color_modes & color_modes[color_mode].mode))
659 continue;
661 attribs[n++] = kCGLPFAColorSize;
662 attribs[n++] = color_modes[color_mode].color_bits;
663 attribs[n++] = kCGLPFAAlphaSize;
664 attribs[n++] = color_modes[color_mode].alpha_bits;
665 if (color_modes[color_mode].is_float)
666 attribs[n++] = kCGLPFAColorFloat;
667 request.color_mode = color_mode;
669 n_stack[++n_stack_idx] = n;
670 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
672 unsigned int stencil_mode;
674 n = n_stack[n_stack_idx];
676 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
677 continue;
679 attribs[n++] = kCGLPFADepthSize;
680 attribs[n++] = depth_stencil_modes[depth_mode].bits;
681 request.depth_bits = depth_stencil_modes[depth_mode].bits;
683 n_stack[++n_stack_idx] = n;
684 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
686 unsigned int stereo;
688 n = n_stack[n_stack_idx];
690 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
691 continue;
692 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
693 continue;
695 attribs[n++] = kCGLPFAStencilSize;
696 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
697 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
699 /* FIXME: Could trim search space a bit here depending on GPU.
700 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
701 n_stack[++n_stack_idx] = n;
702 for (stereo = 0; stereo <= 1; stereo++)
704 int accum_mode;
706 n = n_stack[n_stack_idx];
708 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
709 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
710 continue;
712 if (stereo)
713 attribs[n++] = kCGLPFAStereo;
714 request.stereo = stereo;
716 /* Starts at -1 for a 0 accum size */
717 n_stack[++n_stack_idx] = n;
718 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
720 unsigned int target_pass;
722 n = n_stack[n_stack_idx];
724 if (accum_mode >= 0)
726 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
727 continue;
729 attribs[n++] = kCGLPFAAccumSize;
730 attribs[n++] = color_modes[accum_mode].color_bits;
731 request.accum_mode = accum_mode + 1;
733 else
734 request.accum_mode = 0;
736 /* Targets to request are:
737 accelerated: window OR window + pbuffer
738 software: window + pbuffer */
739 n_stack[++n_stack_idx] = n;
740 for (target_pass = 0; target_pass <= accelerated; target_pass++)
742 unsigned int samples, max_samples;
744 n = n_stack[n_stack_idx];
746 attribs[n++] = kCGLPFAWindow;
747 request.window = 1;
749 if (!accelerated || target_pass > 0)
751 attribs[n++] = kCGLPFAPBuffer;
752 request.pbuffer = 1;
754 else
755 request.pbuffer = 0;
757 /* FIXME: Could trim search space a bit here depending on GPU.
758 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
759 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
760 n_stack[++n_stack_idx] = n;
761 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
762 for (samples = 1; samples <= max_samples; samples *= 2)
764 unsigned int backing_store, min_backing_store, max_backing_store;
766 n = n_stack[n_stack_idx];
768 if (samples > 1)
770 attribs[n++] = kCGLPFASampleBuffers;
771 attribs[n++] = renderer.max_sample_buffers;
772 attribs[n++] = kCGLPFASamples;
773 attribs[n++] = samples;
774 request.sample_buffers = renderer.max_sample_buffers;
775 request.samples = samples;
777 else
778 request.sample_buffers = request.samples = 0;
780 if (renderer.backing_store && double_buffer)
782 /* The software renderer seems to always preserve the backing store, whether
783 we ask for it or not. So don't bother not asking for it. */
784 min_backing_store = accelerated ? 0 : 1;
785 max_backing_store = 1;
787 else
788 min_backing_store = max_backing_store = 0;
789 n_stack[++n_stack_idx] = n;
790 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
792 CGLPixelFormatObj pix;
793 GLint virtualScreens;
794 CGLError err;
796 n = n_stack[n_stack_idx];
798 if (backing_store)
799 attribs[n++] = kCGLPFABackingStore;
800 request.backing_store = backing_store;
802 attribs[n] = 0;
804 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
805 if (err == kCGLNoError && pix)
807 pixel_format pf;
808 GLint value, color_size, alpha_size, color_float;
809 UInt64 pf_code;
810 CFNumberRef code_object;
811 BOOL dupe;
813 memset(&pf, 0, sizeof(pf));
815 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
816 pf.accelerated = value;
817 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
818 pf.aux_buffers = value;
819 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
820 pf.depth_bits = value;
821 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
822 pf.double_buffer = value;
823 if (pf.double_buffer &&
824 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
825 pf.backing_store = value;
826 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
827 pf.pbuffer = value;
828 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
829 pf.sample_buffers = value;
830 if (pf.sample_buffers &&
831 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
832 pf.samples = value;
833 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
834 pf.stencil_bits = value;
835 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
836 pf.stereo = value;
837 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
838 pf.window = value;
840 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
841 color_size = 0;
842 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
843 alpha_size = 0;
844 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
845 color_float = 0;
846 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
848 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
849 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
851 CGLReleasePixelFormat(pix);
853 pf_code = code_for_pixel_format(&pf);
855 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
856 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
857 dupe_pixel_formats++;
858 else
860 CFSetAddValue(pixel_format_set, code_object);
861 CFArrayAppendValue(pixel_format_array, code_object);
862 new_pixel_formats++;
864 CFRelease(code_object);
866 if (pf_code == code_for_pixel_format(&request))
867 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
868 else
870 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
871 dupe ? " (duplicate)" : "");
874 else
876 failed_pixel_formats++;
877 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
880 tried_pixel_formats++;
883 n_stack_idx--;
886 n_stack_idx--;
889 n_stack_idx--;
892 n_stack_idx--;
895 n_stack_idx--;
898 n_stack_idx--;
901 n_stack_idx--;
904 n_stack_idx--;
907 n_stack_idx--;
910 n_stack_idx--;
912 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
913 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
914 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
915 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
919 /* The docs for WGL_ARB_pixel_format say:
920 Indices are assigned to pixel formats in the following order:
921 1. Accelerated pixel formats that are displayable
922 2. Accelerated pixel formats that are displayable and which have
923 extended attributes
924 3. Generic pixel formats
925 4. Accelerated pixel formats that are non displayable
927 static int pixel_format_category(pixel_format pf)
929 /* non-displayable */
930 if (!pf.window)
931 return 4;
933 /* non-accelerated a.k.a. software a.k.a. generic */
934 if (!pf.accelerated)
935 return 3;
937 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
938 if (color_modes[pf.color_mode].is_float)
939 return 2;
941 /* accelerated, displayable, no extended attributes */
942 return 1;
946 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
948 CFNumberRef number1 = val1;
949 CFNumberRef number2 = val2;
950 UInt64 code1, code2;
951 pixel_format pf1, pf2;
952 int category1, category2;
954 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
955 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
956 pf1 = pixel_format_for_code(code1);
957 pf2 = pixel_format_for_code(code2);
958 category1 = pixel_format_category(pf1);
959 category2 = pixel_format_category(pf2);
961 if (category1 < category2)
962 return kCFCompareLessThan;
963 if (category1 > category2)
964 return kCFCompareGreaterThan;
966 /* Within a category, sort the "best" formats toward the front since that's
967 what wglChoosePixelFormatARB() has to do. The ordering implemented here
968 matches at least one Windows 7 machine's behavior.
970 /* Accelerated before unaccelerated. */
971 if (pf1.accelerated && !pf2.accelerated)
972 return kCFCompareLessThan;
973 if (!pf1.accelerated && pf2.accelerated)
974 return kCFCompareGreaterThan;
976 /* Explicit color mode ordering. */
977 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
978 return kCFCompareLessThan;
979 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
980 return kCFCompareGreaterThan;
982 /* Non-pbuffer-capable before pbuffer-capable. */
983 if (!pf1.pbuffer && pf2.pbuffer)
984 return kCFCompareLessThan;
985 if (pf1.pbuffer && !pf2.pbuffer)
986 return kCFCompareGreaterThan;
988 /* Fewer samples before more samples. */
989 if (pf1.samples < pf2.samples)
990 return kCFCompareLessThan;
991 if (pf1.samples > pf2.samples)
992 return kCFCompareGreaterThan;
994 /* Monoscopic before stereoscopic. (This is a guess.) */
995 if (!pf1.stereo && pf2.stereo)
996 return kCFCompareLessThan;
997 if (pf1.stereo && !pf2.stereo)
998 return kCFCompareGreaterThan;
1000 /* Single buffered before double buffered. */
1001 if (!pf1.double_buffer && pf2.double_buffer)
1002 return kCFCompareLessThan;
1003 if (pf1.double_buffer && !pf2.double_buffer)
1004 return kCFCompareGreaterThan;
1006 /* Possibly-optimized double buffering before backing-store-preserving
1007 double buffering. */
1008 if (!pf1.backing_store && pf2.backing_store)
1009 return kCFCompareLessThan;
1010 if (pf1.backing_store && !pf2.backing_store)
1011 return kCFCompareGreaterThan;
1013 /* Bigger depth buffer before smaller depth buffer. */
1014 if (pf1.depth_bits > pf2.depth_bits)
1015 return kCFCompareLessThan;
1016 if (pf1.depth_bits < pf2.depth_bits)
1017 return kCFCompareGreaterThan;
1019 /* Smaller stencil buffer before bigger stencil buffer. */
1020 if (pf1.stencil_bits < pf2.stencil_bits)
1021 return kCFCompareLessThan;
1022 if (pf1.stencil_bits > pf2.stencil_bits)
1023 return kCFCompareGreaterThan;
1025 /* Smaller alpha bits before larger alpha bits. */
1026 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1027 return kCFCompareLessThan;
1028 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1029 return kCFCompareGreaterThan;
1031 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1032 if (pf1.accum_mode)
1034 if (pf2.accum_mode)
1036 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1037 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1038 return kCFCompareLessThan;
1039 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1040 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1041 return kCFCompareGreaterThan;
1043 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1044 return kCFCompareLessThan;
1045 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1046 return kCFCompareGreaterThan;
1048 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1049 return kCFCompareLessThan;
1050 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1051 return kCFCompareGreaterThan;
1053 else
1054 return kCFCompareGreaterThan;
1056 else if (pf2.accum_mode)
1057 return kCFCompareLessThan;
1059 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1060 if (pf1.aux_buffers < pf2.aux_buffers)
1061 return kCFCompareLessThan;
1062 if (pf1.aux_buffers > pf2.aux_buffers)
1063 return kCFCompareGreaterThan;
1065 /* If we get here, arbitrarily sort based on code. */
1066 if (code1 < code2)
1067 return kCFCompareLessThan;
1068 if (code1 > code2)
1069 return kCFCompareGreaterThan;
1070 return kCFCompareEqualTo;
1074 static BOOL init_pixel_formats(void)
1076 BOOL ret = FALSE;
1077 CGLRendererInfoObj renderer_info;
1078 GLint rendererCount;
1079 CGLError err;
1080 CFMutableSetRef pixel_format_set;
1081 CFMutableArrayRef pixel_format_array;
1082 int i;
1083 CFRange range;
1085 TRACE("()\n");
1087 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1088 if (err)
1090 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1091 return FALSE;
1094 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1095 if (!pixel_format_set)
1097 WARN("CFSetCreateMutable failed\n");
1098 CGLDestroyRendererInfo(renderer_info);
1099 return FALSE;
1102 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1103 if (!pixel_format_array)
1105 WARN("CFArrayCreateMutable failed\n");
1106 CFRelease(pixel_format_set);
1107 CGLDestroyRendererInfo(renderer_info);
1108 return FALSE;
1111 for (i = 0; i < rendererCount; i++)
1113 renderer_properties renderer;
1115 get_renderer_properties(renderer_info, i, &renderer);
1116 if (TRACE_ON(wgl))
1118 TRACE("renderer_properties %d:\n", i);
1119 dump_renderer(&renderer);
1122 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1125 CFRelease(pixel_format_set);
1126 CGLDestroyRendererInfo(renderer_info);
1128 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1129 if (range.length)
1131 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1132 if (pixel_formats)
1134 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1135 for (i = 0; i < range.length; i++)
1137 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1138 UInt64 code;
1140 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1141 pixel_formats[i] = pixel_format_for_code(code);
1142 if (pixel_formats[i].window)
1143 nb_displayable_formats++;
1146 nb_formats = range.length;
1147 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1148 ret = TRUE;
1150 else
1151 WARN("failed to allocate pixel format list\n");
1153 else
1154 WARN("got no pixel formats\n");
1156 CFRelease(pixel_format_array);
1157 return ret;
1161 static inline BOOL is_valid_pixel_format(int format)
1163 return format > 0 && format <= nb_formats;
1167 static inline BOOL is_displayable_pixel_format(int format)
1169 return format > 0 && format <= nb_displayable_formats;
1173 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1175 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1176 * format in case of probing the number of pixel formats.
1178 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1180 TRACE("Returning format %d\n", format);
1181 return &pixel_formats[format - 1];
1183 return NULL;
1187 static BOOL init_gl_info(void)
1189 CGDirectDisplayID display = CGMainDisplayID();
1190 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1191 CGLPixelFormatAttribute attribs[] = {
1192 kCGLPFADisplayMask, displayMask,
1195 CGLPixelFormatObj pix;
1196 GLint virtualScreens;
1197 CGLError err;
1198 CGLContextObj context;
1199 CGLContextObj old_context = CGLGetCurrentContext();
1200 const char *str;
1202 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1203 if (err != kCGLNoError || !pix)
1205 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1206 return FALSE;
1209 err = CGLCreateContext(pix, NULL, &context);
1210 CGLReleasePixelFormat(pix);
1211 if (err != kCGLNoError || !context)
1213 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1214 return FALSE;
1217 err = CGLSetCurrentContext(context);
1218 if (err != kCGLNoError)
1220 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1221 CGLReleaseContext(context);
1222 return FALSE;
1225 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1226 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1227 strcpy(gl_info.glVersion, str);
1228 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1229 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1230 strcpy(gl_info.glExtensions, str);
1232 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1234 TRACE("GL version : %s\n", gl_info.glVersion);
1235 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1237 CGLSetCurrentContext(old_context);
1238 CGLReleaseContext(context);
1240 return TRUE;
1244 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1246 BOOL ret = TRUE;
1247 *rect = data->client_rect;
1249 if (data->cocoa_window)
1251 if (window)
1252 *window = data->cocoa_window;
1253 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1255 else
1257 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1258 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1259 struct macdrv_win_data *top_data = get_win_data(top);
1261 if (top_data && top_data->cocoa_window)
1263 if (window)
1264 *window = top_data->cocoa_window;
1265 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1266 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1268 else
1269 ret = FALSE;
1271 release_win_data(top_data);
1274 return ret;
1278 /***********************************************************************
1279 * set_win_format
1281 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1283 macdrv_window cocoa_window;
1285 TRACE("hwnd %p format %d\n", data->hwnd, format);
1287 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1289 ERR("no top-level parent with Cocoa window in this process\n");
1290 return FALSE;
1293 if (data->gl_view) macdrv_dispose_view(data->gl_view);
1294 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1296 if (!data->gl_view)
1298 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1299 return FALSE;
1302 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1303 wine_dbgstr_rect(&data->gl_rect));
1305 data->pixel_format = format;
1307 return TRUE;
1311 /**********************************************************************
1312 * set_pixel_format
1314 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1316 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1318 struct macdrv_win_data *data;
1319 const pixel_format *pf;
1320 HWND hwnd = WindowFromDC(hdc);
1321 BOOL ret = FALSE;
1323 TRACE("hdc %p format %d\n", hdc, fmt);
1325 if (!hwnd || hwnd == GetDesktopWindow())
1327 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1328 return FALSE;
1331 if (!(data = get_win_data(hwnd)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1334 return FALSE;
1337 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1339 ret = (data->pixel_format == fmt);
1340 goto done;
1343 /* Check if fmt is in our list of supported formats to see if it is supported. */
1344 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1345 if (!pf)
1347 ERR("Invalid pixel format: %d\n", fmt);
1348 goto done;
1351 if (!pf->window)
1353 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1354 goto done;
1357 if (!set_win_format(data, fmt))
1359 WARN("Couldn't set format of the window, returning failure\n");
1360 goto done;
1363 TRACE("pixel format:\n");
1364 TRACE(" window: %u\n", (unsigned int)pf->window);
1365 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1366 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1367 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1368 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1369 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1370 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1371 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1372 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1373 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1374 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1375 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1376 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1377 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1378 ret = TRUE;
1380 done:
1381 release_win_data(data);
1382 if (ret) __wine_set_pixel_format(hwnd, fmt);
1383 return ret;
1387 /**********************************************************************
1388 * set_gl_view_parent
1390 void set_gl_view_parent(HWND hwnd, HWND parent)
1392 struct macdrv_win_data *data;
1394 if (!(data = get_win_data(hwnd))) return;
1396 if (data->gl_view)
1398 macdrv_window cocoa_window;
1400 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1402 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1404 ERR("no top-level parent with Cocoa window in this process\n");
1405 macdrv_dispose_view(data->gl_view);
1406 data->gl_view = NULL;
1407 release_win_data(data);
1408 __wine_set_pixel_format( hwnd, 0 );
1409 return;
1412 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1415 release_win_data(data);
1419 /**********************************************************************
1420 * make_context_current
1422 static void make_context_current(struct wgl_context *context, BOOL read)
1424 macdrv_view view;
1425 struct wgl_pbuffer *pbuffer;
1427 if (read)
1429 view = context->read_view;
1430 pbuffer = context->read_pbuffer;
1432 else
1434 view = context->draw_view;
1435 pbuffer = context->draw_pbuffer;
1438 if (view || !pbuffer)
1439 macdrv_make_context_current(context->context, view);
1440 else
1442 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1443 pbuffer->level, 0);
1444 CGLSetCurrentContext(context->cglcontext);
1449 /**********************************************************************
1450 * macdrv_glCopyColorTable
1452 * Hook into glCopyColorTable as part of the implementation of
1453 * wglMakeContextCurrentARB. If the context has a separate readable,
1454 * temporarily make that current, do glCopyColorTable, and then set it
1455 * back to the drawable. This is modeled after what Mesa GLX's Apple
1456 * implementation does.
1458 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1459 GLsizei width)
1461 struct wgl_context *context = NtCurrentTeb()->glContext;
1463 if (context->read_view || context->read_pbuffer)
1464 make_context_current(context, TRUE);
1466 pglCopyColorTable(target, internalformat, x, y, width);
1468 if (context->read_view || context->read_pbuffer)
1469 make_context_current(context, FALSE);
1473 /**********************************************************************
1474 * macdrv_glCopyPixels
1476 * Hook into glCopyPixels as part of the implementation of
1477 * wglMakeContextCurrentARB. If the context has a separate readable,
1478 * temporarily make that current, do glCopyPixels, and then set it back
1479 * to the drawable. This is modeled after what Mesa GLX's Apple
1480 * implementation does.
1482 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1484 struct wgl_context *context = NtCurrentTeb()->glContext;
1486 if (context->read_view || context->read_pbuffer)
1487 make_context_current(context, TRUE);
1489 pglCopyPixels(x, y, width, height, type);
1491 if (context->read_view || context->read_pbuffer)
1492 make_context_current(context, FALSE);
1496 static void macdrv_glFlush(void)
1498 struct wgl_context *context = NtCurrentTeb()->glContext;
1499 const pixel_format *pf = &pixel_formats[context->format - 1];
1500 DWORD now = GetTickCount();
1502 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1503 context->last_flush_time, now);
1504 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1506 TRACE("calling glFlushRenderAPPLE()\n");
1507 pglFlushRenderAPPLE();
1509 else
1511 TRACE("calling glFlush()\n");
1512 pglFlush();
1513 context->last_flush_time = now;
1518 /**********************************************************************
1519 * macdrv_glReadPixels
1521 * Hook into glReadPixels as part of the implementation of
1522 * wglMakeContextCurrentARB. If the context has a separate readable,
1523 * temporarily make that current, do glReadPixels, and then set it back
1524 * to the drawable. This is modeled after what Mesa GLX's Apple
1525 * implementation does.
1527 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1528 GLenum format, GLenum type, void *pixels)
1530 struct wgl_context *context = NtCurrentTeb()->glContext;
1532 if (context->read_view || context->read_pbuffer)
1533 make_context_current(context, TRUE);
1535 pglReadPixels(x, y, width, height, format, type, pixels);
1537 if (context->read_view || context->read_pbuffer)
1538 make_context_current(context, FALSE);
1542 /**********************************************************************
1543 * macdrv_glViewport
1545 * Hook into glViewport as an opportunity to update the OpenGL context
1546 * if necessary. This is modeled after what Mesa GLX's Apple
1547 * implementation does.
1549 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1551 struct wgl_context *context = NtCurrentTeb()->glContext;
1553 macdrv_update_opengl_context(context->context);
1554 pglViewport(x, y, width, height);
1558 /***********************************************************************
1559 * macdrv_wglBindTexImageARB
1561 * WGL_ARB_render_texture: wglBindTexImageARB
1563 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1565 struct wgl_context *context = NtCurrentTeb()->glContext;
1566 GLenum source;
1567 CGLError err;
1569 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1571 if (pbuffer->no_texture)
1573 SetLastError(ERROR_INVALID_OPERATION);
1574 return GL_FALSE;
1577 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1578 opengl_funcs.gl.p_glFlush();
1580 switch (iBuffer)
1582 case WGL_FRONT_LEFT_ARB:
1583 if (pixel_formats[pbuffer->format - 1].stereo)
1584 source = GL_FRONT_LEFT;
1585 else
1586 source = GL_FRONT;
1587 break;
1588 case WGL_FRONT_RIGHT_ARB:
1589 source = GL_FRONT_RIGHT;
1590 break;
1591 case WGL_BACK_LEFT_ARB:
1592 if (pixel_formats[pbuffer->format - 1].stereo)
1593 source = GL_BACK_LEFT;
1594 else
1595 source = GL_BACK;
1596 break;
1597 case WGL_BACK_RIGHT_ARB:
1598 source = GL_BACK_RIGHT;
1599 break;
1600 case WGL_AUX0_ARB: source = GL_AUX0; break;
1601 case WGL_AUX1_ARB: source = GL_AUX1; break;
1602 case WGL_AUX2_ARB: source = GL_AUX2; break;
1603 case WGL_AUX3_ARB: source = GL_AUX3; break;
1605 case WGL_AUX4_ARB:
1606 case WGL_AUX5_ARB:
1607 case WGL_AUX6_ARB:
1608 case WGL_AUX7_ARB:
1609 case WGL_AUX8_ARB:
1610 case WGL_AUX9_ARB:
1611 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1612 SetLastError(ERROR_INVALID_DATA);
1613 return GL_FALSE;
1615 default:
1616 WARN("unknown source buffer 0x%x\n", iBuffer);
1617 SetLastError(ERROR_INVALID_DATA);
1618 return GL_FALSE;
1621 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1622 if (err != kCGLNoError)
1624 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1625 SetLastError(ERROR_INVALID_OPERATION);
1626 return GL_FALSE;
1629 return GL_TRUE;
1633 /***********************************************************************
1634 * macdrv_wglChoosePixelFormatARB
1636 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1638 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1639 const FLOAT *pfAttribFList, UINT nMaxFormats,
1640 int *piFormats, UINT *nNumFormats)
1642 pixel_format pf, valid;
1643 const int *iptr;
1644 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1645 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1646 int float_color;
1647 BOOL srgb;
1648 int i, found = 0;
1650 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1651 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1652 if (pfAttribFList)
1653 FIXME("unused pfAttribFList\n");
1655 memset(&pf, 0, sizeof(pf));
1656 memset(&valid, 0, sizeof(valid));
1657 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1658 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1659 float_color = -1;
1660 srgb = FALSE;
1662 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1664 int attr = iptr[0];
1665 int value = iptr[1];
1667 TRACE("%s\n", debugstr_attrib(attr, value));
1669 switch (attr)
1671 case WGL_DRAW_TO_WINDOW_ARB:
1672 if (valid.window && (!pf.window != !value)) goto cant_match;
1673 pf.window = (value != 0);
1674 valid.window = 1;
1675 break;
1677 case WGL_DRAW_TO_BITMAP_ARB:
1678 goto cant_match;
1680 case WGL_ACCELERATION_ARB:
1681 if (value == WGL_FULL_ACCELERATION_ARB)
1682 value = 1;
1683 else if (value == WGL_NO_ACCELERATION_ARB)
1684 value = 0;
1685 else
1686 goto cant_match;
1687 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1688 pf.accelerated = value;
1689 valid.accelerated = 1;
1690 break;
1692 case WGL_NEED_PALETTE_ARB:
1693 case WGL_NEED_SYSTEM_PALETTE_ARB:
1694 case WGL_SWAP_LAYER_BUFFERS_ARB:
1695 if (value) goto cant_match;
1696 break;
1698 case WGL_SWAP_METHOD_ARB:
1699 if (value == WGL_SWAP_COPY_ARB)
1700 value = 1;
1701 else if (value == WGL_SWAP_UNDEFINED_ARB)
1702 value = 0;
1703 else
1704 goto cant_match;
1705 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1706 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1707 pf.backing_store = value;
1708 valid.backing_store = 1;
1709 break;
1711 case WGL_NUMBER_OVERLAYS_ARB:
1712 case WGL_NUMBER_UNDERLAYS_ARB:
1713 if (value) goto cant_match;
1714 break;
1716 case WGL_SHARE_DEPTH_ARB:
1717 case WGL_SHARE_STENCIL_ARB:
1718 case WGL_SHARE_ACCUM_ARB:
1719 /* no effect */
1720 break;
1722 case WGL_SUPPORT_GDI_ARB:
1723 if (value) goto cant_match;
1724 break;
1726 case WGL_SUPPORT_OPENGL_ARB:
1727 if (!value) goto cant_match;
1728 break;
1730 case WGL_DOUBLE_BUFFER_ARB:
1731 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1732 pf.double_buffer = (value != 0);
1733 valid.double_buffer = 1;
1734 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1735 break;
1737 case WGL_STEREO_ARB:
1738 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1739 pf.stereo = (value != 0);
1740 valid.stereo = 1;
1741 break;
1743 case WGL_PIXEL_TYPE_ARB:
1744 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1745 value = 1;
1746 else if (value == WGL_TYPE_RGBA_ARB)
1747 value = 0;
1748 else
1750 /* Mac contexts don't support rendering to unsigned floating
1751 point formats, even if GL_EXT_packed_float is supported.
1752 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1753 goto cant_match;
1755 if (float_color != -1 && float_color != value) goto cant_match;
1756 if (srgb && value) goto cant_match;
1757 float_color = value;
1758 break;
1760 case WGL_COLOR_BITS_ARB:
1761 if (color_bits < value) color_bits = value;
1762 break;
1764 case WGL_RED_BITS_ARB:
1765 if (srgb && value > 8) goto cant_match;
1766 if (red_bits < value) red_bits = value;
1767 break;
1769 case WGL_GREEN_BITS_ARB:
1770 if (srgb && value > 8) goto cant_match;
1771 if (green_bits < value) green_bits = value;
1772 break;
1774 case WGL_BLUE_BITS_ARB:
1775 if (srgb && value > 8) goto cant_match;
1776 if (blue_bits < value) blue_bits = value;
1777 break;
1779 case WGL_ALPHA_BITS_ARB:
1780 if (alpha_bits < value) alpha_bits = value;
1781 break;
1783 case WGL_ACCUM_BITS_ARB:
1784 if (accum_bits < value) accum_bits = value;
1785 break;
1787 case WGL_ACCUM_RED_BITS_ARB:
1788 if (accum_red_bits < value) accum_red_bits = value;
1789 break;
1791 case WGL_ACCUM_GREEN_BITS_ARB:
1792 if (accum_green_bits < value) accum_green_bits = value;
1793 break;
1795 case WGL_ACCUM_BLUE_BITS_ARB:
1796 if (accum_blue_bits < value) accum_blue_bits = value;
1797 break;
1799 case WGL_ACCUM_ALPHA_BITS_ARB:
1800 if (accum_alpha_bits < value) accum_alpha_bits = value;
1801 break;
1803 case WGL_DEPTH_BITS_ARB:
1804 if (value > 255) goto cant_match;
1805 if (pf.depth_bits < value) pf.depth_bits = value;
1806 break;
1808 case WGL_STENCIL_BITS_ARB:
1809 if (value > 255) goto cant_match;
1810 if (pf.stencil_bits < value) pf.stencil_bits = value;
1811 break;
1813 case WGL_AUX_BUFFERS_ARB:
1814 if (value > 7) goto cant_match;
1815 if (pf.aux_buffers < value) pf.aux_buffers = value;
1816 break;
1818 case WGL_SAMPLE_BUFFERS_ARB:
1819 if (value > 1) goto cant_match;
1820 if (pf.sample_buffers < value) pf.sample_buffers = value;
1821 break;
1823 case WGL_SAMPLES_ARB:
1824 if (value > 31) goto cant_match;
1825 if (pf.samples < value) pf.samples = value;
1826 break;
1828 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1829 /* sRGB is only supported for 8-bit integer color components */
1830 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1831 goto cant_match;
1832 srgb = TRUE;
1833 break;
1835 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1836 case WGL_RED_SHIFT_ARB:
1837 case WGL_GREEN_SHIFT_ARB:
1838 case WGL_BLUE_SHIFT_ARB:
1839 case WGL_ALPHA_SHIFT_ARB:
1840 case WGL_TRANSPARENT_ARB:
1841 case WGL_TRANSPARENT_RED_VALUE_ARB:
1842 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1843 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1844 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1845 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1846 /* ignored */
1847 break;
1849 case WGL_DRAW_TO_PBUFFER_ARB:
1850 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1851 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1852 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1853 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1854 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1855 pf.pbuffer = (value != 0);
1856 valid.pbuffer = 1;
1857 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1858 !alpha_bits)
1859 alpha_bits = 1;
1860 break;
1862 default:
1863 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
1864 return GL_FALSE;
1868 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",
1869 valid.window ? (pf.window ? "1" : "0") : "?",
1870 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
1871 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
1872 color_bits,
1873 float_color == -1 ? "?" : float_color ? "f" : "",
1874 red_bits,
1875 green_bits,
1876 blue_bits,
1877 alpha_bits,
1878 (int)srgb,
1879 accum_bits,
1880 accum_red_bits,
1881 accum_green_bits,
1882 accum_blue_bits,
1883 accum_alpha_bits,
1884 pf.depth_bits,
1885 pf.stencil_bits,
1886 pf.aux_buffers,
1887 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
1888 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
1889 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
1890 pf.sample_buffers,
1891 pf.samples);
1893 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
1895 const struct color_mode *mode;
1897 if (valid.window && pixel_formats[i].window != pf.window) continue;
1898 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
1899 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
1900 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
1901 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
1902 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
1904 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
1905 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
1906 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
1907 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
1908 if (pixel_formats[i].samples < pf.samples) continue;
1910 mode = &color_modes[pixel_formats[i].color_mode];
1911 /* If the mode doesn't have alpha, check requested color bits against
1912 bits per pixel instead of the mode's color bits. On Windows, color
1913 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1914 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1915 expects that to match such a pixel format, we need to accommodate that. */
1916 if (mode->alpha_bits)
1918 if (mode->color_bits < color_bits)
1919 continue;
1921 else
1923 if (mode->bits_per_pixel < color_bits)
1924 continue;
1926 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
1927 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
1928 continue;
1929 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
1930 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
1931 continue;
1933 if (pixel_formats[i].accum_mode)
1935 mode = &color_modes[pixel_formats[i].accum_mode - 1];
1936 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
1937 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
1938 mode->alpha_bits < accum_alpha_bits)
1939 continue;
1941 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
1942 continue;
1944 piFormats[found++] = i + 1;
1945 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
1948 cant_match:
1949 *nNumFormats = found;
1951 return TRUE;
1955 /**********************************************************************
1956 * macdrv_wglCreatePbufferARB
1958 * WGL_ARB_pbuffer: wglCreatePbufferARB
1960 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
1961 const int *piAttribList)
1963 struct wgl_pbuffer* pbuffer;
1964 GLenum target = 0;
1965 GLenum internalFormat = 0;
1966 CGLError err;
1968 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
1969 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
1971 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
1973 WARN("invalid pixel format %d\n", iPixelFormat);
1974 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1975 return NULL;
1978 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
1979 pbuffer->format = iPixelFormat;
1981 for ( ; piAttribList && *piAttribList; piAttribList += 2)
1983 int attr = piAttribList[0];
1984 int value = piAttribList[1];
1986 switch (attr)
1988 case WGL_PBUFFER_LARGEST_ARB:
1989 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
1990 break;
1992 case WGL_TEXTURE_FORMAT_ARB:
1993 switch (value)
1995 case WGL_TEXTURE_RGBA_ARB:
1996 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1997 internalFormat = GL_RGBA;
1998 break;
1999 case WGL_TEXTURE_RGB_ARB:
2000 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2001 internalFormat = GL_RGB;
2002 break;
2003 case WGL_NO_TEXTURE_ARB:
2004 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2005 internalFormat = 0;
2006 break;
2007 default:
2008 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2009 SetLastError(ERROR_INVALID_DATA);
2010 goto done;
2012 break;
2014 case WGL_TEXTURE_TARGET_ARB:
2015 pbuffer->face = 0;
2016 switch (value)
2018 case WGL_NO_TEXTURE_ARB:
2019 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2020 target = 0;
2021 break;
2022 case WGL_TEXTURE_CUBE_MAP_ARB:
2023 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2024 target = GL_TEXTURE_CUBE_MAP;
2025 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2026 break;
2027 case WGL_TEXTURE_1D_ARB:
2028 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2029 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2030 goto done;
2031 case WGL_TEXTURE_2D_ARB:
2032 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2033 target = GL_TEXTURE_2D;
2034 break;
2035 case WGL_TEXTURE_RECTANGLE_NV:
2036 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2037 target = GL_TEXTURE_RECTANGLE;
2038 break;
2039 default:
2040 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2041 SetLastError(ERROR_INVALID_DATA);
2042 goto done;
2044 break;
2046 case WGL_MIPMAP_TEXTURE_ARB:
2047 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2048 pbuffer->max_level = 0;
2049 if (value)
2051 int size = min(iWidth, iHeight) / 2;
2052 while (size)
2054 pbuffer->max_level++;
2055 size /= 2;
2058 break;
2060 default:
2061 WARN("unknown attribute 0x%x\n", attr);
2062 SetLastError(ERROR_INVALID_DATA);
2063 goto done;
2067 if (!target || !internalFormat)
2069 pbuffer->no_texture = TRUE;
2070 /* no actual way to turn off ability to texture; use most permissive target */
2071 target = GL_TEXTURE_RECTANGLE;
2072 internalFormat = GL_RGB;
2075 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2076 if (err != kCGLNoError)
2078 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2079 pbuffer->pbuffer = NULL;
2080 if (err == kCGLBadAlloc)
2081 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2082 else
2083 SetLastError(ERROR_INVALID_DATA);
2086 done:
2087 if (!pbuffer->pbuffer)
2089 HeapFree(GetProcessHeap(), 0, pbuffer);
2090 return NULL;
2093 TRACE(" -> %p\n", pbuffer);
2094 return pbuffer;
2098 /**********************************************************************
2099 * macdrv_wglDestroyPbufferARB
2101 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2103 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2105 TRACE("pbuffer %p\n", pbuffer);
2106 if (pbuffer && pbuffer->pbuffer)
2107 CGLReleasePBuffer(pbuffer->pbuffer);
2108 HeapFree(GetProcessHeap(), 0, pbuffer);
2109 return GL_TRUE;
2113 /**********************************************************************
2114 * macdrv_wglGetExtensionsStringARB
2116 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2118 static const GLubyte *macdrv_wglGetExtensionsStringARB(HDC hdc)
2120 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2121 this can be specific to the CGL renderer like we're supposed to do. */
2122 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2123 return (const GLubyte*)gl_info.wglExtensions;
2127 /**********************************************************************
2128 * macdrv_wglGetExtensionsStringEXT
2130 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2132 static const GLubyte *macdrv_wglGetExtensionsStringEXT(void)
2134 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2135 return (const GLubyte*)gl_info.wglExtensions;
2139 /**********************************************************************
2140 * macdrv_wglGetPbufferDCARB
2142 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2144 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2146 HDC hdc;
2147 struct wgl_pbuffer *prev;
2149 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2150 if (!hdc) return 0;
2152 EnterCriticalSection(&dc_pbuffers_section);
2153 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2154 if (prev)
2156 CGLReleasePBuffer(prev->pbuffer);
2157 HeapFree(GetProcessHeap(), 0, prev);
2159 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2160 LeaveCriticalSection(&dc_pbuffers_section);
2162 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2163 return hdc;
2167 /**********************************************************************
2168 * macdrv_wglGetPixelFormatAttribivARB
2170 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2172 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2173 UINT nAttributes, const int *piAttributes, int *piValues)
2175 const pixel_format *pf;
2176 UINT i;
2178 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2179 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2181 if (!nAttributes) return GL_TRUE;
2183 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2185 piValues[0] = nb_formats;
2186 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2187 return GL_TRUE;
2190 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2191 if (!pf)
2193 WARN("invalid pixel format %d\n", iPixelFormat);
2194 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2195 return GL_FALSE;
2198 for (i = 0; i < nAttributes; ++i)
2200 switch (piAttributes[i])
2202 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2203 piValues[i] = nb_formats;
2204 break;
2206 case WGL_DRAW_TO_WINDOW_ARB:
2207 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2208 break;
2210 case WGL_DRAW_TO_BITMAP_ARB:
2211 piValues[i] = GL_FALSE;
2212 break;
2214 case WGL_ACCELERATION_ARB:
2215 if (iLayerPlane) goto invalid_layer;
2216 if (pf->accelerated)
2217 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2218 else
2219 piValues[i] = WGL_NO_ACCELERATION_ARB;
2220 break;
2222 case WGL_NEED_PALETTE_ARB:
2223 case WGL_NEED_SYSTEM_PALETTE_ARB:
2224 case WGL_SWAP_LAYER_BUFFERS_ARB:
2225 piValues[i] = GL_FALSE;
2226 break;
2228 case WGL_SWAP_METHOD_ARB:
2229 if (pf->double_buffer && pf->backing_store)
2230 piValues[i] = WGL_SWAP_COPY_ARB;
2231 else
2232 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2233 break;
2235 case WGL_NUMBER_OVERLAYS_ARB:
2236 case WGL_NUMBER_UNDERLAYS_ARB:
2237 piValues[i] = 0;
2238 break;
2240 case WGL_TRANSPARENT_ARB:
2241 if (iLayerPlane) goto invalid_layer;
2242 piValues[i] = GL_FALSE;
2243 break;
2245 case WGL_TRANSPARENT_RED_VALUE_ARB:
2246 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2247 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2248 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2249 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2250 if (iLayerPlane) goto invalid_layer;
2251 piValues[i] = 0;
2252 break;
2254 case WGL_SHARE_DEPTH_ARB:
2255 case WGL_SHARE_STENCIL_ARB:
2256 case WGL_SHARE_ACCUM_ARB:
2257 if (iLayerPlane) goto invalid_layer;
2258 piValues[i] = GL_TRUE;
2259 break;
2261 case WGL_SUPPORT_GDI_ARB:
2262 if (iLayerPlane) goto invalid_layer;
2263 piValues[i] = GL_FALSE;
2264 break;
2266 case WGL_SUPPORT_OPENGL_ARB:
2267 if (iLayerPlane) goto invalid_layer;
2268 piValues[i] = GL_TRUE;
2269 break;
2271 case WGL_DOUBLE_BUFFER_ARB:
2272 if (iLayerPlane) goto invalid_layer;
2273 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2274 break;
2276 case WGL_STEREO_ARB:
2277 if (iLayerPlane) goto invalid_layer;
2278 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2279 break;
2281 case WGL_PIXEL_TYPE_ARB:
2282 if (iLayerPlane) goto invalid_layer;
2283 if (color_modes[pf->color_mode].is_float)
2284 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2285 else
2286 piValues[i] = WGL_TYPE_RGBA_ARB;
2287 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2288 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2289 However, Mac contexts don't support rendering to unsigned floating-point
2290 formats, even when GL_EXT_packed_float is supported. */
2291 break;
2293 case WGL_COLOR_BITS_ARB:
2294 if (iLayerPlane) goto invalid_layer;
2295 /* If the mode doesn't have alpha, return bits per pixel instead
2296 of color bits. On Windows, color bits sometimes exceeds r+g+b
2297 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2298 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2299 pixel format, we need to accommodate that. */
2300 if (color_modes[pf->color_mode].alpha_bits)
2301 piValues[i] = color_modes[pf->color_mode].color_bits;
2302 else
2303 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2304 break;
2306 case WGL_RED_BITS_ARB:
2307 if (iLayerPlane) goto invalid_layer;
2308 piValues[i] = color_modes[pf->color_mode].red_bits;
2309 break;
2311 case WGL_RED_SHIFT_ARB:
2312 if (iLayerPlane) goto invalid_layer;
2313 piValues[i] = color_modes[pf->color_mode].red_shift;
2314 break;
2316 case WGL_GREEN_BITS_ARB:
2317 if (iLayerPlane) goto invalid_layer;
2318 piValues[i] = color_modes[pf->color_mode].green_bits;
2319 break;
2321 case WGL_GREEN_SHIFT_ARB:
2322 if (iLayerPlane) goto invalid_layer;
2323 piValues[i] = color_modes[pf->color_mode].green_shift;
2324 break;
2326 case WGL_BLUE_BITS_ARB:
2327 if (iLayerPlane) goto invalid_layer;
2328 piValues[i] = color_modes[pf->color_mode].blue_bits;
2329 break;
2331 case WGL_BLUE_SHIFT_ARB:
2332 if (iLayerPlane) goto invalid_layer;
2333 piValues[i] = color_modes[pf->color_mode].blue_shift;
2334 break;
2336 case WGL_ALPHA_BITS_ARB:
2337 if (iLayerPlane) goto invalid_layer;
2338 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2339 break;
2341 case WGL_ALPHA_SHIFT_ARB:
2342 if (iLayerPlane) goto invalid_layer;
2343 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2344 break;
2346 case WGL_ACCUM_BITS_ARB:
2347 if (iLayerPlane) goto invalid_layer;
2348 if (pf->accum_mode)
2349 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2350 else
2351 piValues[i] = 0;
2352 break;
2354 case WGL_ACCUM_RED_BITS_ARB:
2355 if (iLayerPlane) goto invalid_layer;
2356 if (pf->accum_mode)
2357 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2358 else
2359 piValues[i] = 0;
2360 break;
2362 case WGL_ACCUM_GREEN_BITS_ARB:
2363 if (iLayerPlane) goto invalid_layer;
2364 if (pf->accum_mode)
2365 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2366 else
2367 piValues[i] = 0;
2368 break;
2370 case WGL_ACCUM_BLUE_BITS_ARB:
2371 if (iLayerPlane) goto invalid_layer;
2372 if (pf->accum_mode)
2373 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2374 else
2375 piValues[i] = 0;
2376 break;
2378 case WGL_ACCUM_ALPHA_BITS_ARB:
2379 if (iLayerPlane) goto invalid_layer;
2380 if (pf->accum_mode)
2381 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2382 else
2383 piValues[i] = 0;
2384 break;
2386 case WGL_DEPTH_BITS_ARB:
2387 if (iLayerPlane) goto invalid_layer;
2388 piValues[i] = pf->depth_bits;
2389 break;
2391 case WGL_STENCIL_BITS_ARB:
2392 if (iLayerPlane) goto invalid_layer;
2393 piValues[i] = pf->stencil_bits;
2394 break;
2396 case WGL_AUX_BUFFERS_ARB:
2397 if (iLayerPlane) goto invalid_layer;
2398 piValues[i] = pf->aux_buffers;
2399 break;
2401 case WGL_SAMPLE_BUFFERS_ARB:
2402 if (iLayerPlane) goto invalid_layer;
2403 piValues[i] = pf->sample_buffers;
2404 break;
2406 case WGL_SAMPLES_ARB:
2407 if (iLayerPlane) goto invalid_layer;
2408 piValues[i] = pf->samples;
2409 break;
2411 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2412 if (iLayerPlane) goto invalid_layer;
2413 /* sRGB is only supported for 8-bit integer color components */
2414 if (color_modes[pf->color_mode].red_bits == 8 &&
2415 color_modes[pf->color_mode].green_bits == 8 &&
2416 color_modes[pf->color_mode].blue_bits == 8 &&
2417 !color_modes[pf->color_mode].is_float)
2418 piValues[i] = GL_TRUE;
2419 else
2420 piValues[i] = GL_FALSE;
2421 break;
2423 case WGL_DRAW_TO_PBUFFER_ARB:
2424 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2425 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2426 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2427 break;
2429 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2430 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2431 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2432 break;
2434 case WGL_MAX_PBUFFER_WIDTH_ARB:
2435 piValues[i] = gl_info.max_viewport_dims[0];
2436 break;
2438 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2439 piValues[i] = gl_info.max_viewport_dims[1];
2440 break;
2442 case WGL_MAX_PBUFFER_PIXELS_ARB:
2443 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2444 break;
2446 default:
2447 WARN("invalid attribute %x\n", piAttributes[i]);
2448 return GL_FALSE;
2451 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2454 return GL_TRUE;
2456 invalid_layer:
2457 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2458 return GL_FALSE;
2462 /**********************************************************************
2463 * macdrv_wglGetPixelFormatAttribfvARB
2465 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2467 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2468 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2470 int *attr;
2471 int ret;
2473 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2474 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2476 /* Allocate a temporary array to store integer values */
2477 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2478 if (!attr)
2480 ERR("couldn't allocate %d array\n", nAttributes);
2481 return GL_FALSE;
2484 /* Piggy-back on wglGetPixelFormatAttribivARB */
2485 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2486 if (ret)
2488 UINT i;
2490 /* Convert integer values to float. Should also check for attributes
2491 that can give decimal values here */
2492 for (i = 0; i < nAttributes; i++)
2493 pfValues[i] = attr[i];
2496 HeapFree(GetProcessHeap(), 0, attr);
2497 return ret;
2501 /**********************************************************************
2502 * macdrv_wglGetSwapIntervalEXT
2504 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2506 static int macdrv_wglGetSwapIntervalEXT(void)
2508 struct wgl_context *context = NtCurrentTeb()->glContext;
2509 long value;
2510 CGLError err;
2512 TRACE("\n");
2514 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2515 if (err != kCGLNoError)
2517 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2518 err, CGLErrorString(err));
2519 value = 1;
2522 return value;
2526 /***********************************************************************
2527 * macdrv_wglMakeContextCurrentARB
2529 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2531 * This is not supported directly by OpenGL on the Mac. We emulate it
2532 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2533 * temporarily swap the drawable. This follows the technique used in
2534 * the implementation of Mesa GLX for Apple.
2536 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2538 struct macdrv_win_data *data;
2539 HWND hwnd;
2541 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2542 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2544 if (!context)
2546 macdrv_make_context_current(NULL, NULL);
2547 NtCurrentTeb()->glContext = NULL;
2548 return TRUE;
2551 if ((hwnd = WindowFromDC(draw_hdc)))
2553 if (!(data = get_win_data(hwnd)))
2555 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2556 return FALSE;
2559 if (!data->pixel_format)
2561 WARN("no pixel format set\n");
2562 release_win_data(data);
2563 SetLastError(ERROR_INVALID_HANDLE);
2564 return FALSE;
2566 if (context->format != data->pixel_format)
2568 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2569 release_win_data(data);
2570 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2571 return FALSE;
2574 context->draw_view = data->gl_view;
2575 context->draw_pbuffer = NULL;
2576 release_win_data(data);
2578 else
2580 struct wgl_pbuffer *pbuffer;
2582 EnterCriticalSection(&dc_pbuffers_section);
2583 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2584 if (pbuffer)
2586 if (context->format != pbuffer->format)
2588 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2589 LeaveCriticalSection(&dc_pbuffers_section);
2590 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2591 return FALSE;
2594 else
2596 WARN("no window or pbuffer for DC\n");
2597 LeaveCriticalSection(&dc_pbuffers_section);
2598 SetLastError(ERROR_INVALID_HANDLE);
2599 return FALSE;
2602 context->draw_view = NULL;
2603 context->draw_pbuffer = pbuffer;
2604 LeaveCriticalSection(&dc_pbuffers_section);
2607 context->read_view = NULL;
2608 context->read_pbuffer = NULL;
2609 if (read_hdc && read_hdc != draw_hdc)
2611 if ((hwnd = WindowFromDC(read_hdc)))
2613 if ((data = get_win_data(hwnd)))
2615 if (data->gl_view != context->draw_view)
2616 context->read_view = data->gl_view;
2617 release_win_data(data);
2620 else
2622 EnterCriticalSection(&dc_pbuffers_section);
2623 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2624 LeaveCriticalSection(&dc_pbuffers_section);
2628 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2629 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2631 make_context_current(context, FALSE);
2632 context->has_been_current = TRUE;
2633 NtCurrentTeb()->glContext = context;
2635 return TRUE;
2639 /**********************************************************************
2640 * macdrv_wglQueryPbufferARB
2642 * WGL_ARB_pbuffer: wglQueryPbufferARB
2644 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2646 CGLError err;
2647 GLsizei width;
2648 GLsizei height;
2649 GLenum target;
2650 GLenum internalFormat;
2651 GLint mipmap;
2653 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2655 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2656 if (err != kCGLNoError)
2658 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2659 SetLastError(ERROR_INVALID_HANDLE);
2660 return GL_FALSE;
2663 switch (iAttribute)
2665 case WGL_PBUFFER_WIDTH_ARB:
2666 *piValue = width;
2667 break;
2668 case WGL_PBUFFER_HEIGHT_ARB:
2669 *piValue = height;
2670 break;
2671 case WGL_PBUFFER_LOST_ARB:
2672 /* Mac PBuffers can't be lost */
2673 *piValue = GL_FALSE;
2674 break;
2675 case WGL_TEXTURE_FORMAT_ARB:
2676 if (pbuffer->no_texture)
2677 *piValue = WGL_NO_TEXTURE_ARB;
2678 else switch (internalFormat)
2680 case GL_RGBA:
2681 *piValue = WGL_TEXTURE_RGBA_ARB;
2682 break;
2683 case GL_RGB:
2684 default:
2685 *piValue = WGL_TEXTURE_RGB_ARB;
2686 break;
2688 break;
2689 case WGL_TEXTURE_TARGET_ARB:
2690 if (pbuffer->no_texture)
2691 *piValue = WGL_NO_TEXTURE_ARB;
2692 else switch (target)
2694 case GL_TEXTURE_CUBE_MAP:
2695 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2696 break;
2697 case GL_TEXTURE_2D:
2698 *piValue = WGL_TEXTURE_2D_ARB;
2699 break;
2700 case GL_TEXTURE_RECTANGLE:
2701 default:
2702 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2703 break;
2705 break;
2706 case WGL_MIPMAP_TEXTURE_ARB:
2707 *piValue = (pbuffer->max_level > 0);
2708 break;
2709 case WGL_MIPMAP_LEVEL_ARB:
2710 *piValue = pbuffer->level;
2711 break;
2712 case WGL_CUBE_MAP_FACE_ARB:
2713 switch (pbuffer->face)
2715 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2716 default:
2717 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2718 break;
2719 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2720 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2721 break;
2722 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2723 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2724 break;
2725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2726 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2727 break;
2728 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2729 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2730 break;
2731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2732 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2733 break;
2735 break;
2736 default:
2737 WARN("invalid attribute 0x%x\n", iAttribute);
2738 SetLastError(ERROR_INVALID_DATA);
2739 return GL_FALSE;
2742 return GL_TRUE;
2746 /**********************************************************************
2747 * macdrv_wglReleasePbufferDCARB
2749 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2751 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2753 struct wgl_pbuffer *prev;
2755 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2757 EnterCriticalSection(&dc_pbuffers_section);
2759 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2760 if (prev)
2762 if (prev != pbuffer)
2763 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2764 CGLReleasePBuffer(prev->pbuffer);
2765 HeapFree(GetProcessHeap(), 0, prev);
2766 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2768 else hdc = 0;
2770 LeaveCriticalSection(&dc_pbuffers_section);
2772 return hdc && DeleteDC(hdc);
2776 /**********************************************************************
2777 * macdrv_wglReleaseTexImageARB
2779 * WGL_ARB_render_texture: wglReleaseTexImageARB
2781 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2783 struct wgl_context *context = NtCurrentTeb()->glContext;
2784 CGLError err;
2786 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2788 if (pbuffer->no_texture)
2790 SetLastError(ERROR_INVALID_OPERATION);
2791 return GL_FALSE;
2794 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2795 if (err != kCGLNoError)
2797 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2798 SetLastError(ERROR_INVALID_OPERATION);
2799 return GL_FALSE;
2802 return GL_TRUE;
2806 /**********************************************************************
2807 * macdrv_wglSetPbufferAttribARB
2809 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2811 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2813 struct wgl_context *context = NtCurrentTeb()->glContext;
2815 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2817 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2819 int attr = piAttribList[0];
2820 int value = piAttribList[1];
2821 switch (attr)
2823 case WGL_MIPMAP_LEVEL_ARB:
2824 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2825 pbuffer->level = value;
2826 break;
2827 case WGL_CUBE_MAP_FACE_ARB:
2828 switch (value)
2830 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2831 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2832 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2833 break;
2834 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2835 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2836 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2837 break;
2838 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2839 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2840 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2841 break;
2842 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2843 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2844 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2845 break;
2846 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2847 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2848 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2849 break;
2850 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2851 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2852 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2853 break;
2854 default:
2855 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2856 SetLastError(ERROR_INVALID_DATA);
2857 return GL_FALSE;
2859 break;
2860 default:
2861 WARN("invalide attribute 0x%x\n", attr);
2862 SetLastError(ERROR_INVALID_DATA);
2863 return GL_FALSE;
2867 if (context && context->draw_pbuffer == pbuffer)
2868 make_context_current(context, FALSE);
2870 return GL_TRUE;
2874 /**********************************************************************
2875 * macdrv_wglSetPixelFormatWINE
2877 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2879 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
2881 return set_pixel_format(hdc, fmt, TRUE);
2885 /**********************************************************************
2886 * macdrv_wglSwapIntervalEXT
2888 * WGL_EXT_swap_control: wglSwapIntervalEXT
2890 static BOOL macdrv_wglSwapIntervalEXT(int interval)
2892 struct wgl_context *context = NtCurrentTeb()->glContext;
2893 long value;
2894 CGLError err;
2896 TRACE("interval %d\n", interval);
2898 if (interval < 0)
2900 SetLastError(ERROR_INVALID_DATA);
2901 return FALSE;
2904 if (!pixel_formats[context->format - 1].double_buffer)
2905 interval = 0;
2906 else if (interval > 1)
2907 interval = 1;
2909 value = interval;
2910 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2911 if (err != kCGLNoError)
2913 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2914 err, CGLErrorString(err));
2915 SetLastError(ERROR_GEN_FAILURE);
2916 return FALSE;
2919 return TRUE;
2923 static void register_extension(const char *ext)
2925 if (gl_info.wglExtensions[0])
2926 strcat(gl_info.wglExtensions, " ");
2927 strcat(gl_info.wglExtensions, ext);
2929 TRACE("'%s'\n", ext);
2932 static void load_extensions(void)
2935 * ARB Extensions
2937 register_extension("WGL_ARB_extensions_string");
2938 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
2940 register_extension("WGL_ARB_make_current_read");
2941 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
2942 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
2944 register_extension("WGL_ARB_pixel_format");
2945 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
2946 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
2947 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
2949 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
2951 register_extension("WGL_ARB_pixel_format_float");
2952 register_extension("WGL_ATI_pixel_format_float");
2955 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
2956 register_extension("WGL_ARB_multisample");
2958 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2959 register_extension("WGL_ARB_framebuffer_sRGB");
2961 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
2963 register_extension("WGL_ARB_pbuffer");
2964 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
2965 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
2966 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
2967 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
2968 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
2970 register_extension("WGL_ARB_render_texture");
2971 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
2972 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
2973 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
2975 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
2976 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
2977 register_extension("WGL_NV_render_texture_rectangle");
2980 /* TODO:
2981 WGL_ARB_create_context: wglCreateContextAttribsARB
2982 WGL_ARB_create_context_profile
2986 * EXT Extensions
2988 register_extension("WGL_EXT_extensions_string");
2989 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
2991 if (allow_vsync)
2993 register_extension("WGL_EXT_swap_control");
2994 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
2995 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
2998 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
2999 check for either, so register them separately. */
3000 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3001 register_extension("WGL_EXT_framebuffer_sRGB");
3003 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3004 register_extension("WGL_EXT_pixel_format_packed_float");
3007 * WINE-specific WGL Extensions
3010 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3011 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3013 register_extension("WGL_WINE_pixel_format_passthrough");
3014 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3018 static BOOL init_opengl(void)
3020 static int init_done;
3021 unsigned int i;
3022 char buffer[200];
3024 if (init_done) return (opengl_handle != NULL);
3025 init_done = 1;
3027 TRACE("()\n");
3029 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3030 if (!dc_pbuffers)
3032 WARN("CFDictionaryCreateMutable failed\n");
3033 return FALSE;
3036 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3037 if (!opengl_handle)
3039 ERR("Failed to load OpenGL: %s\n", buffer);
3040 ERR("OpenGL support is disabled.\n");
3041 return FALSE;
3044 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3046 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3048 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3049 goto failed;
3053 /* redirect some standard OpenGL functions */
3054 #define REDIRECT(func) \
3055 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3056 REDIRECT(glCopyPixels);
3057 REDIRECT(glReadPixels);
3058 REDIRECT(glViewport);
3059 if (skip_single_buffer_flushes)
3060 REDIRECT(glFlush);
3061 #undef REDIRECT
3063 /* redirect some OpenGL extension functions */
3064 #define REDIRECT(func) \
3065 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3066 REDIRECT(glCopyColorTable);
3067 #undef REDIRECT
3069 if (!init_gl_info())
3070 goto failed;
3072 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3073 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3075 load_extensions();
3076 if (!init_pixel_formats())
3077 goto failed;
3079 return TRUE;
3081 failed:
3082 wine_dlclose(opengl_handle, NULL, 0);
3083 opengl_handle = NULL;
3084 return FALSE;
3088 /***********************************************************************
3089 * sync_gl_view
3091 * Synchronize the Mac GL view position with the Windows child window
3092 * position.
3094 void sync_gl_view(struct macdrv_win_data *data)
3096 RECT rect;
3098 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3100 if (!data->gl_view) return;
3102 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3104 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3105 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3106 data->gl_rect = rect;
3111 static int get_dc_pixel_format(HDC hdc)
3113 int format;
3114 HWND hwnd;
3116 if ((hwnd = WindowFromDC(hdc)))
3118 struct macdrv_win_data *data;
3120 if (!(data = get_win_data(hwnd)))
3122 FIXME("DC for window %p of other process: not implemented\n", hwnd);
3123 return 0;
3126 format = data->pixel_format;
3127 release_win_data(data);
3129 else
3131 struct wgl_pbuffer *pbuffer;
3133 EnterCriticalSection(&dc_pbuffers_section);
3134 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3135 if (pbuffer)
3136 format = pbuffer->format;
3137 else
3139 WARN("no window or pbuffer for DC %p\n", hdc);
3140 format = 0;
3142 LeaveCriticalSection(&dc_pbuffers_section);
3145 return format;
3149 /**********************************************************************
3150 * create_context
3152 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
3154 const pixel_format *pf;
3155 CGLPixelFormatAttribute attribs[64];
3156 int n = 0;
3157 CGLPixelFormatObj pix;
3158 GLint virtualScreens;
3159 CGLError err;
3160 long swap_interval;
3162 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
3163 if (!pf)
3165 ERR("Invalid pixel format %d, expect problems!\n", context->format);
3166 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3167 return FALSE;
3170 attribs[n++] = kCGLPFAMinimumPolicy;
3171 attribs[n++] = kCGLPFAClosestPolicy;
3173 if (pf->accelerated)
3175 attribs[n++] = kCGLPFAAccelerated;
3176 attribs[n++] = kCGLPFANoRecovery;
3178 else
3180 attribs[n++] = kCGLPFARendererID;
3181 attribs[n++] = kCGLRendererGenericFloatID;
3184 if (pf->double_buffer)
3185 attribs[n++] = kCGLPFADoubleBuffer;
3187 attribs[n++] = kCGLPFAAuxBuffers;
3188 attribs[n++] = pf->aux_buffers;
3190 attribs[n++] = kCGLPFAColorSize;
3191 attribs[n++] = color_modes[pf->color_mode].color_bits;
3192 attribs[n++] = kCGLPFAAlphaSize;
3193 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3194 if (color_modes[pf->color_mode].is_float)
3195 attribs[n++] = kCGLPFAColorFloat;
3197 attribs[n++] = kCGLPFADepthSize;
3198 attribs[n++] = pf->depth_bits;
3200 attribs[n++] = kCGLPFAStencilSize;
3201 attribs[n++] = pf->stencil_bits;
3203 if (pf->stereo)
3204 attribs[n++] = kCGLPFAStereo;
3206 if (pf->accum_mode)
3208 attribs[n++] = kCGLPFAAccumSize;
3209 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3212 if (pf->window)
3213 attribs[n++] = kCGLPFAWindow;
3214 if (pf->pbuffer)
3215 attribs[n++] = kCGLPFAPBuffer;
3217 if (pf->sample_buffers && pf->samples)
3219 attribs[n++] = kCGLPFASampleBuffers;
3220 attribs[n++] = pf->sample_buffers;
3221 attribs[n++] = kCGLPFASamples;
3222 attribs[n++] = pf->samples;
3225 if (pf->backing_store)
3226 attribs[n++] = kCGLPFABackingStore;
3228 attribs[n] = 0;
3230 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3231 if (err != kCGLNoError || !pix)
3233 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3234 return FALSE;
3237 err = CGLCreateContext(pix, share, &context->cglcontext);
3238 CGLReleasePixelFormat(pix);
3239 if (err != kCGLNoError || !context->cglcontext)
3241 context->cglcontext = NULL;
3242 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3243 return FALSE;
3246 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3247 a context is 1. CGL contexts default to 0, so we need to set it. This
3248 only make sense for double-buffered contexts, though. In theory, for
3249 single-buffered contexts, there's no such thing as a swap. But OS X
3250 will synchronize flushes of single-buffered contexts if this is set. */
3251 if (pf->double_buffer && allow_vsync)
3252 swap_interval = 1;
3253 else
3254 swap_interval = 0;
3255 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&swap_interval);
3256 if (err != kCGLNoError)
3257 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err, CGLErrorString(err));
3259 context->context = macdrv_create_opengl_context(context->cglcontext);
3260 CGLReleaseContext(context->cglcontext);
3261 if (!context->context)
3263 WARN("macdrv_create_opengl_context() failed\n");
3264 return FALSE;
3267 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3269 return TRUE;
3273 /**********************************************************************
3274 * macdrv_wglDescribePixelFormat
3276 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3278 int ret = nb_formats;
3279 const pixel_format *pf;
3280 const struct color_mode *mode;
3282 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3284 if (fmt <= 0 || fmt > ret) return ret;
3285 if (size < sizeof(*descr)) return 0;
3287 pf = &pixel_formats[fmt - 1];
3289 memset(descr, 0, sizeof(*descr));
3290 descr->nSize = sizeof(*descr);
3291 descr->nVersion = 1;
3293 descr->dwFlags = PFD_SUPPORT_OPENGL;
3294 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3295 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3296 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3297 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3298 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3300 descr->iPixelType = PFD_TYPE_RGBA;
3302 mode = &color_modes[pf->color_mode];
3303 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3304 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3305 R8G8B8A0 pixel format). If an app depends on that and expects that
3306 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3307 if (mode->alpha_bits)
3308 descr->cColorBits = mode->color_bits;
3309 else
3310 descr->cColorBits = mode->bits_per_pixel;
3311 descr->cRedBits = mode->red_bits;
3312 descr->cRedShift = mode->red_shift;
3313 descr->cGreenBits = mode->green_bits;
3314 descr->cGreenShift = mode->green_shift;
3315 descr->cBlueBits = mode->blue_bits;
3316 descr->cBlueShift = mode->blue_shift;
3317 descr->cAlphaBits = mode->alpha_bits;
3318 descr->cAlphaShift = mode->alpha_shift;
3320 if (pf->accum_mode)
3322 mode = &color_modes[pf->accum_mode - 1];
3323 descr->cAccumBits = mode->color_bits;
3324 descr->cAccumRedBits = mode->red_bits;
3325 descr->cAccumGreenBits = mode->green_bits;
3326 descr->cAccumBlueBits = mode->blue_bits;
3327 descr->cAccumAlphaBits = mode->alpha_bits;
3330 descr->cDepthBits = pf->depth_bits;
3331 descr->cStencilBits = pf->stencil_bits;
3332 descr->cAuxBuffers = pf->aux_buffers;
3333 descr->iLayerType = PFD_MAIN_PLANE;
3334 return ret;
3337 /***********************************************************************
3338 * macdrv_wglCopyContext
3340 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3342 CGLError err;
3344 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3346 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3347 if (err != kCGLNoError)
3348 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3349 return (err == kCGLNoError);
3352 /***********************************************************************
3353 * macdrv_wglCreateContext
3355 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3357 int format;
3358 struct wgl_context *context;
3360 TRACE("hdc %p\n", hdc);
3362 format = get_dc_pixel_format(hdc);
3364 if (!is_valid_pixel_format(format))
3366 ERR("Invalid pixel format %d, expect problems!\n", format);
3367 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3368 return NULL;
3371 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3373 context->format = format;
3374 if (!create_context(context, NULL))
3376 HeapFree(GetProcessHeap(), 0, context);
3377 return NULL;
3380 return context;
3383 /***********************************************************************
3384 * macdrv_wglDeleteContext
3386 static void macdrv_wglDeleteContext(struct wgl_context *context)
3388 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3389 macdrv_dispose_opengl_context(context->context);
3390 HeapFree(GetProcessHeap(), 0, context);
3393 /***********************************************************************
3394 * macdrv_wglGetPixelFormat
3396 static int macdrv_wglGetPixelFormat(HDC hdc)
3398 int format;
3400 format = get_dc_pixel_format(hdc);
3402 if (!is_valid_pixel_format(format)) /* not set yet */
3403 format = 0;
3404 else if (!is_displayable_pixel_format(format))
3406 /* Non-displayable formats can't be used with traditional WGL calls.
3407 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3408 format = 1;
3411 TRACE(" hdc %p -> %d\n", hdc, format);
3412 return format;
3415 /***********************************************************************
3416 * macdrv_wglGetProcAddress
3418 static PROC macdrv_wglGetProcAddress(const char *proc)
3420 void *ret;
3422 if (!strncmp(proc, "wgl", 3)) return NULL;
3423 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3424 if (ret)
3426 if (TRACE_ON(wgl))
3428 Dl_info info;
3429 if (dladdr(ret, &info))
3430 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3431 else
3432 TRACE("%s -> %p (no library info)\n", proc, ret);
3435 else
3436 WARN("failed to find proc %s\n", debugstr_a(proc));
3437 return ret;
3440 /***********************************************************************
3441 * macdrv_wglMakeCurrent
3443 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3445 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3446 (context ? context->cglcontext : NULL));
3448 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3451 /**********************************************************************
3452 * macdrv_wglSetPixelFormat
3454 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3456 return set_pixel_format(hdc, fmt, FALSE);
3459 /***********************************************************************
3460 * macdrv_wglShareLists
3462 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3464 macdrv_opengl_context saved_context;
3465 CGLContextObj saved_cglcontext;
3467 TRACE("org %p dest %p\n", org, dest);
3469 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3470 * at context creation time but in case of WGL it is done using wglShareLists.
3472 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3473 * and when a program requests sharing we recreate the destination context if it hasn't been made
3474 * current or when it hasn't shared display lists before.
3477 if (dest->has_been_current)
3479 WARN("could not share display lists, the destination context has been current already\n");
3480 return FALSE;
3482 else if (dest->sharing)
3484 WARN("could not share display lists because dest has already shared lists before\n");
3485 return FALSE;
3488 /* Re-create the Mac context and share display lists */
3489 saved_context = dest->context;
3490 saved_cglcontext = dest->cglcontext;
3491 dest->context = NULL;
3492 dest->cglcontext = NULL;
3493 if (!create_context(dest, org->cglcontext))
3495 dest->context = saved_context;
3496 dest->cglcontext = saved_cglcontext;
3497 return FALSE;
3500 /* Implicitly disposes of saved_cglcontext. */
3501 macdrv_dispose_opengl_context(saved_context);
3503 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3504 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3506 org->sharing = TRUE;
3507 dest->sharing = TRUE;
3509 return TRUE;
3512 /**********************************************************************
3513 * macdrv_wglSwapBuffers
3515 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3517 struct wgl_context *context = NtCurrentTeb()->glContext;
3519 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3520 (context ? context->cglcontext : NULL));
3522 if (!context)
3524 SetLastError(ERROR_INVALID_HANDLE);
3525 return FALSE;
3528 macdrv_flush_opengl_context(context->context);
3529 return TRUE;
3532 static struct opengl_funcs opengl_funcs =
3535 macdrv_wglCopyContext, /* p_wglCopyContext */
3536 macdrv_wglCreateContext, /* p_wglCreateContext */
3537 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3538 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3539 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3540 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3541 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3542 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3543 macdrv_wglShareLists, /* p_wglShareLists */
3544 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3548 /**********************************************************************
3549 * macdrv_wine_get_wgl_driver
3551 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3553 if (version != WINE_WGL_DRIVER_VERSION)
3555 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3556 return NULL;
3559 if (!init_opengl()) return (void *)-1;
3561 return &opengl_funcs;