Revert "winemac.drv: Actually make the GL context current even if no drawables were...
[wine.git] / dlls / winemac.drv / opengl.c
blobab79a825bba8680d678dea6ec924f922eebfff86
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
36 #define __gl_h_
37 #define __gltypes_h_
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
41 #include <dlfcn.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 struct gl_info {
47 char *glExtensions;
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
53 unsigned int max_major, max_minor;
56 static struct gl_info gl_info;
59 struct wgl_context
61 struct list entry;
62 int format;
63 macdrv_opengl_context context;
64 CGLContextObj cglcontext;
65 HWND draw_hwnd;
66 macdrv_view draw_view;
67 struct wgl_pbuffer *draw_pbuffer;
68 macdrv_view read_view;
69 struct wgl_pbuffer *read_pbuffer;
70 BOOL has_been_current;
71 BOOL sharing;
72 LONG update_swap_interval;
73 DWORD last_flush_time;
74 UINT major;
77 static struct list context_list = LIST_INIT(context_list);
79 static CRITICAL_SECTION context_section;
80 static CRITICAL_SECTION_DEBUG critsect_debug =
82 0, 0, &context_section,
83 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
84 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
86 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
89 struct wgl_pbuffer
91 CGLPBufferObj pbuffer;
92 int format;
93 BOOL no_texture;
94 int max_level;
95 GLint level;
96 GLenum face;
99 static CFMutableDictionaryRef dc_pbuffers;
101 static CRITICAL_SECTION dc_pbuffers_section;
102 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
104 0, 0, &dc_pbuffers_section,
105 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
106 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
108 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
111 static struct opengl_funcs opengl_funcs;
113 #define USE_GL_FUNC(name) #name,
114 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
115 #undef USE_GL_FUNC
118 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
119 GLsizei width);
120 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
121 static void (*pglFinish)(void);
122 static void (*pglFlush)(void);
123 static void (*pglFlushRenderAPPLE)(void);
124 static const GLubyte *(*pglGetString)(GLenum name);
125 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
126 GLenum format, GLenum type, void *pixels);
127 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
130 struct color_mode {
131 GLint mode;
132 int bits_per_pixel;
133 GLint color_bits; /* including alpha_bits */
134 int red_bits, red_shift;
135 int green_bits, green_shift;
136 int blue_bits, blue_shift;
137 GLint alpha_bits, alpha_shift;
138 BOOL is_float;
139 int color_ordering;
142 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
143 observations of the behavior of Windows systems, but also subjective judgments
144 about what color formats are more "normal" than others.
146 On at least some Windows systems, integer color formats are listed before
147 floating-point formats. Within the integer formats, higher color bits were
148 usually listed before lower color bits, while for floating-point formats it
149 was the reverse. However, that leads D3D to select 64-bit integer formats in
150 preference to 32-bit formats when the latter would be sufficient. It seems
151 that a 32-bit format is much more likely to be normally used in that case.
153 Also, there are certain odd color formats supported on the Mac which seem like
154 they would be less appropriate than more common ones. For instance, the color
155 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
156 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
157 components.
159 For two color formats which differ only in whether or not they have alpha bits,
160 we use the same ordering. pixel_format_comparator() gives alpha bits a
161 different weight than color formats.
163 static const struct color_mode color_modes[] = {
164 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
165 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
166 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
167 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
168 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
169 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
170 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
171 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
172 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
173 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
174 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
175 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
176 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
177 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
178 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
179 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
180 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
181 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
182 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
183 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
184 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
185 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
186 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
187 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
191 static const struct {
192 GLint mode;
193 int bits;
194 } depth_stencil_modes[] = {
195 { kCGL0Bit, 0 },
196 { kCGL1Bit, 1 },
197 { kCGL2Bit, 2 },
198 { kCGL3Bit, 3 },
199 { kCGL4Bit, 4 },
200 { kCGL5Bit, 5 },
201 { kCGL6Bit, 6 },
202 { kCGL8Bit, 8 },
203 { kCGL10Bit, 10 },
204 { kCGL12Bit, 12 },
205 { kCGL16Bit, 16 },
206 { kCGL24Bit, 24 },
207 { kCGL32Bit, 32 },
208 { kCGL48Bit, 48 },
209 { kCGL64Bit, 64 },
210 { kCGL96Bit, 96 },
211 { kCGL128Bit, 128 },
215 typedef struct {
216 GLint renderer_id;
217 GLint buffer_modes;
218 GLint color_modes;
219 GLint accum_modes;
220 GLint depth_modes;
221 GLint stencil_modes;
222 GLint max_aux_buffers;
223 GLint max_sample_buffers;
224 GLint max_samples;
225 BOOL offscreen;
226 BOOL accelerated;
227 BOOL backing_store;
228 BOOL window;
229 BOOL online;
230 } renderer_properties;
233 typedef struct {
234 unsigned int window:1;
235 unsigned int pbuffer:1;
236 unsigned int accelerated:1;
237 unsigned int color_mode:5; /* index into color_modes table */
238 unsigned int aux_buffers:3;
239 unsigned int depth_bits:8;
240 unsigned int stencil_bits:8;
241 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
242 unsigned int double_buffer:1;
243 unsigned int stereo:1;
244 unsigned int sample_buffers:1;
245 unsigned int samples:5;
246 unsigned int backing_store:1;
247 } pixel_format;
250 typedef union
252 pixel_format format;
253 UInt64 code;
254 } pixel_format_or_code;
255 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
258 static pixel_format *pixel_formats;
259 static int nb_formats, nb_displayable_formats;
262 static void *opengl_handle;
265 static const char* debugstr_attrib(int attrib, int value)
267 static const struct {
268 int attrib;
269 const char *name;
270 } attrib_names[] = {
271 #define ATTRIB(a) { a, #a }
272 ATTRIB(WGL_ACCELERATION_ARB),
273 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
274 ATTRIB(WGL_ACCUM_BITS_ARB),
275 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
276 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
277 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
278 ATTRIB(WGL_ALPHA_BITS_ARB),
279 ATTRIB(WGL_ALPHA_SHIFT_ARB),
280 ATTRIB(WGL_AUX_BUFFERS_ARB),
281 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
285 ATTRIB(WGL_BLUE_BITS_ARB),
286 ATTRIB(WGL_BLUE_SHIFT_ARB),
287 ATTRIB(WGL_COLOR_BITS_ARB),
288 ATTRIB(WGL_DEPTH_BITS_ARB),
289 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
290 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
291 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
292 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
293 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
294 ATTRIB(WGL_GREEN_BITS_ARB),
295 ATTRIB(WGL_GREEN_SHIFT_ARB),
296 ATTRIB(WGL_NEED_PALETTE_ARB),
297 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
298 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
299 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
300 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
301 ATTRIB(WGL_PIXEL_TYPE_ARB),
302 ATTRIB(WGL_RED_BITS_ARB),
303 ATTRIB(WGL_RED_SHIFT_ARB),
304 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
305 ATTRIB(WGL_SAMPLES_ARB),
306 ATTRIB(WGL_SHARE_ACCUM_ARB),
307 ATTRIB(WGL_SHARE_DEPTH_ARB),
308 ATTRIB(WGL_SHARE_STENCIL_ARB),
309 ATTRIB(WGL_STENCIL_BITS_ARB),
310 ATTRIB(WGL_STEREO_ARB),
311 ATTRIB(WGL_SUPPORT_GDI_ARB),
312 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
313 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
314 ATTRIB(WGL_SWAP_METHOD_ARB),
315 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
316 ATTRIB(WGL_TRANSPARENT_ARB),
317 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
318 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
319 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
320 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
321 #undef ATTRIB
323 int i;
324 const char *attrib_name = NULL;
325 const char *value_name = NULL;
327 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
329 if (attrib_names[i].attrib == attrib)
331 attrib_name = attrib_names[i].name;
332 break;
336 if (!attrib_name)
337 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
339 switch (attrib)
341 case WGL_ACCELERATION_ARB:
342 switch (value)
344 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
345 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
346 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
348 break;
349 case WGL_PIXEL_TYPE_ARB:
350 switch (value)
352 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
353 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
354 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
355 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
357 break;
358 case WGL_SWAP_METHOD_ARB:
359 switch (value)
361 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
362 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
363 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
365 break;
368 if (!value_name)
369 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
371 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
375 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
376 CGLRendererProperty property, GLint *value)
378 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
379 if (err != kCGLNoError)
380 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
381 return (err == kCGLNoError);
385 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
387 GLint value;
389 memset(properties, 0, sizeof(*properties));
391 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
392 properties->renderer_id = value & kCGLRendererIDMatchingMask;
394 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
395 properties->buffer_modes = value;
397 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
398 properties->color_modes = value;
400 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
401 properties->accum_modes = value;
403 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
404 properties->depth_modes = value;
406 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
407 properties->stencil_modes = value;
409 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
410 properties->max_aux_buffers = value;
412 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
413 properties->max_sample_buffers = value;
415 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
416 properties->max_samples = value;
418 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
419 properties->offscreen = (value != 0);
421 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
422 properties->accelerated = (value != 0);
424 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
425 properties->backing_store = (value != 0);
427 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
428 properties->window = (value != 0);
430 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
431 properties->online = (value != 0);
435 static void dump_renderer(const renderer_properties* renderer)
437 int i;
439 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
440 TRACE("Buffer modes:\n");
441 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
442 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
443 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
444 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
446 TRACE("Color buffer modes:\n");
447 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
449 if (renderer->color_modes & color_modes[i].mode)
451 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
452 if (color_modes[i].is_float)
453 TRACE(", Float");
454 TRACE("\n");
458 TRACE("Accumulation buffer sizes: { ");
459 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
461 if (renderer->accum_modes & color_modes[i].mode)
462 TRACE("%d, ", color_modes[i].color_bits);
464 TRACE("}\n");
466 TRACE("Depth buffer sizes: { ");
467 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
469 if (renderer->depth_modes & depth_stencil_modes[i].mode)
470 TRACE("%d, ", depth_stencil_modes[i].bits);
472 TRACE("}\n");
474 TRACE("Stencil buffer sizes: { ");
475 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
477 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
478 TRACE("%d, ", depth_stencil_modes[i].bits);
480 TRACE("}\n");
482 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
483 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
484 TRACE("Max. Samples: %d\n", renderer->max_samples);
485 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
486 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
487 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
488 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
489 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
493 static inline UInt64 code_for_pixel_format(const pixel_format* format)
495 pixel_format_or_code pfc;
497 pfc.code = 0;
498 pfc.format = *format;
499 return pfc.code;
503 static inline pixel_format pixel_format_for_code(UInt64 code)
505 pixel_format_or_code pfc;
507 pfc.code = code;
508 return pfc.format;
512 static const char *debugstr_pf(const pixel_format *pf)
514 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",
515 pf->window,
516 pf->pbuffer,
517 pf->accelerated,
518 color_modes[pf->color_mode].color_bits,
519 (color_modes[pf->color_mode].is_float ? "f" : ""),
520 color_modes[pf->color_mode].alpha_bits,
521 pf->depth_bits,
522 pf->stencil_bits,
523 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
524 pf->aux_buffers,
525 pf->backing_store,
526 pf->double_buffer,
527 pf->stereo,
528 pf->sample_buffers,
529 pf->samples,
530 code_for_pixel_format(pf));
534 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
536 int best = -1;
537 int i;
539 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
541 if ((modes & color_modes[i].mode) &&
542 color_modes[i].color_bits >= color_size &&
543 color_modes[i].alpha_bits >= alpha_size &&
544 !color_modes[i].is_float == !color_float)
546 if (best < 0) /* no existing best choice */
547 best = i;
548 else if (color_modes[i].color_bits == color_size &&
549 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
551 /* prefer it over a best which isn't exact or which has a higher bpp */
552 if (color_modes[best].color_bits != color_size ||
553 color_modes[best].alpha_bits != alpha_size ||
554 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
555 best = i;
557 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
558 (color_modes[i].color_bits == color_modes[best].color_bits &&
559 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
560 best = i;
564 if (best < 0)
566 /* Couldn't find a match. Return first one that renderer supports. */
567 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
569 if (modes & color_modes[i].mode)
570 return i;
574 return best;
578 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
580 int best = -1;
581 int i;
583 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
585 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
587 /* Prefer the fewest color bits, then prefer more alpha bits, then
588 prefer more bits per pixel. */
589 if (best < 0)
590 best = i;
591 else if (color_modes[i].color_bits < color_modes[best].color_bits)
592 best = i;
593 else if (color_modes[i].color_bits == color_modes[best].color_bits)
595 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
596 best = i;
597 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
598 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
599 best = i;
604 if (best < 0)
606 /* Couldn't find a match. Return last one that renderer supports. */
607 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
609 if (modes & color_modes[i].mode)
610 return i;
614 return best;
618 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
619 CFMutableSetRef pixel_format_set)
621 CGLPixelFormatAttribute attribs[64] = {
622 kCGLPFAMinimumPolicy,
623 kCGLPFAClosestPolicy,
624 kCGLPFARendererID, renderer.renderer_id,
625 kCGLPFASingleRenderer,
627 int n = 5, n_stack[16], n_stack_idx = -1;
628 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
629 new_pixel_formats = 0;
630 pixel_format request;
631 unsigned int double_buffer;
632 unsigned int accelerated = renderer.accelerated;
634 if (accelerated)
636 attribs[n++] = kCGLPFAAccelerated;
637 attribs[n++] = kCGLPFANoRecovery;
639 else if (!allow_software_rendering)
641 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
642 return;
645 n_stack[++n_stack_idx] = n;
646 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
648 unsigned int aux;
650 n = n_stack[n_stack_idx];
652 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
653 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
654 continue;
656 if (double_buffer)
657 attribs[n++] = kCGLPFADoubleBuffer;
658 memset(&request, 0, sizeof(request));
659 request.accelerated = accelerated;
660 request.double_buffer = double_buffer;
662 /* Don't bother with in-between aux buffers values: either 0 or max. */
663 n_stack[++n_stack_idx] = n;
664 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
666 unsigned int color_mode;
668 n = n_stack[n_stack_idx];
670 attribs[n++] = kCGLPFAAuxBuffers;
671 attribs[n++] = aux;
672 request.aux_buffers = aux;
674 n_stack[++n_stack_idx] = n;
675 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
677 unsigned int depth_mode;
679 n = n_stack[n_stack_idx];
681 if (!(renderer.color_modes & color_modes[color_mode].mode))
682 continue;
684 attribs[n++] = kCGLPFAColorSize;
685 attribs[n++] = color_modes[color_mode].color_bits;
686 attribs[n++] = kCGLPFAAlphaSize;
687 attribs[n++] = color_modes[color_mode].alpha_bits;
688 if (color_modes[color_mode].is_float)
689 attribs[n++] = kCGLPFAColorFloat;
690 request.color_mode = color_mode;
692 n_stack[++n_stack_idx] = n;
693 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
695 unsigned int stencil_mode;
697 n = n_stack[n_stack_idx];
699 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
700 continue;
702 attribs[n++] = kCGLPFADepthSize;
703 attribs[n++] = depth_stencil_modes[depth_mode].bits;
704 request.depth_bits = depth_stencil_modes[depth_mode].bits;
706 n_stack[++n_stack_idx] = n;
707 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
709 unsigned int stereo;
711 n = n_stack[n_stack_idx];
713 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
714 continue;
715 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
716 continue;
718 attribs[n++] = kCGLPFAStencilSize;
719 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
720 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
722 /* FIXME: Could trim search space a bit here depending on GPU.
723 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
724 n_stack[++n_stack_idx] = n;
725 for (stereo = 0; stereo <= 1; stereo++)
727 int accum_mode;
729 n = n_stack[n_stack_idx];
731 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
732 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
733 continue;
735 if (stereo)
736 attribs[n++] = kCGLPFAStereo;
737 request.stereo = stereo;
739 /* Starts at -1 for a 0 accum size */
740 n_stack[++n_stack_idx] = n;
741 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
743 unsigned int target_pass;
745 n = n_stack[n_stack_idx];
747 if (accum_mode >= 0)
749 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
750 continue;
752 attribs[n++] = kCGLPFAAccumSize;
753 attribs[n++] = color_modes[accum_mode].color_bits;
754 request.accum_mode = accum_mode + 1;
756 else
757 request.accum_mode = 0;
759 /* Targets to request are:
760 accelerated: window OR window + pbuffer
761 software: window + pbuffer */
762 n_stack[++n_stack_idx] = n;
763 for (target_pass = 0; target_pass <= accelerated; target_pass++)
765 unsigned int samples, max_samples;
767 n = n_stack[n_stack_idx];
769 attribs[n++] = kCGLPFAWindow;
770 request.window = 1;
772 if (!accelerated || target_pass > 0)
774 attribs[n++] = kCGLPFAPBuffer;
775 request.pbuffer = 1;
777 else
778 request.pbuffer = 0;
780 /* FIXME: Could trim search space a bit here depending on GPU.
781 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
782 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
783 n_stack[++n_stack_idx] = n;
784 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
785 for (samples = 1; samples <= max_samples; samples *= 2)
787 unsigned int backing_store, min_backing_store, max_backing_store;
789 n = n_stack[n_stack_idx];
791 if (samples > 1)
793 attribs[n++] = kCGLPFASampleBuffers;
794 attribs[n++] = renderer.max_sample_buffers;
795 attribs[n++] = kCGLPFASamples;
796 attribs[n++] = samples;
797 request.sample_buffers = renderer.max_sample_buffers;
798 request.samples = samples;
800 else
801 request.sample_buffers = request.samples = 0;
803 if (renderer.backing_store && double_buffer)
805 /* The software renderer seems to always preserve the backing store, whether
806 we ask for it or not. So don't bother not asking for it. */
807 min_backing_store = accelerated ? 0 : 1;
808 max_backing_store = 1;
810 else
811 min_backing_store = max_backing_store = 0;
812 n_stack[++n_stack_idx] = n;
813 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
815 CGLPixelFormatObj pix;
816 GLint virtualScreens;
817 CGLError err;
819 n = n_stack[n_stack_idx];
821 if (backing_store)
822 attribs[n++] = kCGLPFABackingStore;
823 request.backing_store = backing_store;
825 attribs[n] = 0;
827 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
828 if (err == kCGLNoError && pix)
830 pixel_format pf;
831 GLint value, color_size, alpha_size, color_float;
832 UInt64 pf_code;
833 CFNumberRef code_object;
834 BOOL dupe;
836 memset(&pf, 0, sizeof(pf));
838 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
839 pf.accelerated = value;
840 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
841 pf.aux_buffers = value;
842 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
843 pf.depth_bits = value;
844 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
845 pf.double_buffer = value;
846 if (pf.double_buffer &&
847 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
848 pf.backing_store = value;
849 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
850 pf.pbuffer = value;
851 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
852 pf.sample_buffers = value;
853 if (pf.sample_buffers &&
854 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
855 pf.samples = value;
856 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
857 pf.stencil_bits = value;
858 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
859 pf.stereo = value;
860 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
861 pf.window = value;
863 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
864 color_size = 0;
865 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
866 alpha_size = 0;
867 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
868 color_float = 0;
869 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
871 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
872 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
874 CGLReleasePixelFormat(pix);
876 pf_code = code_for_pixel_format(&pf);
878 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
879 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
880 dupe_pixel_formats++;
881 else
883 CFSetAddValue(pixel_format_set, code_object);
884 CFArrayAppendValue(pixel_format_array, code_object);
885 new_pixel_formats++;
887 CFRelease(code_object);
889 if (pf_code == code_for_pixel_format(&request))
890 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
891 else
893 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
894 dupe ? " (duplicate)" : "");
897 else
899 failed_pixel_formats++;
900 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
903 tried_pixel_formats++;
906 n_stack_idx--;
909 n_stack_idx--;
912 n_stack_idx--;
915 n_stack_idx--;
918 n_stack_idx--;
921 n_stack_idx--;
924 n_stack_idx--;
927 n_stack_idx--;
930 n_stack_idx--;
933 n_stack_idx--;
935 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
936 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
937 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
938 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
942 /* The docs for WGL_ARB_pixel_format say:
943 Indices are assigned to pixel formats in the following order:
944 1. Accelerated pixel formats that are displayable
945 2. Accelerated pixel formats that are displayable and which have
946 extended attributes
947 3. Generic pixel formats
948 4. Accelerated pixel formats that are non displayable
950 static int pixel_format_category(pixel_format pf)
952 /* non-displayable */
953 if (!pf.window)
954 return 4;
956 /* non-accelerated a.k.a. software a.k.a. generic */
957 if (!pf.accelerated)
958 return 3;
960 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
961 if (color_modes[pf.color_mode].is_float)
962 return 2;
964 /* accelerated, displayable, no extended attributes */
965 return 1;
969 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
971 CFNumberRef number1 = val1;
972 CFNumberRef number2 = val2;
973 UInt64 code1, code2;
974 pixel_format pf1, pf2;
975 int category1, category2;
977 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
978 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
979 pf1 = pixel_format_for_code(code1);
980 pf2 = pixel_format_for_code(code2);
981 category1 = pixel_format_category(pf1);
982 category2 = pixel_format_category(pf2);
984 if (category1 < category2)
985 return kCFCompareLessThan;
986 if (category1 > category2)
987 return kCFCompareGreaterThan;
989 /* Within a category, sort the "best" formats toward the front since that's
990 what wglChoosePixelFormatARB() has to do. The ordering implemented here
991 matches at least one Windows 7 machine's behavior.
993 /* Accelerated before unaccelerated. */
994 if (pf1.accelerated && !pf2.accelerated)
995 return kCFCompareLessThan;
996 if (!pf1.accelerated && pf2.accelerated)
997 return kCFCompareGreaterThan;
999 /* Explicit color mode ordering. */
1000 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1001 return kCFCompareLessThan;
1002 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1003 return kCFCompareGreaterThan;
1005 /* Non-pbuffer-capable before pbuffer-capable. */
1006 if (!pf1.pbuffer && pf2.pbuffer)
1007 return kCFCompareLessThan;
1008 if (pf1.pbuffer && !pf2.pbuffer)
1009 return kCFCompareGreaterThan;
1011 /* Fewer samples before more samples. */
1012 if (pf1.samples < pf2.samples)
1013 return kCFCompareLessThan;
1014 if (pf1.samples > pf2.samples)
1015 return kCFCompareGreaterThan;
1017 /* Monoscopic before stereoscopic. (This is a guess.) */
1018 if (!pf1.stereo && pf2.stereo)
1019 return kCFCompareLessThan;
1020 if (pf1.stereo && !pf2.stereo)
1021 return kCFCompareGreaterThan;
1023 /* Single buffered before double buffered. */
1024 if (!pf1.double_buffer && pf2.double_buffer)
1025 return kCFCompareLessThan;
1026 if (pf1.double_buffer && !pf2.double_buffer)
1027 return kCFCompareGreaterThan;
1029 /* Possibly-optimized double buffering before backing-store-preserving
1030 double buffering. */
1031 if (!pf1.backing_store && pf2.backing_store)
1032 return kCFCompareLessThan;
1033 if (pf1.backing_store && !pf2.backing_store)
1034 return kCFCompareGreaterThan;
1036 /* Bigger depth buffer before smaller depth buffer. */
1037 if (pf1.depth_bits > pf2.depth_bits)
1038 return kCFCompareLessThan;
1039 if (pf1.depth_bits < pf2.depth_bits)
1040 return kCFCompareGreaterThan;
1042 /* Smaller stencil buffer before bigger stencil buffer. */
1043 if (pf1.stencil_bits < pf2.stencil_bits)
1044 return kCFCompareLessThan;
1045 if (pf1.stencil_bits > pf2.stencil_bits)
1046 return kCFCompareGreaterThan;
1048 /* Smaller alpha bits before larger alpha bits. */
1049 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1050 return kCFCompareLessThan;
1051 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1052 return kCFCompareGreaterThan;
1054 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1055 if (pf1.accum_mode)
1057 if (pf2.accum_mode)
1059 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1060 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1061 return kCFCompareLessThan;
1062 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1063 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1064 return kCFCompareGreaterThan;
1066 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1067 return kCFCompareLessThan;
1068 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1069 return kCFCompareGreaterThan;
1071 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1072 return kCFCompareLessThan;
1073 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1074 return kCFCompareGreaterThan;
1076 else
1077 return kCFCompareGreaterThan;
1079 else if (pf2.accum_mode)
1080 return kCFCompareLessThan;
1082 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1083 if (pf1.aux_buffers < pf2.aux_buffers)
1084 return kCFCompareLessThan;
1085 if (pf1.aux_buffers > pf2.aux_buffers)
1086 return kCFCompareGreaterThan;
1088 /* If we get here, arbitrarily sort based on code. */
1089 if (code1 < code2)
1090 return kCFCompareLessThan;
1091 if (code1 > code2)
1092 return kCFCompareGreaterThan;
1093 return kCFCompareEqualTo;
1097 static BOOL init_pixel_formats(void)
1099 BOOL ret = FALSE;
1100 CGLRendererInfoObj renderer_info;
1101 GLint rendererCount;
1102 CGLError err;
1103 CFMutableSetRef pixel_format_set;
1104 CFMutableArrayRef pixel_format_array;
1105 int i;
1106 CFRange range;
1108 TRACE("()\n");
1110 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1111 if (err)
1113 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1114 return FALSE;
1117 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1118 if (!pixel_format_set)
1120 WARN("CFSetCreateMutable failed\n");
1121 CGLDestroyRendererInfo(renderer_info);
1122 return FALSE;
1125 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1126 if (!pixel_format_array)
1128 WARN("CFArrayCreateMutable failed\n");
1129 CFRelease(pixel_format_set);
1130 CGLDestroyRendererInfo(renderer_info);
1131 return FALSE;
1134 for (i = 0; i < rendererCount; i++)
1136 renderer_properties renderer;
1138 get_renderer_properties(renderer_info, i, &renderer);
1139 if (TRACE_ON(wgl))
1141 TRACE("renderer_properties %d:\n", i);
1142 dump_renderer(&renderer);
1145 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1148 CFRelease(pixel_format_set);
1149 CGLDestroyRendererInfo(renderer_info);
1151 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1152 if (range.length)
1154 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1155 if (pixel_formats)
1157 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1158 for (i = 0; i < range.length; i++)
1160 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1161 UInt64 code;
1163 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1164 pixel_formats[i] = pixel_format_for_code(code);
1165 if (pixel_formats[i].window)
1166 nb_displayable_formats++;
1169 nb_formats = range.length;
1170 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1171 ret = TRUE;
1173 else
1174 WARN("failed to allocate pixel format list\n");
1176 else
1177 WARN("got no pixel formats\n");
1179 CFRelease(pixel_format_array);
1180 return ret;
1184 static inline BOOL is_valid_pixel_format(int format)
1186 return format > 0 && format <= nb_formats;
1190 static inline BOOL is_displayable_pixel_format(int format)
1192 return format > 0 && format <= nb_displayable_formats;
1196 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1198 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1199 * format in case of probing the number of pixel formats.
1201 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1203 TRACE("Returning format %d\n", format);
1204 return &pixel_formats[format - 1];
1206 return NULL;
1210 static BOOL init_gl_info(void)
1212 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1213 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1215 CGDirectDisplayID display = CGMainDisplayID();
1216 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1217 CGLPixelFormatAttribute attribs[] = {
1218 kCGLPFADisplayMask, displayMask,
1221 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1222 CGLPixelFormatAttribute core_attribs[] =
1224 kCGLPFADisplayMask, displayMask,
1225 kCGLPFAAccelerated,
1226 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1229 #endif
1230 CGLPixelFormatObj pix;
1231 GLint virtualScreens;
1232 CGLError err;
1233 CGLContextObj context;
1234 CGLContextObj old_context = CGLGetCurrentContext();
1235 const char *str;
1236 size_t length;
1238 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1239 if (err != kCGLNoError || !pix)
1241 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1242 return FALSE;
1245 err = CGLCreateContext(pix, NULL, &context);
1246 CGLReleasePixelFormat(pix);
1247 if (err != kCGLNoError || !context)
1249 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1250 return FALSE;
1253 err = CGLSetCurrentContext(context);
1254 if (err != kCGLNoError)
1256 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1257 CGLReleaseContext(context);
1258 return FALSE;
1261 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1262 length = strlen(str) + sizeof(legacy_extensions);
1263 if (allow_vsync)
1264 length += strlen(legacy_ext_swap_control);
1265 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1266 strcpy(gl_info.glExtensions, str);
1267 strcat(gl_info.glExtensions, legacy_extensions);
1268 if (allow_vsync)
1269 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1271 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1273 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1274 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1275 TRACE("GL version : %s\n", str);
1276 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1278 CGLSetCurrentContext(old_context);
1279 CGLReleaseContext(context);
1281 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1282 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1283 if (err != kCGLNoError || !pix)
1285 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1286 err, CGLErrorString(err));
1287 return TRUE;
1290 err = CGLCreateContext(pix, NULL, &context);
1291 CGLReleasePixelFormat(pix);
1292 if (err != kCGLNoError || !context)
1294 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1295 err, CGLErrorString(err));
1296 return TRUE;
1299 err = CGLSetCurrentContext(context);
1300 if (err != kCGLNoError)
1302 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1303 err, CGLErrorString(err));
1304 CGLReleaseContext(context);
1305 return TRUE;
1308 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1309 TRACE("Core context GL version: %s\n", str);
1310 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1311 CGLSetCurrentContext(old_context);
1312 CGLReleaseContext(context);
1313 #endif
1315 return TRUE;
1319 static int get_dc_pixel_format(HDC hdc)
1321 int format;
1322 HWND hwnd;
1324 if ((hwnd = WindowFromDC(hdc)))
1326 struct macdrv_win_data *data;
1328 if (!(data = get_win_data(hwnd)))
1330 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1331 return 0;
1334 format = data->pixel_format;
1335 release_win_data(data);
1337 else
1339 struct wgl_pbuffer *pbuffer;
1341 EnterCriticalSection(&dc_pbuffers_section);
1342 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1343 if (pbuffer)
1344 format = pbuffer->format;
1345 else
1347 WARN("no window or pbuffer for DC %p\n", hdc);
1348 format = 0;
1350 LeaveCriticalSection(&dc_pbuffers_section);
1353 return format;
1357 /**********************************************************************
1358 * create_context
1360 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1362 const pixel_format *pf;
1363 CGLPixelFormatAttribute attribs[64];
1364 int n = 0;
1365 CGLPixelFormatObj pix;
1366 GLint virtualScreens;
1367 CGLError err;
1368 BOOL core = major >= 3;
1370 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1371 if (core)
1373 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1374 return FALSE;
1376 #endif
1378 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1379 if (!pf)
1381 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1382 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1383 return FALSE;
1386 attribs[n++] = kCGLPFAMinimumPolicy;
1387 attribs[n++] = kCGLPFAClosestPolicy;
1389 if (pf->accelerated)
1391 attribs[n++] = kCGLPFAAccelerated;
1392 attribs[n++] = kCGLPFANoRecovery;
1394 else
1396 attribs[n++] = kCGLPFARendererID;
1397 attribs[n++] = kCGLRendererGenericFloatID;
1400 if (pf->double_buffer)
1401 attribs[n++] = kCGLPFADoubleBuffer;
1403 if (!core)
1405 attribs[n++] = kCGLPFAAuxBuffers;
1406 attribs[n++] = pf->aux_buffers;
1409 attribs[n++] = kCGLPFAColorSize;
1410 attribs[n++] = color_modes[pf->color_mode].color_bits;
1411 attribs[n++] = kCGLPFAAlphaSize;
1412 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1413 if (color_modes[pf->color_mode].is_float)
1414 attribs[n++] = kCGLPFAColorFloat;
1416 attribs[n++] = kCGLPFADepthSize;
1417 attribs[n++] = pf->depth_bits;
1419 attribs[n++] = kCGLPFAStencilSize;
1420 attribs[n++] = pf->stencil_bits;
1422 if (pf->stereo)
1423 attribs[n++] = kCGLPFAStereo;
1425 if (pf->accum_mode && !core)
1427 attribs[n++] = kCGLPFAAccumSize;
1428 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1431 if (pf->pbuffer && !core)
1432 attribs[n++] = kCGLPFAPBuffer;
1434 if (pf->sample_buffers && pf->samples)
1436 attribs[n++] = kCGLPFASampleBuffers;
1437 attribs[n++] = pf->sample_buffers;
1438 attribs[n++] = kCGLPFASamples;
1439 attribs[n++] = pf->samples;
1442 if (pf->backing_store)
1443 attribs[n++] = kCGLPFABackingStore;
1445 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1446 if (core)
1448 attribs[n++] = kCGLPFAOpenGLProfile;
1449 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1450 if (major == 3)
1451 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1452 else
1453 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1454 #else
1455 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1456 #endif
1458 #endif
1460 attribs[n] = 0;
1462 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1463 if (err != kCGLNoError || !pix)
1465 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1466 SetLastError(ERROR_INVALID_OPERATION);
1467 return FALSE;
1470 err = CGLCreateContext(pix, share, &context->cglcontext);
1471 CGLReleasePixelFormat(pix);
1472 if (err != kCGLNoError || !context->cglcontext)
1474 context->cglcontext = NULL;
1475 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1476 SetLastError(ERROR_INVALID_OPERATION);
1477 return FALSE;
1480 if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
1482 GLint opacity = 0;
1483 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
1484 if (err != kCGLNoError)
1485 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
1487 else if (gl_surface_mode == GL_SURFACE_BEHIND)
1489 GLint order = -1;
1490 err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
1491 if (err != kCGLNoError)
1492 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
1495 context->context = macdrv_create_opengl_context(context->cglcontext);
1496 CGLReleaseContext(context->cglcontext);
1497 if (!context->context)
1499 WARN("macdrv_create_opengl_context() failed\n");
1500 SetLastError(ERROR_INVALID_OPERATION);
1501 return FALSE;
1503 context->major = major;
1505 if (allow_vsync)
1506 InterlockedExchange(&context->update_swap_interval, TRUE);
1508 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1510 return TRUE;
1514 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1516 BOOL ret = TRUE;
1517 *rect = data->client_rect;
1519 if (data->cocoa_window)
1521 if (window)
1522 *window = data->cocoa_window;
1523 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1525 else
1527 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1528 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1529 struct macdrv_win_data *top_data = get_win_data(top);
1531 if (top_data && top_data->cocoa_window)
1533 if (window)
1534 *window = top_data->cocoa_window;
1535 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1536 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1538 else
1539 ret = FALSE;
1541 release_win_data(top_data);
1544 return ret;
1548 /***********************************************************************
1549 * set_win_format
1551 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1553 TRACE("hwnd %p format %d\n", data->hwnd, format);
1555 if (!data->gl_view)
1557 macdrv_window cocoa_window;
1559 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1561 ERR("no top-level parent with Cocoa window in this process\n");
1562 return FALSE;
1565 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1566 if (!data->gl_view)
1568 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1569 return FALSE;
1572 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1573 wine_dbgstr_rect(&data->gl_rect));
1576 data->pixel_format = format;
1578 return TRUE;
1582 /**********************************************************************
1583 * set_pixel_format
1585 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1587 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1589 struct macdrv_win_data *data;
1590 const pixel_format *pf;
1591 HWND hwnd = WindowFromDC(hdc);
1592 BOOL ret = FALSE;
1594 TRACE("hdc %p format %d\n", hdc, fmt);
1596 if (!hwnd || hwnd == GetDesktopWindow())
1598 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1599 return FALSE;
1602 if (!(data = get_win_data(hwnd)))
1604 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1605 return FALSE;
1608 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1610 ret = (data->pixel_format == fmt);
1611 goto done;
1614 /* Check if fmt is in our list of supported formats to see if it is supported. */
1615 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1616 if (!pf)
1618 ERR("Invalid pixel format: %d\n", fmt);
1619 goto done;
1622 if (!pf->window)
1624 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1625 goto done;
1628 if (!set_win_format(data, fmt))
1630 WARN("Couldn't set format of the window, returning failure\n");
1631 goto done;
1634 TRACE("pixel format:\n");
1635 TRACE(" window: %u\n", (unsigned int)pf->window);
1636 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1637 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1638 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1639 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1640 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1641 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1642 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1643 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1644 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1645 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1646 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1647 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1648 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1649 ret = TRUE;
1651 done:
1652 release_win_data(data);
1653 if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
1654 return ret;
1658 /**********************************************************************
1659 * set_gl_view_parent
1661 void set_gl_view_parent(HWND hwnd, HWND parent)
1663 struct macdrv_win_data *data;
1665 if (!(data = get_win_data(hwnd))) return;
1667 if (data->gl_view)
1669 macdrv_window cocoa_window;
1671 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1673 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1675 ERR("no top-level parent with Cocoa window in this process\n");
1676 macdrv_dispose_view(data->gl_view);
1677 data->gl_view = NULL;
1678 release_win_data(data);
1679 __wine_set_pixel_format( hwnd, 0 );
1680 return;
1683 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1686 release_win_data(data);
1690 /**********************************************************************
1691 * make_context_current
1693 static void make_context_current(struct wgl_context *context, BOOL read)
1695 macdrv_view view;
1696 struct wgl_pbuffer *pbuffer;
1698 if (read)
1700 view = context->read_view;
1701 pbuffer = context->read_pbuffer;
1703 else
1705 view = context->draw_view;
1706 pbuffer = context->draw_pbuffer;
1709 if (view || !pbuffer)
1710 macdrv_make_context_current(context->context, view);
1711 else
1713 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1714 pbuffer->level, 0);
1715 CGLSetCurrentContext(context->cglcontext);
1720 /**********************************************************************
1721 * set_swap_interval
1723 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1725 CGLError err;
1727 /* In theory, for single-buffered contexts, there's no such thing as a swap
1728 so the swap interval shouldn't matter. But OS X will synchronize flushes
1729 of single-buffered contexts if the interval is set to non-zero. */
1730 if (interval && !pixel_formats[context->format - 1].double_buffer)
1731 interval = 0;
1733 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1734 if (err != kCGLNoError)
1735 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1737 return err == kCGLNoError;
1741 /**********************************************************************
1742 * sync_swap_interval
1744 static void sync_swap_interval(struct wgl_context *context)
1746 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1748 int interval;
1750 if (context->draw_hwnd)
1752 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1753 if (data)
1755 interval = data->swap_interval;
1756 release_win_data(data);
1758 else /* window was destroyed? */
1759 interval = 1;
1761 else /* pbuffer */
1762 interval = 0;
1764 set_swap_interval(context, interval);
1769 /**********************************************************************
1770 * macdrv_glCopyColorTable
1772 * Hook into glCopyColorTable as part of the implementation of
1773 * wglMakeContextCurrentARB. If the context has a separate readable,
1774 * temporarily make that current, do glCopyColorTable, and then set it
1775 * back to the drawable. This is modeled after what Mesa GLX's Apple
1776 * implementation does.
1778 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1779 GLsizei width)
1781 struct wgl_context *context = NtCurrentTeb()->glContext;
1783 if (context->read_view || context->read_pbuffer)
1784 make_context_current(context, TRUE);
1786 pglCopyColorTable(target, internalformat, x, y, width);
1788 if (context->read_view || context->read_pbuffer)
1789 make_context_current(context, FALSE);
1793 /**********************************************************************
1794 * macdrv_glCopyPixels
1796 * Hook into glCopyPixels as part of the implementation of
1797 * wglMakeContextCurrentARB. If the context has a separate readable,
1798 * temporarily make that current, do glCopyPixels, and then set it back
1799 * to the drawable. This is modeled after what Mesa GLX's Apple
1800 * implementation does.
1802 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1804 struct wgl_context *context = NtCurrentTeb()->glContext;
1806 if (context->read_view || context->read_pbuffer)
1807 make_context_current(context, TRUE);
1809 pglCopyPixels(x, y, width, height, type);
1811 if (context->read_view || context->read_pbuffer)
1812 make_context_current(context, FALSE);
1816 /**********************************************************************
1817 * macdrv_glFinish
1819 static void macdrv_glFinish(void)
1821 struct wgl_context *context = NtCurrentTeb()->glContext;
1823 sync_swap_interval(context);
1824 pglFinish();
1828 /**********************************************************************
1829 * macdrv_glFlush
1831 static void macdrv_glFlush(void)
1833 struct wgl_context *context = NtCurrentTeb()->glContext;
1835 sync_swap_interval(context);
1837 if (skip_single_buffer_flushes)
1839 const pixel_format *pf = &pixel_formats[context->format - 1];
1840 DWORD now = GetTickCount();
1842 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1843 context->last_flush_time, now);
1844 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1846 TRACE("calling glFlushRenderAPPLE()\n");
1847 pglFlushRenderAPPLE();
1848 return;
1850 else
1852 TRACE("calling glFlush()\n");
1853 context->last_flush_time = now;
1857 pglFlush();
1861 /**********************************************************************
1862 * macdrv_glGetString
1864 * Hook into glGetString in order to return some legacy WGL extensions
1865 * that couldn't be advertised via the standard
1866 * WGL_ARB_extensions_string mechanism. Some programs, especially
1867 * older ones, expect to find certain older extensions, such as
1868 * WGL_EXT_extensions_string itself, in the standard GL extensions
1869 * string, and won't query any other WGL extensions unless they find
1870 * that particular extension there.
1872 static const GLubyte *macdrv_glGetString(GLenum name)
1874 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1875 return (const GLubyte *)gl_info.glExtensions;
1876 else
1877 return pglGetString(name);
1881 /**********************************************************************
1882 * macdrv_glReadPixels
1884 * Hook into glReadPixels as part of the implementation of
1885 * wglMakeContextCurrentARB. If the context has a separate readable,
1886 * temporarily make that current, do glReadPixels, and then set it back
1887 * to the drawable. This is modeled after what Mesa GLX's Apple
1888 * implementation does.
1890 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1891 GLenum format, GLenum type, void *pixels)
1893 struct wgl_context *context = NtCurrentTeb()->glContext;
1895 if (context->read_view || context->read_pbuffer)
1896 make_context_current(context, TRUE);
1898 pglReadPixels(x, y, width, height, format, type, pixels);
1900 if (context->read_view || context->read_pbuffer)
1901 make_context_current(context, FALSE);
1905 /**********************************************************************
1906 * macdrv_glViewport
1908 * Hook into glViewport as an opportunity to update the OpenGL context
1909 * if necessary. This is modeled after what Mesa GLX's Apple
1910 * implementation does.
1912 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1914 struct wgl_context *context = NtCurrentTeb()->glContext;
1916 macdrv_update_opengl_context(context->context);
1917 pglViewport(x, y, width, height);
1921 /***********************************************************************
1922 * macdrv_wglBindTexImageARB
1924 * WGL_ARB_render_texture: wglBindTexImageARB
1926 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1928 struct wgl_context *context = NtCurrentTeb()->glContext;
1929 GLenum source;
1930 CGLError err;
1932 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1934 if (pbuffer->no_texture)
1936 SetLastError(ERROR_INVALID_OPERATION);
1937 return GL_FALSE;
1940 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1941 opengl_funcs.gl.p_glFlush();
1943 switch (iBuffer)
1945 case WGL_FRONT_LEFT_ARB:
1946 if (pixel_formats[pbuffer->format - 1].stereo)
1947 source = GL_FRONT_LEFT;
1948 else
1949 source = GL_FRONT;
1950 break;
1951 case WGL_FRONT_RIGHT_ARB:
1952 source = GL_FRONT_RIGHT;
1953 break;
1954 case WGL_BACK_LEFT_ARB:
1955 if (pixel_formats[pbuffer->format - 1].stereo)
1956 source = GL_BACK_LEFT;
1957 else
1958 source = GL_BACK;
1959 break;
1960 case WGL_BACK_RIGHT_ARB:
1961 source = GL_BACK_RIGHT;
1962 break;
1963 case WGL_AUX0_ARB: source = GL_AUX0; break;
1964 case WGL_AUX1_ARB: source = GL_AUX1; break;
1965 case WGL_AUX2_ARB: source = GL_AUX2; break;
1966 case WGL_AUX3_ARB: source = GL_AUX3; break;
1968 case WGL_AUX4_ARB:
1969 case WGL_AUX5_ARB:
1970 case WGL_AUX6_ARB:
1971 case WGL_AUX7_ARB:
1972 case WGL_AUX8_ARB:
1973 case WGL_AUX9_ARB:
1974 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1975 SetLastError(ERROR_INVALID_DATA);
1976 return GL_FALSE;
1978 default:
1979 WARN("unknown source buffer 0x%x\n", iBuffer);
1980 SetLastError(ERROR_INVALID_DATA);
1981 return GL_FALSE;
1984 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1985 if (err != kCGLNoError)
1987 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1988 SetLastError(ERROR_INVALID_OPERATION);
1989 return GL_FALSE;
1992 return GL_TRUE;
1996 /***********************************************************************
1997 * macdrv_wglChoosePixelFormatARB
1999 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2001 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
2002 const FLOAT *pfAttribFList, UINT nMaxFormats,
2003 int *piFormats, UINT *nNumFormats)
2005 pixel_format pf, valid;
2006 const int *iptr;
2007 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
2008 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
2009 int float_color;
2010 BOOL srgb;
2011 int i, found = 0;
2013 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2014 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2015 if (pfAttribFList)
2016 FIXME("unused pfAttribFList\n");
2018 memset(&pf, 0, sizeof(pf));
2019 memset(&valid, 0, sizeof(valid));
2020 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2021 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2022 float_color = -1;
2023 srgb = FALSE;
2025 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2027 int attr = iptr[0];
2028 int value = iptr[1];
2030 TRACE("%s\n", debugstr_attrib(attr, value));
2032 switch (attr)
2034 case WGL_DRAW_TO_WINDOW_ARB:
2035 if (valid.window && (!pf.window != !value)) goto cant_match;
2036 pf.window = (value != 0);
2037 valid.window = 1;
2038 break;
2040 case WGL_DRAW_TO_BITMAP_ARB:
2041 goto cant_match;
2043 case WGL_ACCELERATION_ARB:
2044 if (value == WGL_FULL_ACCELERATION_ARB)
2045 value = 1;
2046 else if (value == WGL_NO_ACCELERATION_ARB)
2047 value = 0;
2048 else
2049 goto cant_match;
2050 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2051 pf.accelerated = value;
2052 valid.accelerated = 1;
2053 break;
2055 case WGL_NEED_PALETTE_ARB:
2056 case WGL_NEED_SYSTEM_PALETTE_ARB:
2057 case WGL_SWAP_LAYER_BUFFERS_ARB:
2058 if (value) goto cant_match;
2059 break;
2061 case WGL_SWAP_METHOD_ARB:
2062 if (value == WGL_SWAP_COPY_ARB)
2063 value = 1;
2064 else if (value == WGL_SWAP_UNDEFINED_ARB)
2065 value = 0;
2066 else
2067 goto cant_match;
2068 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2069 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2070 pf.backing_store = value;
2071 valid.backing_store = 1;
2072 break;
2074 case WGL_NUMBER_OVERLAYS_ARB:
2075 case WGL_NUMBER_UNDERLAYS_ARB:
2076 if (value) goto cant_match;
2077 break;
2079 case WGL_SHARE_DEPTH_ARB:
2080 case WGL_SHARE_STENCIL_ARB:
2081 case WGL_SHARE_ACCUM_ARB:
2082 /* no effect */
2083 break;
2085 case WGL_SUPPORT_GDI_ARB:
2086 if (value) goto cant_match;
2087 break;
2089 case WGL_SUPPORT_OPENGL_ARB:
2090 if (!value) goto cant_match;
2091 break;
2093 case WGL_DOUBLE_BUFFER_ARB:
2094 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2095 pf.double_buffer = (value != 0);
2096 valid.double_buffer = 1;
2097 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2098 break;
2100 case WGL_STEREO_ARB:
2101 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2102 pf.stereo = (value != 0);
2103 valid.stereo = 1;
2104 break;
2106 case WGL_PIXEL_TYPE_ARB:
2107 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2108 value = 1;
2109 else if (value == WGL_TYPE_RGBA_ARB)
2110 value = 0;
2111 else
2113 /* Mac contexts don't support rendering to unsigned floating
2114 point formats, even if GL_EXT_packed_float is supported.
2115 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2116 goto cant_match;
2118 if (float_color != -1 && float_color != value) goto cant_match;
2119 if (srgb && value) goto cant_match;
2120 float_color = value;
2121 break;
2123 case WGL_COLOR_BITS_ARB:
2124 if (color_bits < value) color_bits = value;
2125 break;
2127 case WGL_RED_BITS_ARB:
2128 if (srgb && value > 8) goto cant_match;
2129 if (red_bits < value) red_bits = value;
2130 break;
2132 case WGL_GREEN_BITS_ARB:
2133 if (srgb && value > 8) goto cant_match;
2134 if (green_bits < value) green_bits = value;
2135 break;
2137 case WGL_BLUE_BITS_ARB:
2138 if (srgb && value > 8) goto cant_match;
2139 if (blue_bits < value) blue_bits = value;
2140 break;
2142 case WGL_ALPHA_BITS_ARB:
2143 if (alpha_bits < value) alpha_bits = value;
2144 break;
2146 case WGL_ACCUM_BITS_ARB:
2147 if (accum_bits < value) accum_bits = value;
2148 break;
2150 case WGL_ACCUM_RED_BITS_ARB:
2151 if (accum_red_bits < value) accum_red_bits = value;
2152 break;
2154 case WGL_ACCUM_GREEN_BITS_ARB:
2155 if (accum_green_bits < value) accum_green_bits = value;
2156 break;
2158 case WGL_ACCUM_BLUE_BITS_ARB:
2159 if (accum_blue_bits < value) accum_blue_bits = value;
2160 break;
2162 case WGL_ACCUM_ALPHA_BITS_ARB:
2163 if (accum_alpha_bits < value) accum_alpha_bits = value;
2164 break;
2166 case WGL_DEPTH_BITS_ARB:
2167 if (value > 255) goto cant_match;
2168 if (pf.depth_bits < value) pf.depth_bits = value;
2169 break;
2171 case WGL_STENCIL_BITS_ARB:
2172 if (value > 255) goto cant_match;
2173 if (pf.stencil_bits < value) pf.stencil_bits = value;
2174 break;
2176 case WGL_AUX_BUFFERS_ARB:
2177 if (value > 7) goto cant_match;
2178 if (pf.aux_buffers < value) pf.aux_buffers = value;
2179 break;
2181 case WGL_SAMPLE_BUFFERS_ARB:
2182 if (value > 1) goto cant_match;
2183 if (pf.sample_buffers < value) pf.sample_buffers = value;
2184 break;
2186 case WGL_SAMPLES_ARB:
2187 if (value > 31) goto cant_match;
2188 if (pf.samples < value) pf.samples = value;
2189 break;
2191 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2192 /* sRGB is only supported for 8-bit integer color components */
2193 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2194 goto cant_match;
2195 srgb = TRUE;
2196 break;
2198 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2199 case WGL_RED_SHIFT_ARB:
2200 case WGL_GREEN_SHIFT_ARB:
2201 case WGL_BLUE_SHIFT_ARB:
2202 case WGL_ALPHA_SHIFT_ARB:
2203 case WGL_TRANSPARENT_ARB:
2204 case WGL_TRANSPARENT_RED_VALUE_ARB:
2205 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2206 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2207 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2208 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2209 /* ignored */
2210 break;
2212 case WGL_DRAW_TO_PBUFFER_ARB:
2213 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2214 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2215 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2216 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2217 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2218 pf.pbuffer = (value != 0);
2219 valid.pbuffer = 1;
2220 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2221 !alpha_bits)
2222 alpha_bits = 1;
2223 break;
2225 default:
2226 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2227 return GL_FALSE;
2231 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",
2232 valid.window ? (pf.window ? "1" : "0") : "?",
2233 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2234 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2235 color_bits,
2236 float_color == -1 ? "?" : float_color ? "f" : "",
2237 red_bits,
2238 green_bits,
2239 blue_bits,
2240 alpha_bits,
2241 (int)srgb,
2242 accum_bits,
2243 accum_red_bits,
2244 accum_green_bits,
2245 accum_blue_bits,
2246 accum_alpha_bits,
2247 pf.depth_bits,
2248 pf.stencil_bits,
2249 pf.aux_buffers,
2250 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2251 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2252 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2253 pf.sample_buffers,
2254 pf.samples);
2256 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2258 const struct color_mode *mode;
2260 if (valid.window && pixel_formats[i].window != pf.window) continue;
2261 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2262 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2263 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2264 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2265 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2267 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2268 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2269 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2270 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2271 if (pixel_formats[i].samples < pf.samples) continue;
2273 mode = &color_modes[pixel_formats[i].color_mode];
2274 /* If the mode doesn't have alpha, check requested color bits against
2275 bits per pixel instead of the mode's color bits. On Windows, color
2276 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2277 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2278 expects that to match such a pixel format, we need to accommodate that. */
2279 if (mode->alpha_bits)
2281 if (mode->color_bits < color_bits)
2282 continue;
2284 else
2286 if (mode->bits_per_pixel < color_bits)
2287 continue;
2289 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2290 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2291 continue;
2292 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2293 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2294 continue;
2296 if (pixel_formats[i].accum_mode)
2298 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2299 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2300 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2301 mode->alpha_bits < accum_alpha_bits)
2302 continue;
2304 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2305 continue;
2307 piFormats[found++] = i + 1;
2308 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2311 cant_match:
2312 *nNumFormats = found;
2314 return TRUE;
2318 /***********************************************************************
2319 * macdrv_wglCreateContextAttribsARB
2321 * WGL_ARB_create_context: wglCreateContextAttribsARB
2323 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2324 struct wgl_context *share_context,
2325 const int *attrib_list)
2327 int format;
2328 struct wgl_context *context;
2329 const int *iptr;
2330 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2331 BOOL core = FALSE;
2333 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2335 format = get_dc_pixel_format(hdc);
2337 if (!is_valid_pixel_format(format))
2339 ERR("Invalid pixel format %d, expect problems!\n", format);
2340 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2341 return NULL;
2344 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2346 int attr = iptr[0];
2347 int value = iptr[1];
2349 TRACE("%s\n", debugstr_attrib(attr, value));
2351 switch (attr)
2353 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2354 major = value;
2355 break;
2357 case WGL_CONTEXT_MINOR_VERSION_ARB:
2358 minor = value;
2359 break;
2361 case WGL_CONTEXT_LAYER_PLANE_ARB:
2362 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2363 break;
2365 case WGL_CONTEXT_FLAGS_ARB:
2366 flags = value;
2367 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2368 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2369 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2370 break;
2372 case WGL_CONTEXT_PROFILE_MASK_ARB:
2373 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2374 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2376 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2377 SetLastError(ERROR_INVALID_PROFILE_ARB);
2378 return NULL;
2380 profile = value;
2381 break;
2383 default:
2384 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2385 SetLastError(ERROR_INVALID_PARAMETER);
2386 return NULL;
2390 if ((major == 3 && (minor == 2 || minor == 3)) ||
2391 (major == 4 && (minor == 0 || minor == 1)))
2393 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2395 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2396 SetLastError(ERROR_INVALID_VERSION_ARB);
2397 return NULL;
2399 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2401 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2402 SetLastError(ERROR_INVALID_PROFILE_ARB);
2403 return NULL;
2405 if (major > gl_info.max_major ||
2406 (major == gl_info.max_major && minor > gl_info.max_minor))
2408 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2409 major, minor);
2410 SetLastError(ERROR_INVALID_PROFILE_ARB);
2411 return NULL;
2413 core = TRUE;
2415 else if (major >= 3)
2417 WARN("Profile version %u.%u not supported\n", major, minor);
2418 SetLastError(ERROR_INVALID_VERSION_ARB);
2419 return NULL;
2421 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2422 (major == 2 && (minor < 0 || minor > 1)))
2424 WARN("Invalid GL version requested\n");
2425 SetLastError(ERROR_INVALID_VERSION_ARB);
2426 return NULL;
2428 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2430 WARN("Forward compatible context requested for GL version < 3\n");
2431 SetLastError(ERROR_INVALID_VERSION_ARB);
2432 return NULL;
2435 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2437 context->format = format;
2438 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2440 HeapFree(GetProcessHeap(), 0, context);
2441 return NULL;
2444 EnterCriticalSection(&context_section);
2445 list_add_tail(&context_list, &context->entry);
2446 LeaveCriticalSection(&context_section);
2448 return context;
2452 /**********************************************************************
2453 * macdrv_wglCreatePbufferARB
2455 * WGL_ARB_pbuffer: wglCreatePbufferARB
2457 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2458 const int *piAttribList)
2460 struct wgl_pbuffer* pbuffer;
2461 GLenum target = 0;
2462 GLenum internalFormat = 0;
2463 CGLError err;
2465 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2466 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2468 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2470 WARN("invalid pixel format %d\n", iPixelFormat);
2471 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2472 return NULL;
2475 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2476 pbuffer->format = iPixelFormat;
2478 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2480 int attr = piAttribList[0];
2481 int value = piAttribList[1];
2483 switch (attr)
2485 case WGL_PBUFFER_LARGEST_ARB:
2486 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2487 break;
2489 case WGL_TEXTURE_FORMAT_ARB:
2490 switch (value)
2492 case WGL_TEXTURE_RGBA_ARB:
2493 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2494 internalFormat = GL_RGBA;
2495 break;
2496 case WGL_TEXTURE_RGB_ARB:
2497 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2498 internalFormat = GL_RGB;
2499 break;
2500 case WGL_NO_TEXTURE_ARB:
2501 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2502 internalFormat = 0;
2503 break;
2504 default:
2505 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2506 SetLastError(ERROR_INVALID_DATA);
2507 goto done;
2509 break;
2511 case WGL_TEXTURE_TARGET_ARB:
2512 pbuffer->face = 0;
2513 switch (value)
2515 case WGL_NO_TEXTURE_ARB:
2516 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2517 target = 0;
2518 break;
2519 case WGL_TEXTURE_CUBE_MAP_ARB:
2520 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2521 target = GL_TEXTURE_CUBE_MAP;
2522 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2523 break;
2524 case WGL_TEXTURE_1D_ARB:
2525 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2526 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2527 goto done;
2528 case WGL_TEXTURE_2D_ARB:
2529 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2530 target = GL_TEXTURE_2D;
2531 break;
2532 case WGL_TEXTURE_RECTANGLE_NV:
2533 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2534 target = GL_TEXTURE_RECTANGLE;
2535 break;
2536 default:
2537 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2538 SetLastError(ERROR_INVALID_DATA);
2539 goto done;
2541 break;
2543 case WGL_MIPMAP_TEXTURE_ARB:
2544 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2545 pbuffer->max_level = 0;
2546 if (value)
2548 int size = min(iWidth, iHeight) / 2;
2549 while (size)
2551 pbuffer->max_level++;
2552 size /= 2;
2555 break;
2557 default:
2558 WARN("unknown attribute 0x%x\n", attr);
2559 SetLastError(ERROR_INVALID_DATA);
2560 goto done;
2564 if (!target || !internalFormat)
2566 pbuffer->no_texture = TRUE;
2567 /* no actual way to turn off ability to texture; use most permissive target */
2568 target = GL_TEXTURE_RECTANGLE;
2569 internalFormat = GL_RGB;
2572 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2573 if (err != kCGLNoError)
2575 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2576 pbuffer->pbuffer = NULL;
2577 if (err == kCGLBadAlloc)
2578 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2579 else
2580 SetLastError(ERROR_INVALID_DATA);
2583 done:
2584 if (!pbuffer->pbuffer)
2586 HeapFree(GetProcessHeap(), 0, pbuffer);
2587 return NULL;
2590 TRACE(" -> %p\n", pbuffer);
2591 return pbuffer;
2595 /**********************************************************************
2596 * macdrv_wglDestroyPbufferARB
2598 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2600 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2602 TRACE("pbuffer %p\n", pbuffer);
2603 if (pbuffer && pbuffer->pbuffer)
2604 CGLReleasePBuffer(pbuffer->pbuffer);
2605 HeapFree(GetProcessHeap(), 0, pbuffer);
2606 return GL_TRUE;
2610 /**********************************************************************
2611 * macdrv_wglGetExtensionsStringARB
2613 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2615 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2617 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2618 this can be specific to the CGL renderer like we're supposed to do. */
2619 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2620 return gl_info.wglExtensions;
2624 /**********************************************************************
2625 * macdrv_wglGetExtensionsStringEXT
2627 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2629 static const char *macdrv_wglGetExtensionsStringEXT(void)
2631 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2632 return gl_info.wglExtensions;
2636 /**********************************************************************
2637 * macdrv_wglGetPbufferDCARB
2639 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2641 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2643 HDC hdc;
2644 struct wgl_pbuffer *prev;
2646 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2647 if (!hdc) return 0;
2649 EnterCriticalSection(&dc_pbuffers_section);
2650 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2651 if (prev)
2653 CGLReleasePBuffer(prev->pbuffer);
2654 HeapFree(GetProcessHeap(), 0, prev);
2656 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2657 LeaveCriticalSection(&dc_pbuffers_section);
2659 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2660 return hdc;
2664 /**********************************************************************
2665 * macdrv_wglGetPixelFormatAttribivARB
2667 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2669 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2670 UINT nAttributes, const int *piAttributes, int *piValues)
2672 const pixel_format *pf;
2673 UINT i;
2675 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2676 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2678 if (!nAttributes) return GL_TRUE;
2680 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2682 piValues[0] = nb_formats;
2683 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2684 return GL_TRUE;
2687 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2688 if (!pf)
2690 WARN("invalid pixel format %d\n", iPixelFormat);
2691 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2692 return GL_FALSE;
2695 for (i = 0; i < nAttributes; ++i)
2697 switch (piAttributes[i])
2699 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2700 piValues[i] = nb_formats;
2701 break;
2703 case WGL_DRAW_TO_WINDOW_ARB:
2704 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2705 break;
2707 case WGL_DRAW_TO_BITMAP_ARB:
2708 piValues[i] = GL_FALSE;
2709 break;
2711 case WGL_ACCELERATION_ARB:
2712 if (iLayerPlane) goto invalid_layer;
2713 if (pf->accelerated)
2714 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2715 else
2716 piValues[i] = WGL_NO_ACCELERATION_ARB;
2717 break;
2719 case WGL_NEED_PALETTE_ARB:
2720 case WGL_NEED_SYSTEM_PALETTE_ARB:
2721 case WGL_SWAP_LAYER_BUFFERS_ARB:
2722 piValues[i] = GL_FALSE;
2723 break;
2725 case WGL_SWAP_METHOD_ARB:
2726 if (pf->double_buffer && pf->backing_store)
2727 piValues[i] = WGL_SWAP_COPY_ARB;
2728 else
2729 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2730 break;
2732 case WGL_NUMBER_OVERLAYS_ARB:
2733 case WGL_NUMBER_UNDERLAYS_ARB:
2734 piValues[i] = 0;
2735 break;
2737 case WGL_TRANSPARENT_ARB:
2738 if (iLayerPlane) goto invalid_layer;
2739 piValues[i] = GL_FALSE;
2740 break;
2742 case WGL_TRANSPARENT_RED_VALUE_ARB:
2743 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2744 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2745 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2746 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2747 if (iLayerPlane) goto invalid_layer;
2748 piValues[i] = 0;
2749 break;
2751 case WGL_SHARE_DEPTH_ARB:
2752 case WGL_SHARE_STENCIL_ARB:
2753 case WGL_SHARE_ACCUM_ARB:
2754 if (iLayerPlane) goto invalid_layer;
2755 piValues[i] = GL_TRUE;
2756 break;
2758 case WGL_SUPPORT_GDI_ARB:
2759 if (iLayerPlane) goto invalid_layer;
2760 piValues[i] = GL_FALSE;
2761 break;
2763 case WGL_SUPPORT_OPENGL_ARB:
2764 if (iLayerPlane) goto invalid_layer;
2765 piValues[i] = GL_TRUE;
2766 break;
2768 case WGL_DOUBLE_BUFFER_ARB:
2769 if (iLayerPlane) goto invalid_layer;
2770 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2771 break;
2773 case WGL_STEREO_ARB:
2774 if (iLayerPlane) goto invalid_layer;
2775 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2776 break;
2778 case WGL_PIXEL_TYPE_ARB:
2779 if (iLayerPlane) goto invalid_layer;
2780 if (color_modes[pf->color_mode].is_float)
2781 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2782 else
2783 piValues[i] = WGL_TYPE_RGBA_ARB;
2784 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2785 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2786 However, Mac contexts don't support rendering to unsigned floating-point
2787 formats, even when GL_EXT_packed_float is supported. */
2788 break;
2790 case WGL_COLOR_BITS_ARB:
2791 if (iLayerPlane) goto invalid_layer;
2792 /* If the mode doesn't have alpha, return bits per pixel instead
2793 of color bits. On Windows, color bits sometimes exceeds r+g+b
2794 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2795 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2796 pixel format, we need to accommodate that. */
2797 if (color_modes[pf->color_mode].alpha_bits)
2798 piValues[i] = color_modes[pf->color_mode].color_bits;
2799 else
2800 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2801 break;
2803 case WGL_RED_BITS_ARB:
2804 if (iLayerPlane) goto invalid_layer;
2805 piValues[i] = color_modes[pf->color_mode].red_bits;
2806 break;
2808 case WGL_RED_SHIFT_ARB:
2809 if (iLayerPlane) goto invalid_layer;
2810 piValues[i] = color_modes[pf->color_mode].red_shift;
2811 break;
2813 case WGL_GREEN_BITS_ARB:
2814 if (iLayerPlane) goto invalid_layer;
2815 piValues[i] = color_modes[pf->color_mode].green_bits;
2816 break;
2818 case WGL_GREEN_SHIFT_ARB:
2819 if (iLayerPlane) goto invalid_layer;
2820 piValues[i] = color_modes[pf->color_mode].green_shift;
2821 break;
2823 case WGL_BLUE_BITS_ARB:
2824 if (iLayerPlane) goto invalid_layer;
2825 piValues[i] = color_modes[pf->color_mode].blue_bits;
2826 break;
2828 case WGL_BLUE_SHIFT_ARB:
2829 if (iLayerPlane) goto invalid_layer;
2830 piValues[i] = color_modes[pf->color_mode].blue_shift;
2831 break;
2833 case WGL_ALPHA_BITS_ARB:
2834 if (iLayerPlane) goto invalid_layer;
2835 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2836 break;
2838 case WGL_ALPHA_SHIFT_ARB:
2839 if (iLayerPlane) goto invalid_layer;
2840 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2841 break;
2843 case WGL_ACCUM_BITS_ARB:
2844 if (iLayerPlane) goto invalid_layer;
2845 if (pf->accum_mode)
2846 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2847 else
2848 piValues[i] = 0;
2849 break;
2851 case WGL_ACCUM_RED_BITS_ARB:
2852 if (iLayerPlane) goto invalid_layer;
2853 if (pf->accum_mode)
2854 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2855 else
2856 piValues[i] = 0;
2857 break;
2859 case WGL_ACCUM_GREEN_BITS_ARB:
2860 if (iLayerPlane) goto invalid_layer;
2861 if (pf->accum_mode)
2862 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2863 else
2864 piValues[i] = 0;
2865 break;
2867 case WGL_ACCUM_BLUE_BITS_ARB:
2868 if (iLayerPlane) goto invalid_layer;
2869 if (pf->accum_mode)
2870 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2871 else
2872 piValues[i] = 0;
2873 break;
2875 case WGL_ACCUM_ALPHA_BITS_ARB:
2876 if (iLayerPlane) goto invalid_layer;
2877 if (pf->accum_mode)
2878 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2879 else
2880 piValues[i] = 0;
2881 break;
2883 case WGL_DEPTH_BITS_ARB:
2884 if (iLayerPlane) goto invalid_layer;
2885 piValues[i] = pf->depth_bits;
2886 break;
2888 case WGL_STENCIL_BITS_ARB:
2889 if (iLayerPlane) goto invalid_layer;
2890 piValues[i] = pf->stencil_bits;
2891 break;
2893 case WGL_AUX_BUFFERS_ARB:
2894 if (iLayerPlane) goto invalid_layer;
2895 piValues[i] = pf->aux_buffers;
2896 break;
2898 case WGL_SAMPLE_BUFFERS_ARB:
2899 if (iLayerPlane) goto invalid_layer;
2900 piValues[i] = pf->sample_buffers;
2901 break;
2903 case WGL_SAMPLES_ARB:
2904 if (iLayerPlane) goto invalid_layer;
2905 piValues[i] = pf->samples;
2906 break;
2908 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2909 if (iLayerPlane) goto invalid_layer;
2910 /* sRGB is only supported for 8-bit integer color components */
2911 if (color_modes[pf->color_mode].red_bits == 8 &&
2912 color_modes[pf->color_mode].green_bits == 8 &&
2913 color_modes[pf->color_mode].blue_bits == 8 &&
2914 !color_modes[pf->color_mode].is_float)
2915 piValues[i] = GL_TRUE;
2916 else
2917 piValues[i] = GL_FALSE;
2918 break;
2920 case WGL_DRAW_TO_PBUFFER_ARB:
2921 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2922 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2923 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2924 break;
2926 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2927 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2928 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2929 break;
2931 case WGL_MAX_PBUFFER_WIDTH_ARB:
2932 piValues[i] = gl_info.max_viewport_dims[0];
2933 break;
2935 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2936 piValues[i] = gl_info.max_viewport_dims[1];
2937 break;
2939 case WGL_MAX_PBUFFER_PIXELS_ARB:
2940 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2941 break;
2943 default:
2944 WARN("invalid attribute %x\n", piAttributes[i]);
2945 return GL_FALSE;
2948 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2951 return GL_TRUE;
2953 invalid_layer:
2954 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2955 return GL_FALSE;
2959 /**********************************************************************
2960 * macdrv_wglGetPixelFormatAttribfvARB
2962 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2964 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2965 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2967 int *attr;
2968 int ret;
2970 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2971 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2973 /* Allocate a temporary array to store integer values */
2974 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2975 if (!attr)
2977 ERR("couldn't allocate %d array\n", nAttributes);
2978 return GL_FALSE;
2981 /* Piggy-back on wglGetPixelFormatAttribivARB */
2982 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2983 if (ret)
2985 UINT i;
2987 /* Convert integer values to float. Should also check for attributes
2988 that can give decimal values here */
2989 for (i = 0; i < nAttributes; i++)
2990 pfValues[i] = attr[i];
2993 HeapFree(GetProcessHeap(), 0, attr);
2994 return ret;
2998 /**********************************************************************
2999 * macdrv_wglGetSwapIntervalEXT
3001 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3003 static int macdrv_wglGetSwapIntervalEXT(void)
3005 struct wgl_context *context = NtCurrentTeb()->glContext;
3006 struct macdrv_win_data *data;
3007 long value;
3008 CGLError err;
3010 TRACE("\n");
3012 if ((data = get_win_data(context->draw_hwnd)))
3014 value = data->swap_interval;
3015 release_win_data(data);
3017 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3018 set_swap_interval(context, value);
3020 else
3022 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3023 if (err != kCGLNoError)
3025 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3026 err, CGLErrorString(err));
3027 value = 1;
3031 return value;
3035 /***********************************************************************
3036 * macdrv_wglMakeContextCurrentARB
3038 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3040 * This is not supported directly by OpenGL on the Mac. We emulate it
3041 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3042 * temporarily swap the drawable. This follows the technique used in
3043 * the implementation of Mesa GLX for Apple.
3045 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3047 struct macdrv_win_data *data;
3048 HWND hwnd;
3050 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3051 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3053 if (!context)
3055 macdrv_make_context_current(NULL, NULL);
3056 NtCurrentTeb()->glContext = NULL;
3057 return TRUE;
3060 if ((hwnd = WindowFromDC(draw_hdc)))
3062 if (!(data = get_win_data(hwnd)))
3064 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3065 return FALSE;
3068 if (!data->pixel_format)
3070 WARN("no pixel format set\n");
3071 release_win_data(data);
3072 SetLastError(ERROR_INVALID_HANDLE);
3073 return FALSE;
3075 if (context->format != data->pixel_format)
3077 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3078 release_win_data(data);
3079 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3080 return FALSE;
3083 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3084 set_swap_interval(context, data->swap_interval);
3086 context->draw_hwnd = hwnd;
3087 context->draw_view = data->gl_view;
3088 context->draw_pbuffer = NULL;
3089 release_win_data(data);
3091 else
3093 struct wgl_pbuffer *pbuffer;
3095 EnterCriticalSection(&dc_pbuffers_section);
3096 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3097 if (pbuffer)
3099 if (context->format != pbuffer->format)
3101 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3102 LeaveCriticalSection(&dc_pbuffers_section);
3103 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3104 return FALSE;
3107 if (allow_vsync &&
3108 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3109 set_swap_interval(context, 0);
3111 else
3113 WARN("no window or pbuffer for DC\n");
3114 LeaveCriticalSection(&dc_pbuffers_section);
3115 SetLastError(ERROR_INVALID_HANDLE);
3116 return FALSE;
3119 context->draw_hwnd = NULL;
3120 context->draw_view = NULL;
3121 context->draw_pbuffer = pbuffer;
3122 LeaveCriticalSection(&dc_pbuffers_section);
3125 context->read_view = NULL;
3126 context->read_pbuffer = NULL;
3127 if (read_hdc && read_hdc != draw_hdc)
3129 if ((hwnd = WindowFromDC(read_hdc)))
3131 if ((data = get_win_data(hwnd)))
3133 if (data->gl_view != context->draw_view)
3134 context->read_view = data->gl_view;
3135 release_win_data(data);
3138 else
3140 EnterCriticalSection(&dc_pbuffers_section);
3141 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3142 LeaveCriticalSection(&dc_pbuffers_section);
3146 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3147 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
3149 make_context_current(context, FALSE);
3150 context->has_been_current = TRUE;
3151 NtCurrentTeb()->glContext = context;
3153 return TRUE;
3157 /**********************************************************************
3158 * macdrv_wglQueryPbufferARB
3160 * WGL_ARB_pbuffer: wglQueryPbufferARB
3162 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3164 CGLError err;
3165 GLsizei width;
3166 GLsizei height;
3167 GLenum target;
3168 GLenum internalFormat;
3169 GLint mipmap;
3171 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3173 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3174 if (err != kCGLNoError)
3176 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3177 SetLastError(ERROR_INVALID_HANDLE);
3178 return GL_FALSE;
3181 switch (iAttribute)
3183 case WGL_PBUFFER_WIDTH_ARB:
3184 *piValue = width;
3185 break;
3186 case WGL_PBUFFER_HEIGHT_ARB:
3187 *piValue = height;
3188 break;
3189 case WGL_PBUFFER_LOST_ARB:
3190 /* Mac PBuffers can't be lost */
3191 *piValue = GL_FALSE;
3192 break;
3193 case WGL_TEXTURE_FORMAT_ARB:
3194 if (pbuffer->no_texture)
3195 *piValue = WGL_NO_TEXTURE_ARB;
3196 else switch (internalFormat)
3198 case GL_RGBA:
3199 *piValue = WGL_TEXTURE_RGBA_ARB;
3200 break;
3201 case GL_RGB:
3202 default:
3203 *piValue = WGL_TEXTURE_RGB_ARB;
3204 break;
3206 break;
3207 case WGL_TEXTURE_TARGET_ARB:
3208 if (pbuffer->no_texture)
3209 *piValue = WGL_NO_TEXTURE_ARB;
3210 else switch (target)
3212 case GL_TEXTURE_CUBE_MAP:
3213 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3214 break;
3215 case GL_TEXTURE_2D:
3216 *piValue = WGL_TEXTURE_2D_ARB;
3217 break;
3218 case GL_TEXTURE_RECTANGLE:
3219 default:
3220 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3221 break;
3223 break;
3224 case WGL_MIPMAP_TEXTURE_ARB:
3225 *piValue = (pbuffer->max_level > 0);
3226 break;
3227 case WGL_MIPMAP_LEVEL_ARB:
3228 *piValue = pbuffer->level;
3229 break;
3230 case WGL_CUBE_MAP_FACE_ARB:
3231 switch (pbuffer->face)
3233 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3234 default:
3235 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3236 break;
3237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3238 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3239 break;
3240 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3241 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3242 break;
3243 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3244 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3245 break;
3246 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3247 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3248 break;
3249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3250 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3251 break;
3253 break;
3254 default:
3255 WARN("invalid attribute 0x%x\n", iAttribute);
3256 SetLastError(ERROR_INVALID_DATA);
3257 return GL_FALSE;
3260 return GL_TRUE;
3264 /**********************************************************************
3265 * macdrv_wglReleasePbufferDCARB
3267 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3269 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3271 struct wgl_pbuffer *prev;
3273 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3275 EnterCriticalSection(&dc_pbuffers_section);
3277 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3278 if (prev)
3280 if (prev != pbuffer)
3281 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3282 CGLReleasePBuffer(prev->pbuffer);
3283 HeapFree(GetProcessHeap(), 0, prev);
3284 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3286 else hdc = 0;
3288 LeaveCriticalSection(&dc_pbuffers_section);
3290 return hdc && DeleteDC(hdc);
3294 /**********************************************************************
3295 * macdrv_wglReleaseTexImageARB
3297 * WGL_ARB_render_texture: wglReleaseTexImageARB
3299 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3301 struct wgl_context *context = NtCurrentTeb()->glContext;
3302 CGLError err;
3304 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3306 if (pbuffer->no_texture)
3308 SetLastError(ERROR_INVALID_OPERATION);
3309 return GL_FALSE;
3312 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3313 if (err != kCGLNoError)
3315 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3316 SetLastError(ERROR_INVALID_OPERATION);
3317 return GL_FALSE;
3320 return GL_TRUE;
3324 /**********************************************************************
3325 * macdrv_wglSetPbufferAttribARB
3327 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3329 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3331 struct wgl_context *context = NtCurrentTeb()->glContext;
3333 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3335 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3337 int attr = piAttribList[0];
3338 int value = piAttribList[1];
3339 switch (attr)
3341 case WGL_MIPMAP_LEVEL_ARB:
3342 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3343 pbuffer->level = value;
3344 break;
3345 case WGL_CUBE_MAP_FACE_ARB:
3346 switch (value)
3348 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3349 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3350 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3351 break;
3352 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3353 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3354 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
3355 break;
3356 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3357 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3358 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
3359 break;
3360 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3361 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3362 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
3363 break;
3364 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3365 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3366 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
3367 break;
3368 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3369 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3370 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
3371 break;
3372 default:
3373 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
3374 SetLastError(ERROR_INVALID_DATA);
3375 return GL_FALSE;
3377 break;
3378 default:
3379 WARN("invalide attribute 0x%x\n", attr);
3380 SetLastError(ERROR_INVALID_DATA);
3381 return GL_FALSE;
3385 if (context && context->draw_pbuffer == pbuffer)
3386 make_context_current(context, FALSE);
3388 return GL_TRUE;
3392 /**********************************************************************
3393 * macdrv_wglSetPixelFormatWINE
3395 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3397 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
3399 return set_pixel_format(hdc, fmt, TRUE);
3403 /**********************************************************************
3404 * macdrv_wglSwapIntervalEXT
3406 * WGL_EXT_swap_control: wglSwapIntervalEXT
3408 static BOOL macdrv_wglSwapIntervalEXT(int interval)
3410 struct wgl_context *context = NtCurrentTeb()->glContext;
3411 BOOL changed = FALSE;
3413 TRACE("interval %d\n", interval);
3415 if (interval < 0)
3417 SetLastError(ERROR_INVALID_DATA);
3418 return FALSE;
3420 if (interval > 1)
3421 interval = 1;
3423 if (context->draw_hwnd)
3425 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
3426 if (data)
3428 changed = data->swap_interval != interval;
3429 if (changed)
3430 data->swap_interval = interval;
3431 release_win_data(data);
3434 else /* pbuffer */
3435 interval = 0;
3437 InterlockedExchange(&context->update_swap_interval, FALSE);
3438 if (!set_swap_interval(context, interval))
3440 SetLastError(ERROR_GEN_FAILURE);
3441 return FALSE;
3444 if (changed)
3446 struct wgl_context *ctx;
3448 EnterCriticalSection(&context_section);
3449 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
3451 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
3452 InterlockedExchange(&context->update_swap_interval, TRUE);
3454 LeaveCriticalSection(&context_section);
3457 return TRUE;
3461 static void register_extension(const char *ext)
3463 if (gl_info.wglExtensions[0])
3464 strcat(gl_info.wglExtensions, " ");
3465 strcat(gl_info.wglExtensions, ext);
3467 TRACE("'%s'\n", ext);
3470 static void load_extensions(void)
3473 * ARB Extensions
3475 register_extension("WGL_ARB_extensions_string");
3476 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
3478 register_extension("WGL_ARB_make_current_read");
3479 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
3480 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
3482 register_extension("WGL_ARB_pixel_format");
3483 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
3484 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
3485 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
3487 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
3489 register_extension("WGL_ARB_pixel_format_float");
3490 register_extension("WGL_ATI_pixel_format_float");
3493 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
3494 register_extension("WGL_ARB_multisample");
3496 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3497 register_extension("WGL_ARB_framebuffer_sRGB");
3499 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
3501 register_extension("WGL_ARB_pbuffer");
3502 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3503 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3504 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3505 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3506 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3508 register_extension("WGL_ARB_render_texture");
3509 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3510 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3511 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3513 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3514 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3515 register_extension("WGL_NV_render_texture_rectangle");
3518 register_extension("WGL_ARB_create_context");
3519 register_extension("WGL_ARB_create_context_profile");
3520 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
3523 * EXT Extensions
3525 register_extension("WGL_EXT_extensions_string");
3526 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3528 if (allow_vsync)
3530 register_extension("WGL_EXT_swap_control");
3531 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3532 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3535 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3536 check for either, so register them separately. */
3537 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3538 register_extension("WGL_EXT_framebuffer_sRGB");
3540 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3541 register_extension("WGL_EXT_pixel_format_packed_float");
3544 * WINE-specific WGL Extensions
3547 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3548 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3550 register_extension("WGL_WINE_pixel_format_passthrough");
3551 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3555 static BOOL init_opengl(void)
3557 static BOOL init_done = FALSE;
3558 unsigned int i;
3559 char buffer[200];
3561 if (init_done) return (opengl_handle != NULL);
3562 init_done = TRUE;
3564 TRACE("()\n");
3566 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3567 if (!dc_pbuffers)
3569 WARN("CFDictionaryCreateMutable failed\n");
3570 return FALSE;
3573 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3574 if (!opengl_handle)
3576 ERR("Failed to load OpenGL: %s\n", buffer);
3577 ERR("OpenGL support is disabled.\n");
3578 return FALSE;
3581 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3583 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3585 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3586 goto failed;
3590 /* redirect some standard OpenGL functions */
3591 #define REDIRECT(func) \
3592 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3593 REDIRECT(glCopyPixels);
3594 REDIRECT(glGetString);
3595 REDIRECT(glReadPixels);
3596 REDIRECT(glViewport);
3597 if (skip_single_buffer_flushes || allow_vsync)
3598 REDIRECT(glFlush);
3599 if (allow_vsync)
3600 REDIRECT(glFinish);
3601 #undef REDIRECT
3603 /* redirect some OpenGL extension functions */
3604 #define REDIRECT(func) \
3605 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3606 REDIRECT(glCopyColorTable);
3607 #undef REDIRECT
3609 if (!init_gl_info())
3610 goto failed;
3612 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3613 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3615 load_extensions();
3616 if (!init_pixel_formats())
3617 goto failed;
3619 return TRUE;
3621 failed:
3622 wine_dlclose(opengl_handle, NULL, 0);
3623 opengl_handle = NULL;
3624 return FALSE;
3628 /***********************************************************************
3629 * sync_gl_view
3631 * Synchronize the Mac GL view position with the Windows child window
3632 * position.
3634 void sync_gl_view(struct macdrv_win_data *data)
3636 RECT rect;
3638 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3640 if (!data->gl_view) return;
3642 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3644 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3645 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3646 data->gl_rect = rect;
3651 /**********************************************************************
3652 * macdrv_wglDescribePixelFormat
3654 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3656 const pixel_format *pf;
3657 const struct color_mode *mode;
3659 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3661 if (!descr) return nb_displayable_formats;
3662 if (size < sizeof(*descr)) return 0;
3664 if (!(pf = get_pixel_format(fmt, FALSE)))
3665 return 0;
3667 memset(descr, 0, sizeof(*descr));
3668 descr->nSize = sizeof(*descr);
3669 descr->nVersion = 1;
3671 descr->dwFlags = PFD_SUPPORT_OPENGL;
3672 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3673 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3674 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3675 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3676 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3678 descr->iPixelType = PFD_TYPE_RGBA;
3680 mode = &color_modes[pf->color_mode];
3681 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3682 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3683 R8G8B8A0 pixel format). If an app depends on that and expects that
3684 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3685 if (mode->alpha_bits)
3686 descr->cColorBits = mode->color_bits;
3687 else
3688 descr->cColorBits = mode->bits_per_pixel;
3689 descr->cRedBits = mode->red_bits;
3690 descr->cRedShift = mode->red_shift;
3691 descr->cGreenBits = mode->green_bits;
3692 descr->cGreenShift = mode->green_shift;
3693 descr->cBlueBits = mode->blue_bits;
3694 descr->cBlueShift = mode->blue_shift;
3695 descr->cAlphaBits = mode->alpha_bits;
3696 descr->cAlphaShift = mode->alpha_shift;
3698 if (pf->accum_mode)
3700 mode = &color_modes[pf->accum_mode - 1];
3701 descr->cAccumBits = mode->color_bits;
3702 descr->cAccumRedBits = mode->red_bits;
3703 descr->cAccumGreenBits = mode->green_bits;
3704 descr->cAccumBlueBits = mode->blue_bits;
3705 descr->cAccumAlphaBits = mode->alpha_bits;
3708 descr->cDepthBits = pf->depth_bits;
3709 descr->cStencilBits = pf->stencil_bits;
3710 descr->cAuxBuffers = pf->aux_buffers;
3711 descr->iLayerType = PFD_MAIN_PLANE;
3713 TRACE("%s\n", debugstr_pf(pf));
3714 return nb_displayable_formats;
3717 /***********************************************************************
3718 * macdrv_wglCopyContext
3720 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3722 CGLError err;
3724 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3726 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3727 if (err != kCGLNoError)
3728 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3729 return (err == kCGLNoError);
3732 /***********************************************************************
3733 * macdrv_wglCreateContext
3735 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3737 struct wgl_context *context;
3739 TRACE("hdc %p\n", hdc);
3741 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
3743 return context;
3746 /***********************************************************************
3747 * macdrv_wglDeleteContext
3749 static void macdrv_wglDeleteContext(struct wgl_context *context)
3751 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3753 EnterCriticalSection(&context_section);
3754 list_remove(&context->entry);
3755 LeaveCriticalSection(&context_section);
3757 macdrv_dispose_opengl_context(context->context);
3758 HeapFree(GetProcessHeap(), 0, context);
3761 /***********************************************************************
3762 * macdrv_wglGetPixelFormat
3764 static int macdrv_wglGetPixelFormat(HDC hdc)
3766 int format;
3768 format = get_dc_pixel_format(hdc);
3770 if (!is_valid_pixel_format(format)) /* not set yet */
3771 format = 0;
3772 else if (!is_displayable_pixel_format(format))
3774 /* Non-displayable formats can't be used with traditional WGL calls.
3775 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3776 format = 1;
3779 TRACE(" hdc %p -> %d\n", hdc, format);
3780 return format;
3783 /***********************************************************************
3784 * macdrv_wglGetProcAddress
3786 static PROC macdrv_wglGetProcAddress(const char *proc)
3788 void *ret;
3790 if (!strncmp(proc, "wgl", 3)) return NULL;
3791 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3792 if (ret)
3794 if (TRACE_ON(wgl))
3796 Dl_info info;
3797 if (dladdr(ret, &info))
3798 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3799 else
3800 TRACE("%s -> %p (no library info)\n", proc, ret);
3803 else
3804 WARN("failed to find proc %s\n", debugstr_a(proc));
3805 return ret;
3808 /***********************************************************************
3809 * macdrv_wglMakeCurrent
3811 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3813 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3814 (context ? context->cglcontext : NULL));
3816 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3819 /**********************************************************************
3820 * macdrv_wglSetPixelFormat
3822 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3824 return set_pixel_format(hdc, fmt, FALSE);
3827 /***********************************************************************
3828 * macdrv_wglShareLists
3830 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3832 macdrv_opengl_context saved_context;
3833 CGLContextObj saved_cglcontext;
3835 TRACE("org %p dest %p\n", org, dest);
3837 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3838 * at context creation time but in case of WGL it is done using wglShareLists.
3840 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3841 * and when a program requests sharing we recreate the destination context if it hasn't been made
3842 * current or when it hasn't shared display lists before.
3845 if (dest->has_been_current)
3847 WARN("could not share display lists, the destination context has been current already\n");
3848 return FALSE;
3850 else if (dest->sharing)
3852 WARN("could not share display lists because dest has already shared lists before\n");
3853 return FALSE;
3856 /* Re-create the Mac context and share display lists */
3857 saved_context = dest->context;
3858 saved_cglcontext = dest->cglcontext;
3859 dest->context = NULL;
3860 dest->cglcontext = NULL;
3861 if (!create_context(dest, org->cglcontext, dest->major))
3863 dest->context = saved_context;
3864 dest->cglcontext = saved_cglcontext;
3865 return FALSE;
3868 /* Implicitly disposes of saved_cglcontext. */
3869 macdrv_dispose_opengl_context(saved_context);
3871 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3872 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3874 org->sharing = TRUE;
3875 dest->sharing = TRUE;
3877 return TRUE;
3880 /**********************************************************************
3881 * macdrv_wglSwapBuffers
3883 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3885 struct wgl_context *context = NtCurrentTeb()->glContext;
3886 BOOL match = FALSE;
3887 HWND hwnd;
3889 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3890 (context ? context->cglcontext : NULL));
3892 if (context)
3893 sync_swap_interval(context);
3895 if ((hwnd = WindowFromDC(hdc)))
3897 struct macdrv_win_data *data;
3899 if (!(data = get_win_data(hwnd)))
3901 SetLastError(ERROR_INVALID_HANDLE);
3902 return FALSE;
3905 if (context && context->draw_view == data->gl_view)
3906 match = TRUE;
3908 release_win_data(data);
3910 else
3912 struct wgl_pbuffer *pbuffer;
3914 EnterCriticalSection(&dc_pbuffers_section);
3915 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3916 LeaveCriticalSection(&dc_pbuffers_section);
3918 if (!pbuffer)
3920 SetLastError(ERROR_INVALID_HANDLE);
3921 return FALSE;
3924 if (context && context->draw_pbuffer == pbuffer)
3925 match = TRUE;
3928 if (match)
3929 macdrv_flush_opengl_context(context->context);
3930 else
3932 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3934 /* If there is a current context, then wglSwapBuffers should do an implicit
3935 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3936 in the other branch, but we have to do it explicitly here. */
3937 if (context)
3938 pglFlush();
3941 return TRUE;
3944 static struct opengl_funcs opengl_funcs =
3947 macdrv_wglCopyContext, /* p_wglCopyContext */
3948 macdrv_wglCreateContext, /* p_wglCreateContext */
3949 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3950 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3951 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3952 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3953 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3954 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3955 macdrv_wglShareLists, /* p_wglShareLists */
3956 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3960 /**********************************************************************
3961 * macdrv_wine_get_wgl_driver
3963 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3965 if (version != WINE_WGL_DRIVER_VERSION)
3967 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3968 return NULL;
3971 if (!init_opengl()) return (void *)-1;
3973 return &opengl_funcs;