include: Add event trace flags and guid to evntrace.h.
[wine.git] / dlls / winemac.drv / opengl.c
blob220efa3be0d55bb86cf037157f2d4f7c43446343
1 /*
2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include "macdrv.h"
27 #include "winuser.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32 #include "wine/wgl.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
36 #define __gl_h_
37 #define __gltypes_h_
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
41 #include <dlfcn.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 struct gl_info {
47 char *glVersion;
48 char *glExtensions;
50 char wglExtensions[4096];
52 GLint max_viewport_dims[2];
54 unsigned int max_major, max_minor;
57 static struct gl_info gl_info;
60 struct wgl_context
62 struct list entry;
63 int format;
64 macdrv_opengl_context context;
65 CGLContextObj cglcontext;
66 HWND draw_hwnd;
67 macdrv_view draw_view;
68 struct wgl_pbuffer *draw_pbuffer;
69 macdrv_view read_view;
70 struct wgl_pbuffer *read_pbuffer;
71 BOOL has_been_current;
72 BOOL sharing;
73 LONG update_swap_interval;
74 DWORD last_flush_time;
75 UINT major;
78 static struct list context_list = LIST_INIT(context_list);
80 static CRITICAL_SECTION context_section;
81 static CRITICAL_SECTION_DEBUG critsect_debug =
83 0, 0, &context_section,
84 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
85 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
87 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
90 struct wgl_pbuffer
92 CGLPBufferObj pbuffer;
93 int format;
94 BOOL no_texture;
95 int max_level;
96 GLint level;
97 GLenum face;
100 static CFMutableDictionaryRef dc_pbuffers;
102 static CRITICAL_SECTION dc_pbuffers_section;
103 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
105 0, 0, &dc_pbuffers_section,
106 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
107 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
109 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
112 static struct opengl_funcs opengl_funcs;
114 #define USE_GL_FUNC(name) #name,
115 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
116 #undef USE_GL_FUNC
119 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
120 GLsizei width);
121 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
122 static void (*pglFinish)(void);
123 static void (*pglFlush)(void);
124 static void (*pglFlushRenderAPPLE)(void);
125 static const GLubyte *(*pglGetString)(GLenum name);
126 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
127 GLenum format, GLenum type, void *pixels);
128 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
131 struct color_mode {
132 GLint mode;
133 int bits_per_pixel;
134 GLint color_bits; /* including alpha_bits */
135 int red_bits, red_shift;
136 int green_bits, green_shift;
137 int blue_bits, blue_shift;
138 GLint alpha_bits, alpha_shift;
139 BOOL is_float;
140 int color_ordering;
143 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
144 observations of the behavior of Windows systems, but also subjective judgments
145 about what color formats are more "normal" than others.
147 On at least some Windows systems, integer color formats are listed before
148 floating-point formats. Within the integer formats, higher color bits were
149 usually listed before lower color bits, while for floating-point formats it
150 was the reverse. However, that leads D3D to select 64-bit integer formats in
151 preference to 32-bit formats when the latter would be sufficient. It seems
152 that a 32-bit format is much more likely to be normally used in that case.
154 Also, there are certain odd color formats supported on the Mac which seem like
155 they would be less appropriate than more common ones. For instance, the color
156 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
157 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
158 components.
160 For two color formats which differ only in whether or not they have alpha bits,
161 we use the same ordering. pixel_format_comparator() gives alpha bits a
162 different weight than color formats.
164 static const struct color_mode color_modes[] = {
165 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
166 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
167 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
168 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
169 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
170 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
171 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
172 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
173 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
174 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
175 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
176 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
177 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
178 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
179 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
180 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
181 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
182 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
183 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
184 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
185 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
186 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
187 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
188 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
192 static const struct {
193 GLint mode;
194 int bits;
195 } depth_stencil_modes[] = {
196 { kCGL0Bit, 0 },
197 { kCGL1Bit, 1 },
198 { kCGL2Bit, 2 },
199 { kCGL3Bit, 3 },
200 { kCGL4Bit, 4 },
201 { kCGL5Bit, 5 },
202 { kCGL6Bit, 6 },
203 { kCGL8Bit, 8 },
204 { kCGL10Bit, 10 },
205 { kCGL12Bit, 12 },
206 { kCGL16Bit, 16 },
207 { kCGL24Bit, 24 },
208 { kCGL32Bit, 32 },
209 { kCGL48Bit, 48 },
210 { kCGL64Bit, 64 },
211 { kCGL96Bit, 96 },
212 { kCGL128Bit, 128 },
216 typedef struct {
217 GLint renderer_id;
218 GLint buffer_modes;
219 GLint color_modes;
220 GLint accum_modes;
221 GLint depth_modes;
222 GLint stencil_modes;
223 GLint max_aux_buffers;
224 GLint max_sample_buffers;
225 GLint max_samples;
226 BOOL offscreen;
227 BOOL accelerated;
228 BOOL backing_store;
229 BOOL window;
230 BOOL online;
231 } renderer_properties;
234 typedef struct {
235 unsigned int window:1;
236 unsigned int pbuffer:1;
237 unsigned int accelerated:1;
238 unsigned int color_mode:5; /* index into color_modes table */
239 unsigned int aux_buffers:3;
240 unsigned int depth_bits:8;
241 unsigned int stencil_bits:8;
242 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
243 unsigned int double_buffer:1;
244 unsigned int stereo:1;
245 unsigned int sample_buffers:1;
246 unsigned int samples:5;
247 unsigned int backing_store:1;
248 } pixel_format;
251 typedef union
253 pixel_format format;
254 UInt64 code;
255 } pixel_format_or_code;
256 C_ASSERT(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
259 static pixel_format *pixel_formats;
260 static int nb_formats, nb_displayable_formats;
263 static void *opengl_handle;
266 static const char* debugstr_attrib(int attrib, int value)
268 static const struct {
269 int attrib;
270 const char *name;
271 } attrib_names[] = {
272 #define ATTRIB(a) { a, #a }
273 ATTRIB(WGL_ACCELERATION_ARB),
274 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
275 ATTRIB(WGL_ACCUM_BITS_ARB),
276 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
277 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
278 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
279 ATTRIB(WGL_ALPHA_BITS_ARB),
280 ATTRIB(WGL_ALPHA_SHIFT_ARB),
281 ATTRIB(WGL_AUX_BUFFERS_ARB),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
286 ATTRIB(WGL_BLUE_BITS_ARB),
287 ATTRIB(WGL_BLUE_SHIFT_ARB),
288 ATTRIB(WGL_COLOR_BITS_ARB),
289 ATTRIB(WGL_DEPTH_BITS_ARB),
290 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
291 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
292 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
293 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
294 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
295 ATTRIB(WGL_GREEN_BITS_ARB),
296 ATTRIB(WGL_GREEN_SHIFT_ARB),
297 ATTRIB(WGL_NEED_PALETTE_ARB),
298 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
299 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
300 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
301 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
302 ATTRIB(WGL_PIXEL_TYPE_ARB),
303 ATTRIB(WGL_RED_BITS_ARB),
304 ATTRIB(WGL_RED_SHIFT_ARB),
305 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
306 ATTRIB(WGL_SAMPLES_ARB),
307 ATTRIB(WGL_SHARE_ACCUM_ARB),
308 ATTRIB(WGL_SHARE_DEPTH_ARB),
309 ATTRIB(WGL_SHARE_STENCIL_ARB),
310 ATTRIB(WGL_STENCIL_BITS_ARB),
311 ATTRIB(WGL_STEREO_ARB),
312 ATTRIB(WGL_SUPPORT_GDI_ARB),
313 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
314 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
315 ATTRIB(WGL_SWAP_METHOD_ARB),
316 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
317 ATTRIB(WGL_TRANSPARENT_ARB),
318 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
319 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
320 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
321 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
322 #undef ATTRIB
324 int i;
325 const char *attrib_name = NULL;
326 const char *value_name = NULL;
328 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
330 if (attrib_names[i].attrib == attrib)
332 attrib_name = attrib_names[i].name;
333 break;
337 if (!attrib_name)
338 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
340 switch (attrib)
342 case WGL_ACCELERATION_ARB:
343 switch (value)
345 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
346 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
347 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
349 break;
350 case WGL_PIXEL_TYPE_ARB:
351 switch (value)
353 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
354 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
355 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
356 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
358 break;
359 case WGL_SWAP_METHOD_ARB:
360 switch (value)
362 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
363 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
364 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
366 break;
369 if (!value_name)
370 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
372 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
376 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
377 CGLRendererProperty property, GLint *value)
379 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
380 if (err != kCGLNoError)
381 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
382 return (err == kCGLNoError);
386 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
388 GLint value;
390 memset(properties, 0, sizeof(*properties));
392 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
393 properties->renderer_id = value & kCGLRendererIDMatchingMask;
395 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
396 properties->buffer_modes = value;
398 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
399 properties->color_modes = value;
401 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
402 properties->accum_modes = value;
404 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
405 properties->depth_modes = value;
407 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
408 properties->stencil_modes = value;
410 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
411 properties->max_aux_buffers = value;
413 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
414 properties->max_sample_buffers = value;
416 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
417 properties->max_samples = value;
419 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
420 properties->offscreen = (value != 0);
422 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
423 properties->accelerated = (value != 0);
425 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
426 properties->backing_store = (value != 0);
428 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
429 properties->window = (value != 0);
431 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
432 properties->online = (value != 0);
436 static void dump_renderer(const renderer_properties* renderer)
438 int i;
440 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
441 TRACE("Buffer modes:\n");
442 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
443 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
444 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
445 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
447 TRACE("Color buffer modes:\n");
448 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
450 if (renderer->color_modes & color_modes[i].mode)
452 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
453 if (color_modes[i].is_float)
454 TRACE(", Float");
455 TRACE("\n");
459 TRACE("Accumulation buffer sizes: { ");
460 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
462 if (renderer->accum_modes & color_modes[i].mode)
463 TRACE("%d, ", color_modes[i].color_bits);
465 TRACE("}\n");
467 TRACE("Depth buffer sizes: { ");
468 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
470 if (renderer->depth_modes & depth_stencil_modes[i].mode)
471 TRACE("%d, ", depth_stencil_modes[i].bits);
473 TRACE("}\n");
475 TRACE("Stencil buffer sizes: { ");
476 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
478 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
479 TRACE("%d, ", depth_stencil_modes[i].bits);
481 TRACE("}\n");
483 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
484 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
485 TRACE("Max. Samples: %d\n", renderer->max_samples);
486 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
487 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
488 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
489 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
490 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
494 static inline UInt64 code_for_pixel_format(const pixel_format* format)
496 pixel_format_or_code pfc;
498 pfc.code = 0;
499 pfc.format = *format;
500 return pfc.code;
504 static inline pixel_format pixel_format_for_code(UInt64 code)
506 pixel_format_or_code pfc;
508 pfc.code = code;
509 return pfc.format;
513 static const char *debugstr_pf(const pixel_format *pf)
515 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",
516 pf->window,
517 pf->pbuffer,
518 pf->accelerated,
519 color_modes[pf->color_mode].color_bits,
520 (color_modes[pf->color_mode].is_float ? "f" : ""),
521 color_modes[pf->color_mode].alpha_bits,
522 pf->depth_bits,
523 pf->stencil_bits,
524 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
525 pf->aux_buffers,
526 pf->backing_store,
527 pf->double_buffer,
528 pf->stereo,
529 pf->sample_buffers,
530 pf->samples,
531 code_for_pixel_format(pf));
535 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
537 int best = -1;
538 int i;
540 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
542 if ((modes & color_modes[i].mode) &&
543 color_modes[i].color_bits >= color_size &&
544 color_modes[i].alpha_bits >= alpha_size &&
545 !color_modes[i].is_float == !color_float)
547 if (best < 0) /* no existing best choice */
548 best = i;
549 else if (color_modes[i].color_bits == color_size &&
550 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
552 /* prefer it over a best which isn't exact or which has a higher bpp */
553 if (color_modes[best].color_bits != color_size ||
554 color_modes[best].alpha_bits != alpha_size ||
555 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
556 best = i;
558 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
559 (color_modes[i].color_bits == color_modes[best].color_bits &&
560 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
561 best = i;
565 if (best < 0)
567 /* Couldn't find a match. Return first one that renderer supports. */
568 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
570 if (modes & color_modes[i].mode)
571 return i;
575 return best;
579 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
581 int best = -1;
582 int i;
584 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
586 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
588 /* Prefer the fewest color bits, then prefer more alpha bits, then
589 prefer more bits per pixel. */
590 if (best < 0)
591 best = i;
592 else if (color_modes[i].color_bits < color_modes[best].color_bits)
593 best = i;
594 else if (color_modes[i].color_bits == color_modes[best].color_bits)
596 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
597 best = i;
598 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
599 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
600 best = i;
605 if (best < 0)
607 /* Couldn't find a match. Return last one that renderer supports. */
608 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
610 if (modes & color_modes[i].mode)
611 return i;
615 return best;
619 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
620 CFMutableSetRef pixel_format_set)
622 CGLPixelFormatAttribute attribs[64] = {
623 kCGLPFAMinimumPolicy,
624 kCGLPFAClosestPolicy,
625 kCGLPFARendererID, renderer.renderer_id,
626 kCGLPFASingleRenderer,
628 int n = 5, n_stack[16], n_stack_idx = -1;
629 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
630 new_pixel_formats = 0;
631 pixel_format request;
632 unsigned int double_buffer;
633 unsigned int accelerated = renderer.accelerated;
635 if (accelerated)
637 attribs[n++] = kCGLPFAAccelerated;
638 attribs[n++] = kCGLPFANoRecovery;
640 else if (!allow_software_rendering)
642 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
643 return;
646 n_stack[++n_stack_idx] = n;
647 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
649 unsigned int aux;
651 n = n_stack[n_stack_idx];
653 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
654 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
655 continue;
657 if (double_buffer)
658 attribs[n++] = kCGLPFADoubleBuffer;
659 memset(&request, 0, sizeof(request));
660 request.accelerated = accelerated;
661 request.double_buffer = double_buffer;
663 /* Don't bother with in-between aux buffers values: either 0 or max. */
664 n_stack[++n_stack_idx] = n;
665 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
667 unsigned int color_mode;
669 n = n_stack[n_stack_idx];
671 attribs[n++] = kCGLPFAAuxBuffers;
672 attribs[n++] = aux;
673 request.aux_buffers = aux;
675 n_stack[++n_stack_idx] = n;
676 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
678 unsigned int depth_mode;
680 n = n_stack[n_stack_idx];
682 if (!(renderer.color_modes & color_modes[color_mode].mode))
683 continue;
685 attribs[n++] = kCGLPFAColorSize;
686 attribs[n++] = color_modes[color_mode].color_bits;
687 attribs[n++] = kCGLPFAAlphaSize;
688 attribs[n++] = color_modes[color_mode].alpha_bits;
689 if (color_modes[color_mode].is_float)
690 attribs[n++] = kCGLPFAColorFloat;
691 request.color_mode = color_mode;
693 n_stack[++n_stack_idx] = n;
694 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
696 unsigned int stencil_mode;
698 n = n_stack[n_stack_idx];
700 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
701 continue;
703 attribs[n++] = kCGLPFADepthSize;
704 attribs[n++] = depth_stencil_modes[depth_mode].bits;
705 request.depth_bits = depth_stencil_modes[depth_mode].bits;
707 n_stack[++n_stack_idx] = n;
708 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
710 unsigned int stereo;
712 n = n_stack[n_stack_idx];
714 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
715 continue;
716 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
717 continue;
719 attribs[n++] = kCGLPFAStencilSize;
720 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
721 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
723 /* FIXME: Could trim search space a bit here depending on GPU.
724 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
725 n_stack[++n_stack_idx] = n;
726 for (stereo = 0; stereo <= 1; stereo++)
728 int accum_mode;
730 n = n_stack[n_stack_idx];
732 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
733 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
734 continue;
736 if (stereo)
737 attribs[n++] = kCGLPFAStereo;
738 request.stereo = stereo;
740 /* Starts at -1 for a 0 accum size */
741 n_stack[++n_stack_idx] = n;
742 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
744 unsigned int target_pass;
746 n = n_stack[n_stack_idx];
748 if (accum_mode >= 0)
750 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
751 continue;
753 attribs[n++] = kCGLPFAAccumSize;
754 attribs[n++] = color_modes[accum_mode].color_bits;
755 request.accum_mode = accum_mode + 1;
757 else
758 request.accum_mode = 0;
760 /* Targets to request are:
761 accelerated: window OR window + pbuffer
762 software: window + pbuffer */
763 n_stack[++n_stack_idx] = n;
764 for (target_pass = 0; target_pass <= accelerated; target_pass++)
766 unsigned int samples, max_samples;
768 n = n_stack[n_stack_idx];
770 attribs[n++] = kCGLPFAWindow;
771 request.window = 1;
773 if (!accelerated || target_pass > 0)
775 attribs[n++] = kCGLPFAPBuffer;
776 request.pbuffer = 1;
778 else
779 request.pbuffer = 0;
781 /* FIXME: Could trim search space a bit here depending on GPU.
782 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
783 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
784 n_stack[++n_stack_idx] = n;
785 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
786 for (samples = 1; samples <= max_samples; samples *= 2)
788 unsigned int backing_store, min_backing_store, max_backing_store;
790 n = n_stack[n_stack_idx];
792 if (samples > 1)
794 attribs[n++] = kCGLPFASampleBuffers;
795 attribs[n++] = renderer.max_sample_buffers;
796 attribs[n++] = kCGLPFASamples;
797 attribs[n++] = samples;
798 request.sample_buffers = renderer.max_sample_buffers;
799 request.samples = samples;
801 else
802 request.sample_buffers = request.samples = 0;
804 if (renderer.backing_store && double_buffer)
806 /* The software renderer seems to always preserve the backing store, whether
807 we ask for it or not. So don't bother not asking for it. */
808 min_backing_store = accelerated ? 0 : 1;
809 max_backing_store = 1;
811 else
812 min_backing_store = max_backing_store = 0;
813 n_stack[++n_stack_idx] = n;
814 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
816 CGLPixelFormatObj pix;
817 GLint virtualScreens;
818 CGLError err;
820 n = n_stack[n_stack_idx];
822 if (backing_store)
823 attribs[n++] = kCGLPFABackingStore;
824 request.backing_store = backing_store;
826 attribs[n] = 0;
828 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
829 if (err == kCGLNoError && pix)
831 pixel_format pf;
832 GLint value, color_size, alpha_size, color_float;
833 UInt64 pf_code;
834 CFNumberRef code_object;
835 BOOL dupe;
837 memset(&pf, 0, sizeof(pf));
839 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
840 pf.accelerated = value;
841 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
842 pf.aux_buffers = value;
843 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
844 pf.depth_bits = value;
845 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
846 pf.double_buffer = value;
847 if (pf.double_buffer &&
848 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
849 pf.backing_store = value;
850 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
851 pf.pbuffer = value;
852 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
853 pf.sample_buffers = value;
854 if (pf.sample_buffers &&
855 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
856 pf.samples = value;
857 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
858 pf.stencil_bits = value;
859 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
860 pf.stereo = value;
861 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
862 pf.window = value;
864 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
865 color_size = 0;
866 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
867 alpha_size = 0;
868 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
869 color_float = 0;
870 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
872 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
873 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
875 CGLReleasePixelFormat(pix);
877 pf_code = code_for_pixel_format(&pf);
879 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
880 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
881 dupe_pixel_formats++;
882 else
884 CFSetAddValue(pixel_format_set, code_object);
885 CFArrayAppendValue(pixel_format_array, code_object);
886 new_pixel_formats++;
888 CFRelease(code_object);
890 if (pf_code == code_for_pixel_format(&request))
891 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
892 else
894 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
895 dupe ? " (duplicate)" : "");
898 else
900 failed_pixel_formats++;
901 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
904 tried_pixel_formats++;
907 n_stack_idx--;
910 n_stack_idx--;
913 n_stack_idx--;
916 n_stack_idx--;
919 n_stack_idx--;
922 n_stack_idx--;
925 n_stack_idx--;
928 n_stack_idx--;
931 n_stack_idx--;
934 n_stack_idx--;
936 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
937 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
938 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
939 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
943 /* The docs for WGL_ARB_pixel_format say:
944 Indices are assigned to pixel formats in the following order:
945 1. Accelerated pixel formats that are displayable
946 2. Accelerated pixel formats that are displayable and which have
947 extended attributes
948 3. Generic pixel formats
949 4. Accelerated pixel formats that are non displayable
951 static int pixel_format_category(pixel_format pf)
953 /* non-displayable */
954 if (!pf.window)
955 return 4;
957 /* non-accelerated a.k.a. software a.k.a. generic */
958 if (!pf.accelerated)
959 return 3;
961 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
962 if (color_modes[pf.color_mode].is_float)
963 return 2;
965 /* accelerated, displayable, no extended attributes */
966 return 1;
970 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
972 CFNumberRef number1 = val1;
973 CFNumberRef number2 = val2;
974 UInt64 code1, code2;
975 pixel_format pf1, pf2;
976 int category1, category2;
978 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
979 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
980 pf1 = pixel_format_for_code(code1);
981 pf2 = pixel_format_for_code(code2);
982 category1 = pixel_format_category(pf1);
983 category2 = pixel_format_category(pf2);
985 if (category1 < category2)
986 return kCFCompareLessThan;
987 if (category1 > category2)
988 return kCFCompareGreaterThan;
990 /* Within a category, sort the "best" formats toward the front since that's
991 what wglChoosePixelFormatARB() has to do. The ordering implemented here
992 matches at least one Windows 7 machine's behavior.
994 /* Accelerated before unaccelerated. */
995 if (pf1.accelerated && !pf2.accelerated)
996 return kCFCompareLessThan;
997 if (!pf1.accelerated && pf2.accelerated)
998 return kCFCompareGreaterThan;
1000 /* Explicit color mode ordering. */
1001 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
1002 return kCFCompareLessThan;
1003 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
1004 return kCFCompareGreaterThan;
1006 /* Non-pbuffer-capable before pbuffer-capable. */
1007 if (!pf1.pbuffer && pf2.pbuffer)
1008 return kCFCompareLessThan;
1009 if (pf1.pbuffer && !pf2.pbuffer)
1010 return kCFCompareGreaterThan;
1012 /* Fewer samples before more samples. */
1013 if (pf1.samples < pf2.samples)
1014 return kCFCompareLessThan;
1015 if (pf1.samples > pf2.samples)
1016 return kCFCompareGreaterThan;
1018 /* Monoscopic before stereoscopic. (This is a guess.) */
1019 if (!pf1.stereo && pf2.stereo)
1020 return kCFCompareLessThan;
1021 if (pf1.stereo && !pf2.stereo)
1022 return kCFCompareGreaterThan;
1024 /* Single buffered before double buffered. */
1025 if (!pf1.double_buffer && pf2.double_buffer)
1026 return kCFCompareLessThan;
1027 if (pf1.double_buffer && !pf2.double_buffer)
1028 return kCFCompareGreaterThan;
1030 /* Possibly-optimized double buffering before backing-store-preserving
1031 double buffering. */
1032 if (!pf1.backing_store && pf2.backing_store)
1033 return kCFCompareLessThan;
1034 if (pf1.backing_store && !pf2.backing_store)
1035 return kCFCompareGreaterThan;
1037 /* Bigger depth buffer before smaller depth buffer. */
1038 if (pf1.depth_bits > pf2.depth_bits)
1039 return kCFCompareLessThan;
1040 if (pf1.depth_bits < pf2.depth_bits)
1041 return kCFCompareGreaterThan;
1043 /* Smaller stencil buffer before bigger stencil buffer. */
1044 if (pf1.stencil_bits < pf2.stencil_bits)
1045 return kCFCompareLessThan;
1046 if (pf1.stencil_bits > pf2.stencil_bits)
1047 return kCFCompareGreaterThan;
1049 /* Smaller alpha bits before larger alpha bits. */
1050 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1051 return kCFCompareLessThan;
1052 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1053 return kCFCompareGreaterThan;
1055 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1056 if (pf1.accum_mode)
1058 if (pf2.accum_mode)
1060 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1061 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1062 return kCFCompareLessThan;
1063 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1064 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1065 return kCFCompareGreaterThan;
1067 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1068 return kCFCompareLessThan;
1069 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1070 return kCFCompareGreaterThan;
1072 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1073 return kCFCompareLessThan;
1074 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1075 return kCFCompareGreaterThan;
1077 else
1078 return kCFCompareGreaterThan;
1080 else if (pf2.accum_mode)
1081 return kCFCompareLessThan;
1083 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1084 if (pf1.aux_buffers < pf2.aux_buffers)
1085 return kCFCompareLessThan;
1086 if (pf1.aux_buffers > pf2.aux_buffers)
1087 return kCFCompareGreaterThan;
1089 /* If we get here, arbitrarily sort based on code. */
1090 if (code1 < code2)
1091 return kCFCompareLessThan;
1092 if (code1 > code2)
1093 return kCFCompareGreaterThan;
1094 return kCFCompareEqualTo;
1098 static BOOL init_pixel_formats(void)
1100 BOOL ret = FALSE;
1101 CGLRendererInfoObj renderer_info;
1102 GLint rendererCount;
1103 CGLError err;
1104 CFMutableSetRef pixel_format_set;
1105 CFMutableArrayRef pixel_format_array;
1106 int i;
1107 CFRange range;
1109 TRACE("()\n");
1111 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1112 if (err)
1114 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1115 return FALSE;
1118 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1119 if (!pixel_format_set)
1121 WARN("CFSetCreateMutable failed\n");
1122 CGLDestroyRendererInfo(renderer_info);
1123 return FALSE;
1126 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1127 if (!pixel_format_array)
1129 WARN("CFArrayCreateMutable failed\n");
1130 CFRelease(pixel_format_set);
1131 CGLDestroyRendererInfo(renderer_info);
1132 return FALSE;
1135 for (i = 0; i < rendererCount; i++)
1137 renderer_properties renderer;
1139 get_renderer_properties(renderer_info, i, &renderer);
1140 if (TRACE_ON(wgl))
1142 TRACE("renderer_properties %d:\n", i);
1143 dump_renderer(&renderer);
1146 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1149 CFRelease(pixel_format_set);
1150 CGLDestroyRendererInfo(renderer_info);
1152 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1153 if (range.length)
1155 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1156 if (pixel_formats)
1158 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1159 for (i = 0; i < range.length; i++)
1161 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1162 UInt64 code;
1164 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1165 pixel_formats[i] = pixel_format_for_code(code);
1166 if (pixel_formats[i].window)
1167 nb_displayable_formats++;
1170 nb_formats = range.length;
1171 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1172 ret = TRUE;
1174 else
1175 WARN("failed to allocate pixel format list\n");
1177 else
1178 WARN("got no pixel formats\n");
1180 CFRelease(pixel_format_array);
1181 return ret;
1185 static inline BOOL is_valid_pixel_format(int format)
1187 return format > 0 && format <= nb_formats;
1191 static inline BOOL is_displayable_pixel_format(int format)
1193 return format > 0 && format <= nb_displayable_formats;
1197 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1199 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1200 * format in case of probing the number of pixel formats.
1202 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1204 TRACE("Returning format %d\n", format);
1205 return &pixel_formats[format - 1];
1207 return NULL;
1211 static BOOL init_gl_info(void)
1213 static const char legacy_extensions[] = " WGL_EXT_extensions_string";
1214 static const char legacy_ext_swap_control[] = " WGL_EXT_swap_control";
1216 CGDirectDisplayID display = CGMainDisplayID();
1217 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1218 CGLPixelFormatAttribute attribs[] = {
1219 kCGLPFADisplayMask, displayMask,
1222 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1223 CGLPixelFormatAttribute core_attribs[] =
1225 kCGLPFADisplayMask, displayMask,
1226 kCGLPFAAccelerated,
1227 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
1230 #endif
1231 CGLPixelFormatObj pix;
1232 GLint virtualScreens;
1233 CGLError err;
1234 CGLContextObj context;
1235 CGLContextObj old_context = CGLGetCurrentContext();
1236 const char *str;
1237 size_t length;
1239 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1240 if (err != kCGLNoError || !pix)
1242 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1243 return FALSE;
1246 err = CGLCreateContext(pix, NULL, &context);
1247 CGLReleasePixelFormat(pix);
1248 if (err != kCGLNoError || !context)
1250 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1251 return FALSE;
1254 err = CGLSetCurrentContext(context);
1255 if (err != kCGLNoError)
1257 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1258 CGLReleaseContext(context);
1259 return FALSE;
1262 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1263 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1264 strcpy(gl_info.glVersion, str);
1265 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1266 length = strlen(str) + sizeof(legacy_extensions);
1267 if (allow_vsync)
1268 length += strlen(legacy_ext_swap_control);
1269 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, length);
1270 strcpy(gl_info.glExtensions, str);
1271 strcat(gl_info.glExtensions, legacy_extensions);
1272 if (allow_vsync)
1273 strcat(gl_info.glExtensions, legacy_ext_swap_control);
1275 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1277 TRACE("GL version : %s\n", gl_info.glVersion);
1278 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1279 sscanf(gl_info.glVersion, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1281 CGLSetCurrentContext(old_context);
1282 CGLReleaseContext(context);
1284 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1285 err = CGLChoosePixelFormat(core_attribs, &pix, &virtualScreens);
1286 if (err != kCGLNoError || !pix)
1288 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1289 err, CGLErrorString(err));
1290 return TRUE;
1293 err = CGLCreateContext(pix, NULL, &context);
1294 CGLReleasePixelFormat(pix);
1295 if (err != kCGLNoError || !context)
1297 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1298 err, CGLErrorString(err));
1299 return TRUE;
1302 err = CGLSetCurrentContext(context);
1303 if (err != kCGLNoError)
1305 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1306 err, CGLErrorString(err));
1307 CGLReleaseContext(context);
1308 return TRUE;
1311 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1312 TRACE("Core context GL version: %s\n", str);
1313 sscanf(str, "%u.%u", &gl_info.max_major, &gl_info.max_minor);
1314 CGLSetCurrentContext(old_context);
1315 CGLReleaseContext(context);
1316 #endif
1318 return TRUE;
1322 static int get_dc_pixel_format(HDC hdc)
1324 int format;
1325 HWND hwnd;
1327 if ((hwnd = WindowFromDC(hdc)))
1329 struct macdrv_win_data *data;
1331 if (!(data = get_win_data(hwnd)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1334 return 0;
1337 format = data->pixel_format;
1338 release_win_data(data);
1340 else
1342 struct wgl_pbuffer *pbuffer;
1344 EnterCriticalSection(&dc_pbuffers_section);
1345 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
1346 if (pbuffer)
1347 format = pbuffer->format;
1348 else
1350 WARN("no window or pbuffer for DC %p\n", hdc);
1351 format = 0;
1353 LeaveCriticalSection(&dc_pbuffers_section);
1356 return format;
1360 /**********************************************************************
1361 * create_context
1363 static BOOL create_context(struct wgl_context *context, CGLContextObj share, unsigned int major)
1365 const pixel_format *pf;
1366 CGLPixelFormatAttribute attribs[64];
1367 int n = 0;
1368 CGLPixelFormatObj pix;
1369 GLint virtualScreens;
1370 CGLError err;
1371 BOOL core = major >= 3;
1373 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1374 if (core)
1376 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1377 return FALSE;
1379 #endif
1381 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
1382 if (!pf)
1384 ERR("Invalid pixel format %d, expect problems!\n", context->format);
1385 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1386 return FALSE;
1389 attribs[n++] = kCGLPFAMinimumPolicy;
1390 attribs[n++] = kCGLPFAClosestPolicy;
1392 if (pf->accelerated)
1394 attribs[n++] = kCGLPFAAccelerated;
1395 attribs[n++] = kCGLPFANoRecovery;
1397 else
1399 attribs[n++] = kCGLPFARendererID;
1400 attribs[n++] = kCGLRendererGenericFloatID;
1403 if (pf->double_buffer)
1404 attribs[n++] = kCGLPFADoubleBuffer;
1406 if (!core)
1408 attribs[n++] = kCGLPFAAuxBuffers;
1409 attribs[n++] = pf->aux_buffers;
1412 attribs[n++] = kCGLPFAColorSize;
1413 attribs[n++] = color_modes[pf->color_mode].color_bits;
1414 attribs[n++] = kCGLPFAAlphaSize;
1415 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
1416 if (color_modes[pf->color_mode].is_float)
1417 attribs[n++] = kCGLPFAColorFloat;
1419 attribs[n++] = kCGLPFADepthSize;
1420 attribs[n++] = pf->depth_bits;
1422 attribs[n++] = kCGLPFAStencilSize;
1423 attribs[n++] = pf->stencil_bits;
1425 if (pf->stereo)
1426 attribs[n++] = kCGLPFAStereo;
1428 if (pf->accum_mode && !core)
1430 attribs[n++] = kCGLPFAAccumSize;
1431 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
1434 if (pf->pbuffer && !core)
1435 attribs[n++] = kCGLPFAPBuffer;
1437 if (pf->sample_buffers && pf->samples)
1439 attribs[n++] = kCGLPFASampleBuffers;
1440 attribs[n++] = pf->sample_buffers;
1441 attribs[n++] = kCGLPFASamples;
1442 attribs[n++] = pf->samples;
1445 if (pf->backing_store)
1446 attribs[n++] = kCGLPFABackingStore;
1448 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1449 if (core)
1451 attribs[n++] = kCGLPFAOpenGLProfile;
1452 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1453 if (major == 3)
1454 attribs[n++] = (int)kCGLOGLPVersion_GL3_Core;
1455 else
1456 attribs[n++] = (int)kCGLOGLPVersion_GL4_Core;
1457 #else
1458 attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
1459 #endif
1461 #endif
1463 attribs[n] = 0;
1465 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1466 if (err != kCGLNoError || !pix)
1468 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1469 SetLastError(ERROR_INVALID_OPERATION);
1470 return FALSE;
1473 err = CGLCreateContext(pix, share, &context->cglcontext);
1474 CGLReleasePixelFormat(pix);
1475 if (err != kCGLNoError || !context->cglcontext)
1477 context->cglcontext = NULL;
1478 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1479 SetLastError(ERROR_INVALID_OPERATION);
1480 return FALSE;
1483 context->context = macdrv_create_opengl_context(context->cglcontext);
1484 CGLReleaseContext(context->cglcontext);
1485 if (!context->context)
1487 WARN("macdrv_create_opengl_context() failed\n");
1488 SetLastError(ERROR_INVALID_OPERATION);
1489 return FALSE;
1491 context->major = major;
1493 if (allow_vsync)
1494 InterlockedExchange(&context->update_swap_interval, TRUE);
1496 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
1498 return TRUE;
1502 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1504 BOOL ret = TRUE;
1505 *rect = data->client_rect;
1507 if (data->cocoa_window)
1509 if (window)
1510 *window = data->cocoa_window;
1511 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1513 else
1515 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1516 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1517 struct macdrv_win_data *top_data = get_win_data(top);
1519 if (top_data && top_data->cocoa_window)
1521 if (window)
1522 *window = top_data->cocoa_window;
1523 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1524 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1526 else
1527 ret = FALSE;
1529 release_win_data(top_data);
1532 return ret;
1536 /***********************************************************************
1537 * set_win_format
1539 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1541 TRACE("hwnd %p format %d\n", data->hwnd, format);
1543 if (!data->gl_view)
1545 macdrv_window cocoa_window;
1547 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1549 ERR("no top-level parent with Cocoa window in this process\n");
1550 return FALSE;
1553 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1554 if (!data->gl_view)
1556 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1557 return FALSE;
1560 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1561 wine_dbgstr_rect(&data->gl_rect));
1564 data->pixel_format = format;
1566 return TRUE;
1570 /**********************************************************************
1571 * set_pixel_format
1573 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1575 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1577 struct macdrv_win_data *data;
1578 const pixel_format *pf;
1579 HWND hwnd = WindowFromDC(hdc);
1580 BOOL ret = FALSE;
1582 TRACE("hdc %p format %d\n", hdc, fmt);
1584 if (!hwnd || hwnd == GetDesktopWindow())
1586 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1587 return FALSE;
1590 if (!(data = get_win_data(hwnd)))
1592 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1593 return FALSE;
1596 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1598 ret = (data->pixel_format == fmt);
1599 goto done;
1602 /* Check if fmt is in our list of supported formats to see if it is supported. */
1603 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1604 if (!pf)
1606 ERR("Invalid pixel format: %d\n", fmt);
1607 goto done;
1610 if (!pf->window)
1612 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1613 goto done;
1616 if (!set_win_format(data, fmt))
1618 WARN("Couldn't set format of the window, returning failure\n");
1619 goto done;
1622 TRACE("pixel format:\n");
1623 TRACE(" window: %u\n", (unsigned int)pf->window);
1624 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1625 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1626 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1627 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1628 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1629 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1630 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1631 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1632 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1633 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1634 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1635 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1636 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1637 ret = TRUE;
1639 done:
1640 release_win_data(data);
1641 if (ret) __wine_set_pixel_format(hwnd, fmt);
1642 return ret;
1646 /**********************************************************************
1647 * set_gl_view_parent
1649 void set_gl_view_parent(HWND hwnd, HWND parent)
1651 struct macdrv_win_data *data;
1653 if (!(data = get_win_data(hwnd))) return;
1655 if (data->gl_view)
1657 macdrv_window cocoa_window;
1659 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1661 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1663 ERR("no top-level parent with Cocoa window in this process\n");
1664 macdrv_dispose_view(data->gl_view);
1665 data->gl_view = NULL;
1666 release_win_data(data);
1667 __wine_set_pixel_format( hwnd, 0 );
1668 return;
1671 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1674 release_win_data(data);
1678 /**********************************************************************
1679 * make_context_current
1681 static void make_context_current(struct wgl_context *context, BOOL read)
1683 macdrv_view view;
1684 struct wgl_pbuffer *pbuffer;
1686 if (read)
1688 view = context->read_view;
1689 pbuffer = context->read_pbuffer;
1691 else
1693 view = context->draw_view;
1694 pbuffer = context->draw_pbuffer;
1697 if (view || !pbuffer)
1698 macdrv_make_context_current(context->context, view);
1699 else
1701 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1702 pbuffer->level, 0);
1703 CGLSetCurrentContext(context->cglcontext);
1708 /**********************************************************************
1709 * set_swap_interval
1711 static BOOL set_swap_interval(struct wgl_context *context, long interval)
1713 CGLError err;
1715 /* In theory, for single-buffered contexts, there's no such thing as a swap
1716 so the swap interval shouldn't matter. But OS X will synchronize flushes
1717 of single-buffered contexts if the interval is set to non-zero. */
1718 if (interval && !pixel_formats[context->format - 1].double_buffer)
1719 interval = 0;
1721 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&interval);
1722 if (err != kCGLNoError)
1723 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err, CGLErrorString(err));
1725 return err == kCGLNoError;
1729 /**********************************************************************
1730 * sync_swap_interval
1732 static void sync_swap_interval(struct wgl_context *context)
1734 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
1736 int interval;
1738 if (context->draw_hwnd)
1740 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
1741 if (data)
1743 interval = data->swap_interval;
1744 release_win_data(data);
1746 else /* window was destroyed? */
1747 interval = 1;
1749 else /* pbuffer */
1750 interval = 0;
1752 set_swap_interval(context, interval);
1757 /**********************************************************************
1758 * macdrv_glCopyColorTable
1760 * Hook into glCopyColorTable as part of the implementation of
1761 * wglMakeContextCurrentARB. If the context has a separate readable,
1762 * temporarily make that current, do glCopyColorTable, and then set it
1763 * back to the drawable. This is modeled after what Mesa GLX's Apple
1764 * implementation does.
1766 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1767 GLsizei width)
1769 struct wgl_context *context = NtCurrentTeb()->glContext;
1771 if (context->read_view || context->read_pbuffer)
1772 make_context_current(context, TRUE);
1774 pglCopyColorTable(target, internalformat, x, y, width);
1776 if (context->read_view || context->read_pbuffer)
1777 make_context_current(context, FALSE);
1781 /**********************************************************************
1782 * macdrv_glCopyPixels
1784 * Hook into glCopyPixels as part of the implementation of
1785 * wglMakeContextCurrentARB. If the context has a separate readable,
1786 * temporarily make that current, do glCopyPixels, and then set it back
1787 * to the drawable. This is modeled after what Mesa GLX's Apple
1788 * implementation does.
1790 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1792 struct wgl_context *context = NtCurrentTeb()->glContext;
1794 if (context->read_view || context->read_pbuffer)
1795 make_context_current(context, TRUE);
1797 pglCopyPixels(x, y, width, height, type);
1799 if (context->read_view || context->read_pbuffer)
1800 make_context_current(context, FALSE);
1804 /**********************************************************************
1805 * macdrv_glFinish
1807 static void macdrv_glFinish(void)
1809 struct wgl_context *context = NtCurrentTeb()->glContext;
1811 sync_swap_interval(context);
1812 pglFinish();
1816 /**********************************************************************
1817 * macdrv_glFlush
1819 static void macdrv_glFlush(void)
1821 struct wgl_context *context = NtCurrentTeb()->glContext;
1823 sync_swap_interval(context);
1825 if (skip_single_buffer_flushes)
1827 const pixel_format *pf = &pixel_formats[context->format - 1];
1828 DWORD now = GetTickCount();
1830 TRACE("double buffer %d last flush time %d now %d\n", (int)pf->double_buffer,
1831 context->last_flush_time, now);
1832 if (pglFlushRenderAPPLE && !pf->double_buffer && (now - context->last_flush_time) < 17)
1834 TRACE("calling glFlushRenderAPPLE()\n");
1835 pglFlushRenderAPPLE();
1836 return;
1838 else
1840 TRACE("calling glFlush()\n");
1841 context->last_flush_time = now;
1845 pglFlush();
1849 /**********************************************************************
1850 * macdrv_glGetString
1852 * Hook into glGetString in order to return some legacy WGL extensions
1853 * that couldn't be advertised via the standard
1854 * WGL_ARB_extensions_string mechanism. Some programs, especially
1855 * older ones, expect to find certain older extensions, such as
1856 * WGL_EXT_extensions_string itself, in the standard GL extensions
1857 * string, and won't query any other WGL extensions unless they find
1858 * that particular extension there.
1860 static const GLubyte *macdrv_glGetString(GLenum name)
1862 if (name == GL_EXTENSIONS && gl_info.glExtensions)
1863 return (const GLubyte *)gl_info.glExtensions;
1864 else
1865 return pglGetString(name);
1869 /**********************************************************************
1870 * macdrv_glReadPixels
1872 * Hook into glReadPixels as part of the implementation of
1873 * wglMakeContextCurrentARB. If the context has a separate readable,
1874 * temporarily make that current, do glReadPixels, and then set it back
1875 * to the drawable. This is modeled after what Mesa GLX's Apple
1876 * implementation does.
1878 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1879 GLenum format, GLenum type, void *pixels)
1881 struct wgl_context *context = NtCurrentTeb()->glContext;
1883 if (context->read_view || context->read_pbuffer)
1884 make_context_current(context, TRUE);
1886 pglReadPixels(x, y, width, height, format, type, pixels);
1888 if (context->read_view || context->read_pbuffer)
1889 make_context_current(context, FALSE);
1893 /**********************************************************************
1894 * macdrv_glViewport
1896 * Hook into glViewport as an opportunity to update the OpenGL context
1897 * if necessary. This is modeled after what Mesa GLX's Apple
1898 * implementation does.
1900 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1902 struct wgl_context *context = NtCurrentTeb()->glContext;
1904 macdrv_update_opengl_context(context->context);
1905 pglViewport(x, y, width, height);
1909 /***********************************************************************
1910 * macdrv_wglBindTexImageARB
1912 * WGL_ARB_render_texture: wglBindTexImageARB
1914 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1916 struct wgl_context *context = NtCurrentTeb()->glContext;
1917 GLenum source;
1918 CGLError err;
1920 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1922 if (pbuffer->no_texture)
1924 SetLastError(ERROR_INVALID_OPERATION);
1925 return GL_FALSE;
1928 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1929 opengl_funcs.gl.p_glFlush();
1931 switch (iBuffer)
1933 case WGL_FRONT_LEFT_ARB:
1934 if (pixel_formats[pbuffer->format - 1].stereo)
1935 source = GL_FRONT_LEFT;
1936 else
1937 source = GL_FRONT;
1938 break;
1939 case WGL_FRONT_RIGHT_ARB:
1940 source = GL_FRONT_RIGHT;
1941 break;
1942 case WGL_BACK_LEFT_ARB:
1943 if (pixel_formats[pbuffer->format - 1].stereo)
1944 source = GL_BACK_LEFT;
1945 else
1946 source = GL_BACK;
1947 break;
1948 case WGL_BACK_RIGHT_ARB:
1949 source = GL_BACK_RIGHT;
1950 break;
1951 case WGL_AUX0_ARB: source = GL_AUX0; break;
1952 case WGL_AUX1_ARB: source = GL_AUX1; break;
1953 case WGL_AUX2_ARB: source = GL_AUX2; break;
1954 case WGL_AUX3_ARB: source = GL_AUX3; break;
1956 case WGL_AUX4_ARB:
1957 case WGL_AUX5_ARB:
1958 case WGL_AUX6_ARB:
1959 case WGL_AUX7_ARB:
1960 case WGL_AUX8_ARB:
1961 case WGL_AUX9_ARB:
1962 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1963 SetLastError(ERROR_INVALID_DATA);
1964 return GL_FALSE;
1966 default:
1967 WARN("unknown source buffer 0x%x\n", iBuffer);
1968 SetLastError(ERROR_INVALID_DATA);
1969 return GL_FALSE;
1972 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1973 if (err != kCGLNoError)
1975 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1976 SetLastError(ERROR_INVALID_OPERATION);
1977 return GL_FALSE;
1980 return GL_TRUE;
1984 /***********************************************************************
1985 * macdrv_wglChoosePixelFormatARB
1987 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1989 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1990 const FLOAT *pfAttribFList, UINT nMaxFormats,
1991 int *piFormats, UINT *nNumFormats)
1993 pixel_format pf, valid;
1994 const int *iptr;
1995 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1996 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1997 int float_color;
1998 BOOL srgb;
1999 int i, found = 0;
2001 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2002 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2003 if (pfAttribFList)
2004 FIXME("unused pfAttribFList\n");
2006 memset(&pf, 0, sizeof(pf));
2007 memset(&valid, 0, sizeof(valid));
2008 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
2009 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
2010 float_color = -1;
2011 srgb = FALSE;
2013 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
2015 int attr = iptr[0];
2016 int value = iptr[1];
2018 TRACE("%s\n", debugstr_attrib(attr, value));
2020 switch (attr)
2022 case WGL_DRAW_TO_WINDOW_ARB:
2023 if (valid.window && (!pf.window != !value)) goto cant_match;
2024 pf.window = (value != 0);
2025 valid.window = 1;
2026 break;
2028 case WGL_DRAW_TO_BITMAP_ARB:
2029 goto cant_match;
2031 case WGL_ACCELERATION_ARB:
2032 if (value == WGL_FULL_ACCELERATION_ARB)
2033 value = 1;
2034 else if (value == WGL_NO_ACCELERATION_ARB)
2035 value = 0;
2036 else
2037 goto cant_match;
2038 if (valid.accelerated && pf.accelerated != value) goto cant_match;
2039 pf.accelerated = value;
2040 valid.accelerated = 1;
2041 break;
2043 case WGL_NEED_PALETTE_ARB:
2044 case WGL_NEED_SYSTEM_PALETTE_ARB:
2045 case WGL_SWAP_LAYER_BUFFERS_ARB:
2046 if (value) goto cant_match;
2047 break;
2049 case WGL_SWAP_METHOD_ARB:
2050 if (value == WGL_SWAP_COPY_ARB)
2051 value = 1;
2052 else if (value == WGL_SWAP_UNDEFINED_ARB)
2053 value = 0;
2054 else
2055 goto cant_match;
2056 if (valid.backing_store && pf.backing_store != value) goto cant_match;
2057 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
2058 pf.backing_store = value;
2059 valid.backing_store = 1;
2060 break;
2062 case WGL_NUMBER_OVERLAYS_ARB:
2063 case WGL_NUMBER_UNDERLAYS_ARB:
2064 if (value) goto cant_match;
2065 break;
2067 case WGL_SHARE_DEPTH_ARB:
2068 case WGL_SHARE_STENCIL_ARB:
2069 case WGL_SHARE_ACCUM_ARB:
2070 /* no effect */
2071 break;
2073 case WGL_SUPPORT_GDI_ARB:
2074 if (value) goto cant_match;
2075 break;
2077 case WGL_SUPPORT_OPENGL_ARB:
2078 if (!value) goto cant_match;
2079 break;
2081 case WGL_DOUBLE_BUFFER_ARB:
2082 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
2083 pf.double_buffer = (value != 0);
2084 valid.double_buffer = 1;
2085 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
2086 break;
2088 case WGL_STEREO_ARB:
2089 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
2090 pf.stereo = (value != 0);
2091 valid.stereo = 1;
2092 break;
2094 case WGL_PIXEL_TYPE_ARB:
2095 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
2096 value = 1;
2097 else if (value == WGL_TYPE_RGBA_ARB)
2098 value = 0;
2099 else
2101 /* Mac contexts don't support rendering to unsigned floating
2102 point formats, even if GL_EXT_packed_float is supported.
2103 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2104 goto cant_match;
2106 if (float_color != -1 && float_color != value) goto cant_match;
2107 if (srgb && value) goto cant_match;
2108 float_color = value;
2109 break;
2111 case WGL_COLOR_BITS_ARB:
2112 if (color_bits < value) color_bits = value;
2113 break;
2115 case WGL_RED_BITS_ARB:
2116 if (srgb && value > 8) goto cant_match;
2117 if (red_bits < value) red_bits = value;
2118 break;
2120 case WGL_GREEN_BITS_ARB:
2121 if (srgb && value > 8) goto cant_match;
2122 if (green_bits < value) green_bits = value;
2123 break;
2125 case WGL_BLUE_BITS_ARB:
2126 if (srgb && value > 8) goto cant_match;
2127 if (blue_bits < value) blue_bits = value;
2128 break;
2130 case WGL_ALPHA_BITS_ARB:
2131 if (alpha_bits < value) alpha_bits = value;
2132 break;
2134 case WGL_ACCUM_BITS_ARB:
2135 if (accum_bits < value) accum_bits = value;
2136 break;
2138 case WGL_ACCUM_RED_BITS_ARB:
2139 if (accum_red_bits < value) accum_red_bits = value;
2140 break;
2142 case WGL_ACCUM_GREEN_BITS_ARB:
2143 if (accum_green_bits < value) accum_green_bits = value;
2144 break;
2146 case WGL_ACCUM_BLUE_BITS_ARB:
2147 if (accum_blue_bits < value) accum_blue_bits = value;
2148 break;
2150 case WGL_ACCUM_ALPHA_BITS_ARB:
2151 if (accum_alpha_bits < value) accum_alpha_bits = value;
2152 break;
2154 case WGL_DEPTH_BITS_ARB:
2155 if (value > 255) goto cant_match;
2156 if (pf.depth_bits < value) pf.depth_bits = value;
2157 break;
2159 case WGL_STENCIL_BITS_ARB:
2160 if (value > 255) goto cant_match;
2161 if (pf.stencil_bits < value) pf.stencil_bits = value;
2162 break;
2164 case WGL_AUX_BUFFERS_ARB:
2165 if (value > 7) goto cant_match;
2166 if (pf.aux_buffers < value) pf.aux_buffers = value;
2167 break;
2169 case WGL_SAMPLE_BUFFERS_ARB:
2170 if (value > 1) goto cant_match;
2171 if (pf.sample_buffers < value) pf.sample_buffers = value;
2172 break;
2174 case WGL_SAMPLES_ARB:
2175 if (value > 31) goto cant_match;
2176 if (pf.samples < value) pf.samples = value;
2177 break;
2179 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2180 /* sRGB is only supported for 8-bit integer color components */
2181 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
2182 goto cant_match;
2183 srgb = TRUE;
2184 break;
2186 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2187 case WGL_RED_SHIFT_ARB:
2188 case WGL_GREEN_SHIFT_ARB:
2189 case WGL_BLUE_SHIFT_ARB:
2190 case WGL_ALPHA_SHIFT_ARB:
2191 case WGL_TRANSPARENT_ARB:
2192 case WGL_TRANSPARENT_RED_VALUE_ARB:
2193 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2194 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2195 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2196 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2197 /* ignored */
2198 break;
2200 case WGL_DRAW_TO_PBUFFER_ARB:
2201 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2202 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2203 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2204 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2205 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
2206 pf.pbuffer = (value != 0);
2207 valid.pbuffer = 1;
2208 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
2209 !alpha_bits)
2210 alpha_bits = 1;
2211 break;
2213 default:
2214 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
2215 return GL_FALSE;
2219 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",
2220 valid.window ? (pf.window ? "1" : "0") : "?",
2221 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
2222 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
2223 color_bits,
2224 float_color == -1 ? "?" : float_color ? "f" : "",
2225 red_bits,
2226 green_bits,
2227 blue_bits,
2228 alpha_bits,
2229 (int)srgb,
2230 accum_bits,
2231 accum_red_bits,
2232 accum_green_bits,
2233 accum_blue_bits,
2234 accum_alpha_bits,
2235 pf.depth_bits,
2236 pf.stencil_bits,
2237 pf.aux_buffers,
2238 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
2239 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
2240 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
2241 pf.sample_buffers,
2242 pf.samples);
2244 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
2246 const struct color_mode *mode;
2248 if (valid.window && pixel_formats[i].window != pf.window) continue;
2249 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
2250 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
2251 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
2252 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
2253 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
2255 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
2256 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
2257 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
2258 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
2259 if (pixel_formats[i].samples < pf.samples) continue;
2261 mode = &color_modes[pixel_formats[i].color_mode];
2262 /* If the mode doesn't have alpha, check requested color bits against
2263 bits per pixel instead of the mode's color bits. On Windows, color
2264 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2265 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2266 expects that to match such a pixel format, we need to accommodate that. */
2267 if (mode->alpha_bits)
2269 if (mode->color_bits < color_bits)
2270 continue;
2272 else
2274 if (mode->bits_per_pixel < color_bits)
2275 continue;
2277 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
2278 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
2279 continue;
2280 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
2281 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
2282 continue;
2284 if (pixel_formats[i].accum_mode)
2286 mode = &color_modes[pixel_formats[i].accum_mode - 1];
2287 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
2288 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
2289 mode->alpha_bits < accum_alpha_bits)
2290 continue;
2292 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
2293 continue;
2295 piFormats[found++] = i + 1;
2296 TRACE("match: pixel format %d %s\n", i + 1, debugstr_pf(&pixel_formats[i]));
2299 cant_match:
2300 *nNumFormats = found;
2302 return TRUE;
2306 /***********************************************************************
2307 * macdrv_wglCreateContextAttribsARB
2309 * WGL_ARB_create_context: wglCreateContextAttribsARB
2311 static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
2312 struct wgl_context *share_context,
2313 const int *attrib_list)
2315 int format;
2316 struct wgl_context *context;
2317 const int *iptr;
2318 int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
2319 BOOL core = FALSE;
2321 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
2323 format = get_dc_pixel_format(hdc);
2325 if (!is_valid_pixel_format(format))
2327 ERR("Invalid pixel format %d, expect problems!\n", format);
2328 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2329 return NULL;
2332 for (iptr = attrib_list; iptr && *iptr; iptr += 2)
2334 int attr = iptr[0];
2335 int value = iptr[1];
2337 TRACE("%s\n", debugstr_attrib(attr, value));
2339 switch (attr)
2341 case WGL_CONTEXT_MAJOR_VERSION_ARB:
2342 major = value;
2343 break;
2345 case WGL_CONTEXT_MINOR_VERSION_ARB:
2346 minor = value;
2347 break;
2349 case WGL_CONTEXT_LAYER_PLANE_ARB:
2350 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2351 break;
2353 case WGL_CONTEXT_FLAGS_ARB:
2354 flags = value;
2355 if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2356 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2357 flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2358 break;
2360 case WGL_CONTEXT_PROFILE_MASK_ARB:
2361 if (value != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
2362 value != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
2364 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
2365 SetLastError(ERROR_INVALID_PROFILE_ARB);
2366 return NULL;
2368 profile = value;
2369 break;
2371 default:
2372 WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
2373 SetLastError(ERROR_INVALID_PARAMETER);
2374 return NULL;
2378 if ((major == 3 && (minor == 2 || minor == 3)) ||
2379 (major == 4 && (minor == 0 || minor == 1)))
2381 if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
2383 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2384 SetLastError(ERROR_INVALID_VERSION_ARB);
2385 return NULL;
2387 if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
2389 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2390 SetLastError(ERROR_INVALID_PROFILE_ARB);
2391 return NULL;
2393 if (major > gl_info.max_major ||
2394 (major == gl_info.max_major && minor > gl_info.max_minor))
2396 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2397 major, minor);
2398 SetLastError(ERROR_INVALID_PROFILE_ARB);
2399 return NULL;
2401 core = TRUE;
2403 else if (major >= 3)
2405 WARN("Profile version %u.%u not supported\n", major, minor);
2406 SetLastError(ERROR_INVALID_VERSION_ARB);
2407 return NULL;
2409 else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
2410 (major == 2 && (minor < 0 || minor > 1)))
2412 WARN("Invalid GL version requested\n");
2413 SetLastError(ERROR_INVALID_VERSION_ARB);
2414 return NULL;
2416 if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
2418 WARN("Forward compatible context requested for GL version < 3\n");
2419 SetLastError(ERROR_INVALID_VERSION_ARB);
2420 return NULL;
2423 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
2425 context->format = format;
2426 if (!create_context(context, share_context ? share_context->cglcontext : NULL, major))
2428 HeapFree(GetProcessHeap(), 0, context);
2429 return NULL;
2432 EnterCriticalSection(&context_section);
2433 list_add_tail(&context_list, &context->entry);
2434 LeaveCriticalSection(&context_section);
2436 return context;
2440 /**********************************************************************
2441 * macdrv_wglCreatePbufferARB
2443 * WGL_ARB_pbuffer: wglCreatePbufferARB
2445 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
2446 const int *piAttribList)
2448 struct wgl_pbuffer* pbuffer;
2449 GLenum target = 0;
2450 GLenum internalFormat = 0;
2451 CGLError err;
2453 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2454 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2456 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat - 1].pbuffer)
2458 WARN("invalid pixel format %d\n", iPixelFormat);
2459 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2460 return NULL;
2463 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
2464 pbuffer->format = iPixelFormat;
2466 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2468 int attr = piAttribList[0];
2469 int value = piAttribList[1];
2471 switch (attr)
2473 case WGL_PBUFFER_LARGEST_ARB:
2474 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
2475 break;
2477 case WGL_TEXTURE_FORMAT_ARB:
2478 switch (value)
2480 case WGL_TEXTURE_RGBA_ARB:
2481 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2482 internalFormat = GL_RGBA;
2483 break;
2484 case WGL_TEXTURE_RGB_ARB:
2485 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2486 internalFormat = GL_RGB;
2487 break;
2488 case WGL_NO_TEXTURE_ARB:
2489 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2490 internalFormat = 0;
2491 break;
2492 default:
2493 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
2494 SetLastError(ERROR_INVALID_DATA);
2495 goto done;
2497 break;
2499 case WGL_TEXTURE_TARGET_ARB:
2500 pbuffer->face = 0;
2501 switch (value)
2503 case WGL_NO_TEXTURE_ARB:
2504 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2505 target = 0;
2506 break;
2507 case WGL_TEXTURE_CUBE_MAP_ARB:
2508 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2509 target = GL_TEXTURE_CUBE_MAP;
2510 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2511 break;
2512 case WGL_TEXTURE_1D_ARB:
2513 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2514 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2515 goto done;
2516 case WGL_TEXTURE_2D_ARB:
2517 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2518 target = GL_TEXTURE_2D;
2519 break;
2520 case WGL_TEXTURE_RECTANGLE_NV:
2521 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2522 target = GL_TEXTURE_RECTANGLE;
2523 break;
2524 default:
2525 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2526 SetLastError(ERROR_INVALID_DATA);
2527 goto done;
2529 break;
2531 case WGL_MIPMAP_TEXTURE_ARB:
2532 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2533 pbuffer->max_level = 0;
2534 if (value)
2536 int size = min(iWidth, iHeight) / 2;
2537 while (size)
2539 pbuffer->max_level++;
2540 size /= 2;
2543 break;
2545 default:
2546 WARN("unknown attribute 0x%x\n", attr);
2547 SetLastError(ERROR_INVALID_DATA);
2548 goto done;
2552 if (!target || !internalFormat)
2554 pbuffer->no_texture = TRUE;
2555 /* no actual way to turn off ability to texture; use most permissive target */
2556 target = GL_TEXTURE_RECTANGLE;
2557 internalFormat = GL_RGB;
2560 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2561 if (err != kCGLNoError)
2563 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2564 pbuffer->pbuffer = NULL;
2565 if (err == kCGLBadAlloc)
2566 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2567 else
2568 SetLastError(ERROR_INVALID_DATA);
2571 done:
2572 if (!pbuffer->pbuffer)
2574 HeapFree(GetProcessHeap(), 0, pbuffer);
2575 return NULL;
2578 TRACE(" -> %p\n", pbuffer);
2579 return pbuffer;
2583 /**********************************************************************
2584 * macdrv_wglDestroyPbufferARB
2586 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2588 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2590 TRACE("pbuffer %p\n", pbuffer);
2591 if (pbuffer && pbuffer->pbuffer)
2592 CGLReleasePBuffer(pbuffer->pbuffer);
2593 HeapFree(GetProcessHeap(), 0, pbuffer);
2594 return GL_TRUE;
2598 /**********************************************************************
2599 * macdrv_wglGetExtensionsStringARB
2601 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2603 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc)
2605 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2606 this can be specific to the CGL renderer like we're supposed to do. */
2607 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2608 return gl_info.wglExtensions;
2612 /**********************************************************************
2613 * macdrv_wglGetExtensionsStringEXT
2615 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2617 static const char *macdrv_wglGetExtensionsStringEXT(void)
2619 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2620 return gl_info.wglExtensions;
2624 /**********************************************************************
2625 * macdrv_wglGetPbufferDCARB
2627 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2629 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2631 HDC hdc;
2632 struct wgl_pbuffer *prev;
2634 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2635 if (!hdc) return 0;
2637 EnterCriticalSection(&dc_pbuffers_section);
2638 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2639 if (prev)
2641 CGLReleasePBuffer(prev->pbuffer);
2642 HeapFree(GetProcessHeap(), 0, prev);
2644 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2645 LeaveCriticalSection(&dc_pbuffers_section);
2647 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2648 return hdc;
2652 /**********************************************************************
2653 * macdrv_wglGetPixelFormatAttribivARB
2655 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2657 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2658 UINT nAttributes, const int *piAttributes, int *piValues)
2660 const pixel_format *pf;
2661 UINT i;
2663 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2664 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2666 if (!nAttributes) return GL_TRUE;
2668 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2670 piValues[0] = nb_formats;
2671 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2672 return GL_TRUE;
2675 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2676 if (!pf)
2678 WARN("invalid pixel format %d\n", iPixelFormat);
2679 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2680 return GL_FALSE;
2683 for (i = 0; i < nAttributes; ++i)
2685 switch (piAttributes[i])
2687 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2688 piValues[i] = nb_formats;
2689 break;
2691 case WGL_DRAW_TO_WINDOW_ARB:
2692 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2693 break;
2695 case WGL_DRAW_TO_BITMAP_ARB:
2696 piValues[i] = GL_FALSE;
2697 break;
2699 case WGL_ACCELERATION_ARB:
2700 if (iLayerPlane) goto invalid_layer;
2701 if (pf->accelerated)
2702 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2703 else
2704 piValues[i] = WGL_NO_ACCELERATION_ARB;
2705 break;
2707 case WGL_NEED_PALETTE_ARB:
2708 case WGL_NEED_SYSTEM_PALETTE_ARB:
2709 case WGL_SWAP_LAYER_BUFFERS_ARB:
2710 piValues[i] = GL_FALSE;
2711 break;
2713 case WGL_SWAP_METHOD_ARB:
2714 if (pf->double_buffer && pf->backing_store)
2715 piValues[i] = WGL_SWAP_COPY_ARB;
2716 else
2717 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2718 break;
2720 case WGL_NUMBER_OVERLAYS_ARB:
2721 case WGL_NUMBER_UNDERLAYS_ARB:
2722 piValues[i] = 0;
2723 break;
2725 case WGL_TRANSPARENT_ARB:
2726 if (iLayerPlane) goto invalid_layer;
2727 piValues[i] = GL_FALSE;
2728 break;
2730 case WGL_TRANSPARENT_RED_VALUE_ARB:
2731 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2732 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2733 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2734 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2735 if (iLayerPlane) goto invalid_layer;
2736 piValues[i] = 0;
2737 break;
2739 case WGL_SHARE_DEPTH_ARB:
2740 case WGL_SHARE_STENCIL_ARB:
2741 case WGL_SHARE_ACCUM_ARB:
2742 if (iLayerPlane) goto invalid_layer;
2743 piValues[i] = GL_TRUE;
2744 break;
2746 case WGL_SUPPORT_GDI_ARB:
2747 if (iLayerPlane) goto invalid_layer;
2748 piValues[i] = GL_FALSE;
2749 break;
2751 case WGL_SUPPORT_OPENGL_ARB:
2752 if (iLayerPlane) goto invalid_layer;
2753 piValues[i] = GL_TRUE;
2754 break;
2756 case WGL_DOUBLE_BUFFER_ARB:
2757 if (iLayerPlane) goto invalid_layer;
2758 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2759 break;
2761 case WGL_STEREO_ARB:
2762 if (iLayerPlane) goto invalid_layer;
2763 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2764 break;
2766 case WGL_PIXEL_TYPE_ARB:
2767 if (iLayerPlane) goto invalid_layer;
2768 if (color_modes[pf->color_mode].is_float)
2769 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2770 else
2771 piValues[i] = WGL_TYPE_RGBA_ARB;
2772 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2773 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2774 However, Mac contexts don't support rendering to unsigned floating-point
2775 formats, even when GL_EXT_packed_float is supported. */
2776 break;
2778 case WGL_COLOR_BITS_ARB:
2779 if (iLayerPlane) goto invalid_layer;
2780 /* If the mode doesn't have alpha, return bits per pixel instead
2781 of color bits. On Windows, color bits sometimes exceeds r+g+b
2782 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2783 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2784 pixel format, we need to accommodate that. */
2785 if (color_modes[pf->color_mode].alpha_bits)
2786 piValues[i] = color_modes[pf->color_mode].color_bits;
2787 else
2788 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2789 break;
2791 case WGL_RED_BITS_ARB:
2792 if (iLayerPlane) goto invalid_layer;
2793 piValues[i] = color_modes[pf->color_mode].red_bits;
2794 break;
2796 case WGL_RED_SHIFT_ARB:
2797 if (iLayerPlane) goto invalid_layer;
2798 piValues[i] = color_modes[pf->color_mode].red_shift;
2799 break;
2801 case WGL_GREEN_BITS_ARB:
2802 if (iLayerPlane) goto invalid_layer;
2803 piValues[i] = color_modes[pf->color_mode].green_bits;
2804 break;
2806 case WGL_GREEN_SHIFT_ARB:
2807 if (iLayerPlane) goto invalid_layer;
2808 piValues[i] = color_modes[pf->color_mode].green_shift;
2809 break;
2811 case WGL_BLUE_BITS_ARB:
2812 if (iLayerPlane) goto invalid_layer;
2813 piValues[i] = color_modes[pf->color_mode].blue_bits;
2814 break;
2816 case WGL_BLUE_SHIFT_ARB:
2817 if (iLayerPlane) goto invalid_layer;
2818 piValues[i] = color_modes[pf->color_mode].blue_shift;
2819 break;
2821 case WGL_ALPHA_BITS_ARB:
2822 if (iLayerPlane) goto invalid_layer;
2823 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2824 break;
2826 case WGL_ALPHA_SHIFT_ARB:
2827 if (iLayerPlane) goto invalid_layer;
2828 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2829 break;
2831 case WGL_ACCUM_BITS_ARB:
2832 if (iLayerPlane) goto invalid_layer;
2833 if (pf->accum_mode)
2834 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2835 else
2836 piValues[i] = 0;
2837 break;
2839 case WGL_ACCUM_RED_BITS_ARB:
2840 if (iLayerPlane) goto invalid_layer;
2841 if (pf->accum_mode)
2842 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2843 else
2844 piValues[i] = 0;
2845 break;
2847 case WGL_ACCUM_GREEN_BITS_ARB:
2848 if (iLayerPlane) goto invalid_layer;
2849 if (pf->accum_mode)
2850 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2851 else
2852 piValues[i] = 0;
2853 break;
2855 case WGL_ACCUM_BLUE_BITS_ARB:
2856 if (iLayerPlane) goto invalid_layer;
2857 if (pf->accum_mode)
2858 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2859 else
2860 piValues[i] = 0;
2861 break;
2863 case WGL_ACCUM_ALPHA_BITS_ARB:
2864 if (iLayerPlane) goto invalid_layer;
2865 if (pf->accum_mode)
2866 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2867 else
2868 piValues[i] = 0;
2869 break;
2871 case WGL_DEPTH_BITS_ARB:
2872 if (iLayerPlane) goto invalid_layer;
2873 piValues[i] = pf->depth_bits;
2874 break;
2876 case WGL_STENCIL_BITS_ARB:
2877 if (iLayerPlane) goto invalid_layer;
2878 piValues[i] = pf->stencil_bits;
2879 break;
2881 case WGL_AUX_BUFFERS_ARB:
2882 if (iLayerPlane) goto invalid_layer;
2883 piValues[i] = pf->aux_buffers;
2884 break;
2886 case WGL_SAMPLE_BUFFERS_ARB:
2887 if (iLayerPlane) goto invalid_layer;
2888 piValues[i] = pf->sample_buffers;
2889 break;
2891 case WGL_SAMPLES_ARB:
2892 if (iLayerPlane) goto invalid_layer;
2893 piValues[i] = pf->samples;
2894 break;
2896 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2897 if (iLayerPlane) goto invalid_layer;
2898 /* sRGB is only supported for 8-bit integer color components */
2899 if (color_modes[pf->color_mode].red_bits == 8 &&
2900 color_modes[pf->color_mode].green_bits == 8 &&
2901 color_modes[pf->color_mode].blue_bits == 8 &&
2902 !color_modes[pf->color_mode].is_float)
2903 piValues[i] = GL_TRUE;
2904 else
2905 piValues[i] = GL_FALSE;
2906 break;
2908 case WGL_DRAW_TO_PBUFFER_ARB:
2909 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2910 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2911 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2912 break;
2914 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2915 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2916 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2917 break;
2919 case WGL_MAX_PBUFFER_WIDTH_ARB:
2920 piValues[i] = gl_info.max_viewport_dims[0];
2921 break;
2923 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2924 piValues[i] = gl_info.max_viewport_dims[1];
2925 break;
2927 case WGL_MAX_PBUFFER_PIXELS_ARB:
2928 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2929 break;
2931 default:
2932 WARN("invalid attribute %x\n", piAttributes[i]);
2933 return GL_FALSE;
2936 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2939 return GL_TRUE;
2941 invalid_layer:
2942 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2943 return GL_FALSE;
2947 /**********************************************************************
2948 * macdrv_wglGetPixelFormatAttribfvARB
2950 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2952 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2953 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2955 int *attr;
2956 int ret;
2958 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2959 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2961 /* Allocate a temporary array to store integer values */
2962 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2963 if (!attr)
2965 ERR("couldn't allocate %d array\n", nAttributes);
2966 return GL_FALSE;
2969 /* Piggy-back on wglGetPixelFormatAttribivARB */
2970 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2971 if (ret)
2973 UINT i;
2975 /* Convert integer values to float. Should also check for attributes
2976 that can give decimal values here */
2977 for (i = 0; i < nAttributes; i++)
2978 pfValues[i] = attr[i];
2981 HeapFree(GetProcessHeap(), 0, attr);
2982 return ret;
2986 /**********************************************************************
2987 * macdrv_wglGetSwapIntervalEXT
2989 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2991 static int macdrv_wglGetSwapIntervalEXT(void)
2993 struct wgl_context *context = NtCurrentTeb()->glContext;
2994 struct macdrv_win_data *data;
2995 long value;
2996 CGLError err;
2998 TRACE("\n");
3000 if ((data = get_win_data(context->draw_hwnd)))
3002 value = data->swap_interval;
3003 release_win_data(data);
3005 if (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE))
3006 set_swap_interval(context, value);
3008 else
3010 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
3011 if (err != kCGLNoError)
3013 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3014 err, CGLErrorString(err));
3015 value = 1;
3019 return value;
3023 /***********************************************************************
3024 * macdrv_wglMakeContextCurrentARB
3026 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3028 * This is not supported directly by OpenGL on the Mac. We emulate it
3029 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3030 * temporarily swap the drawable. This follows the technique used in
3031 * the implementation of Mesa GLX for Apple.
3033 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
3035 struct macdrv_win_data *data;
3036 HWND hwnd;
3038 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
3039 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
3041 if (!context)
3043 macdrv_make_context_current(NULL, NULL);
3044 NtCurrentTeb()->glContext = NULL;
3045 return TRUE;
3048 if ((hwnd = WindowFromDC(draw_hdc)))
3050 if (!(data = get_win_data(hwnd)))
3052 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
3053 return FALSE;
3056 if (!data->pixel_format)
3058 WARN("no pixel format set\n");
3059 release_win_data(data);
3060 SetLastError(ERROR_INVALID_HANDLE);
3061 return FALSE;
3063 if (context->format != data->pixel_format)
3065 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
3066 release_win_data(data);
3067 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3068 return FALSE;
3071 if (allow_vsync && (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || hwnd != context->draw_hwnd))
3072 set_swap_interval(context, data->swap_interval);
3074 context->draw_hwnd = hwnd;
3075 context->draw_view = data->gl_view;
3076 context->draw_pbuffer = NULL;
3077 release_win_data(data);
3079 else
3081 struct wgl_pbuffer *pbuffer;
3083 EnterCriticalSection(&dc_pbuffers_section);
3084 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
3085 if (pbuffer)
3087 if (context->format != pbuffer->format)
3089 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
3090 LeaveCriticalSection(&dc_pbuffers_section);
3091 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3092 return FALSE;
3095 if (allow_vsync &&
3096 (InterlockedCompareExchange(&context->update_swap_interval, FALSE, TRUE) || pbuffer != context->draw_pbuffer))
3097 set_swap_interval(context, 0);
3099 else
3101 WARN("no window or pbuffer for DC\n");
3102 LeaveCriticalSection(&dc_pbuffers_section);
3103 SetLastError(ERROR_INVALID_HANDLE);
3104 return FALSE;
3107 context->draw_hwnd = NULL;
3108 context->draw_view = NULL;
3109 context->draw_pbuffer = pbuffer;
3110 LeaveCriticalSection(&dc_pbuffers_section);
3113 context->read_view = NULL;
3114 context->read_pbuffer = NULL;
3115 if (read_hdc && read_hdc != draw_hdc)
3117 if ((hwnd = WindowFromDC(read_hdc)))
3119 if ((data = get_win_data(hwnd)))
3121 if (data->gl_view != context->draw_view)
3122 context->read_view = data->gl_view;
3123 release_win_data(data);
3126 else
3128 EnterCriticalSection(&dc_pbuffers_section);
3129 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
3130 LeaveCriticalSection(&dc_pbuffers_section);
3134 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3135 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
3137 make_context_current(context, FALSE);
3138 context->has_been_current = TRUE;
3139 NtCurrentTeb()->glContext = context;
3141 return TRUE;
3145 /**********************************************************************
3146 * macdrv_wglQueryPbufferARB
3148 * WGL_ARB_pbuffer: wglQueryPbufferARB
3150 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
3152 CGLError err;
3153 GLsizei width;
3154 GLsizei height;
3155 GLenum target;
3156 GLenum internalFormat;
3157 GLint mipmap;
3159 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
3161 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
3162 if (err != kCGLNoError)
3164 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
3165 SetLastError(ERROR_INVALID_HANDLE);
3166 return GL_FALSE;
3169 switch (iAttribute)
3171 case WGL_PBUFFER_WIDTH_ARB:
3172 *piValue = width;
3173 break;
3174 case WGL_PBUFFER_HEIGHT_ARB:
3175 *piValue = height;
3176 break;
3177 case WGL_PBUFFER_LOST_ARB:
3178 /* Mac PBuffers can't be lost */
3179 *piValue = GL_FALSE;
3180 break;
3181 case WGL_TEXTURE_FORMAT_ARB:
3182 if (pbuffer->no_texture)
3183 *piValue = WGL_NO_TEXTURE_ARB;
3184 else switch (internalFormat)
3186 case GL_RGBA:
3187 *piValue = WGL_TEXTURE_RGBA_ARB;
3188 break;
3189 case GL_RGB:
3190 default:
3191 *piValue = WGL_TEXTURE_RGB_ARB;
3192 break;
3194 break;
3195 case WGL_TEXTURE_TARGET_ARB:
3196 if (pbuffer->no_texture)
3197 *piValue = WGL_NO_TEXTURE_ARB;
3198 else switch (target)
3200 case GL_TEXTURE_CUBE_MAP:
3201 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
3202 break;
3203 case GL_TEXTURE_2D:
3204 *piValue = WGL_TEXTURE_2D_ARB;
3205 break;
3206 case GL_TEXTURE_RECTANGLE:
3207 default:
3208 *piValue = WGL_TEXTURE_RECTANGLE_NV;
3209 break;
3211 break;
3212 case WGL_MIPMAP_TEXTURE_ARB:
3213 *piValue = (pbuffer->max_level > 0);
3214 break;
3215 case WGL_MIPMAP_LEVEL_ARB:
3216 *piValue = pbuffer->level;
3217 break;
3218 case WGL_CUBE_MAP_FACE_ARB:
3219 switch (pbuffer->face)
3221 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3222 default:
3223 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
3224 break;
3225 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3226 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
3227 break;
3228 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3229 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
3230 break;
3231 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3232 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
3233 break;
3234 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3235 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
3236 break;
3237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3238 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
3239 break;
3241 break;
3242 default:
3243 WARN("invalid attribute 0x%x\n", iAttribute);
3244 SetLastError(ERROR_INVALID_DATA);
3245 return GL_FALSE;
3248 return GL_TRUE;
3252 /**********************************************************************
3253 * macdrv_wglReleasePbufferDCARB
3255 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3257 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
3259 struct wgl_pbuffer *prev;
3261 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
3263 EnterCriticalSection(&dc_pbuffers_section);
3265 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3266 if (prev)
3268 if (prev != pbuffer)
3269 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
3270 CGLReleasePBuffer(prev->pbuffer);
3271 HeapFree(GetProcessHeap(), 0, prev);
3272 CFDictionaryRemoveValue(dc_pbuffers, hdc);
3274 else hdc = 0;
3276 LeaveCriticalSection(&dc_pbuffers_section);
3278 return hdc && DeleteDC(hdc);
3282 /**********************************************************************
3283 * macdrv_wglReleaseTexImageARB
3285 * WGL_ARB_render_texture: wglReleaseTexImageARB
3287 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
3289 struct wgl_context *context = NtCurrentTeb()->glContext;
3290 CGLError err;
3292 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
3294 if (pbuffer->no_texture)
3296 SetLastError(ERROR_INVALID_OPERATION);
3297 return GL_FALSE;
3300 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
3301 if (err != kCGLNoError)
3303 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
3304 SetLastError(ERROR_INVALID_OPERATION);
3305 return GL_FALSE;
3308 return GL_TRUE;
3312 /**********************************************************************
3313 * macdrv_wglSetPbufferAttribARB
3315 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3317 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
3319 struct wgl_context *context = NtCurrentTeb()->glContext;
3321 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
3323 for ( ; piAttribList && *piAttribList; piAttribList += 2)
3325 int attr = piAttribList[0];
3326 int value = piAttribList[1];
3327 switch (attr)
3329 case WGL_MIPMAP_LEVEL_ARB:
3330 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
3331 pbuffer->level = value;
3332 break;
3333 case WGL_CUBE_MAP_FACE_ARB:
3334 switch (value)
3336 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3337 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3338 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3339 break;
3340 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3341 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3342 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
3343 break;
3344 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3345 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3346 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
3347 break;
3348 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3349 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3350 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
3351 break;
3352 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3353 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3354 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
3355 break;
3356 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3357 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3358 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
3359 break;
3360 default:
3361 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
3362 SetLastError(ERROR_INVALID_DATA);
3363 return GL_FALSE;
3365 break;
3366 default:
3367 WARN("invalide attribute 0x%x\n", attr);
3368 SetLastError(ERROR_INVALID_DATA);
3369 return GL_FALSE;
3373 if (context && context->draw_pbuffer == pbuffer)
3374 make_context_current(context, FALSE);
3376 return GL_TRUE;
3380 /**********************************************************************
3381 * macdrv_wglSetPixelFormatWINE
3383 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3385 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
3387 return set_pixel_format(hdc, fmt, TRUE);
3391 /**********************************************************************
3392 * macdrv_wglSwapIntervalEXT
3394 * WGL_EXT_swap_control: wglSwapIntervalEXT
3396 static BOOL macdrv_wglSwapIntervalEXT(int interval)
3398 struct wgl_context *context = NtCurrentTeb()->glContext;
3399 BOOL changed = FALSE;
3401 TRACE("interval %d\n", interval);
3403 if (interval < 0)
3405 SetLastError(ERROR_INVALID_DATA);
3406 return FALSE;
3408 if (interval > 1)
3409 interval = 1;
3411 if (context->draw_hwnd)
3413 struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
3414 if (data)
3416 changed = data->swap_interval != interval;
3417 if (changed)
3418 data->swap_interval = interval;
3419 release_win_data(data);
3422 else /* pbuffer */
3423 interval = 0;
3425 InterlockedExchange(&context->update_swap_interval, FALSE);
3426 if (!set_swap_interval(context, interval))
3428 SetLastError(ERROR_GEN_FAILURE);
3429 return FALSE;
3432 if (changed)
3434 struct wgl_context *ctx;
3436 EnterCriticalSection(&context_section);
3437 LIST_FOR_EACH_ENTRY(ctx, &context_list, struct wgl_context, entry)
3439 if (ctx != context && ctx->draw_hwnd == context->draw_hwnd)
3440 InterlockedExchange(&context->update_swap_interval, TRUE);
3442 LeaveCriticalSection(&context_section);
3445 return TRUE;
3449 static void register_extension(const char *ext)
3451 if (gl_info.wglExtensions[0])
3452 strcat(gl_info.wglExtensions, " ");
3453 strcat(gl_info.wglExtensions, ext);
3455 TRACE("'%s'\n", ext);
3458 static void load_extensions(void)
3461 * ARB Extensions
3463 register_extension("WGL_ARB_extensions_string");
3464 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
3466 register_extension("WGL_ARB_make_current_read");
3467 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
3468 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
3470 register_extension("WGL_ARB_pixel_format");
3471 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
3472 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
3473 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
3475 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
3477 register_extension("WGL_ARB_pixel_format_float");
3478 register_extension("WGL_ATI_pixel_format_float");
3481 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
3482 register_extension("WGL_ARB_multisample");
3484 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3485 register_extension("WGL_ARB_framebuffer_sRGB");
3487 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
3489 register_extension("WGL_ARB_pbuffer");
3490 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
3491 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
3492 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
3493 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
3494 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
3496 register_extension("WGL_ARB_render_texture");
3497 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
3498 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
3499 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
3501 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
3502 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
3503 register_extension("WGL_NV_render_texture_rectangle");
3506 register_extension("WGL_ARB_create_context");
3507 register_extension("WGL_ARB_create_context_profile");
3508 opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
3511 * EXT Extensions
3513 register_extension("WGL_EXT_extensions_string");
3514 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
3516 if (allow_vsync)
3518 register_extension("WGL_EXT_swap_control");
3519 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
3520 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
3523 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3524 check for either, so register them separately. */
3525 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
3526 register_extension("WGL_EXT_framebuffer_sRGB");
3528 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
3529 register_extension("WGL_EXT_pixel_format_packed_float");
3532 * WINE-specific WGL Extensions
3535 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3536 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3538 register_extension("WGL_WINE_pixel_format_passthrough");
3539 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
3543 static BOOL init_opengl(void)
3545 static BOOL init_done = FALSE;
3546 unsigned int i;
3547 char buffer[200];
3549 if (init_done) return (opengl_handle != NULL);
3550 init_done = TRUE;
3552 TRACE("()\n");
3554 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3555 if (!dc_pbuffers)
3557 WARN("CFDictionaryCreateMutable failed\n");
3558 return FALSE;
3561 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3562 if (!opengl_handle)
3564 ERR("Failed to load OpenGL: %s\n", buffer);
3565 ERR("OpenGL support is disabled.\n");
3566 return FALSE;
3569 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3571 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3573 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3574 goto failed;
3578 /* redirect some standard OpenGL functions */
3579 #define REDIRECT(func) \
3580 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3581 REDIRECT(glCopyPixels);
3582 REDIRECT(glGetString);
3583 REDIRECT(glReadPixels);
3584 REDIRECT(glViewport);
3585 if (skip_single_buffer_flushes || allow_vsync)
3586 REDIRECT(glFlush);
3587 if (allow_vsync)
3588 REDIRECT(glFinish);
3589 #undef REDIRECT
3591 /* redirect some OpenGL extension functions */
3592 #define REDIRECT(func) \
3593 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3594 REDIRECT(glCopyColorTable);
3595 #undef REDIRECT
3597 if (!init_gl_info())
3598 goto failed;
3600 if (gluCheckExtension((GLubyte*)"GL_APPLE_flush_render", (GLubyte*)gl_info.glExtensions))
3601 pglFlushRenderAPPLE = wine_dlsym(opengl_handle, "glFlushRenderAPPLE", NULL, 0);
3603 load_extensions();
3604 if (!init_pixel_formats())
3605 goto failed;
3607 return TRUE;
3609 failed:
3610 wine_dlclose(opengl_handle, NULL, 0);
3611 opengl_handle = NULL;
3612 return FALSE;
3616 /***********************************************************************
3617 * sync_gl_view
3619 * Synchronize the Mac GL view position with the Windows child window
3620 * position.
3622 void sync_gl_view(struct macdrv_win_data *data)
3624 RECT rect;
3626 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3628 if (!data->gl_view) return;
3630 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3632 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3633 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3634 data->gl_rect = rect;
3639 /**********************************************************************
3640 * macdrv_wglDescribePixelFormat
3642 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3644 const pixel_format *pf;
3645 const struct color_mode *mode;
3647 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3649 if (!descr) return nb_displayable_formats;
3650 if (size < sizeof(*descr)) return 0;
3652 if (!(pf = get_pixel_format(fmt, FALSE)))
3653 return 0;
3655 memset(descr, 0, sizeof(*descr));
3656 descr->nSize = sizeof(*descr);
3657 descr->nVersion = 1;
3659 descr->dwFlags = PFD_SUPPORT_OPENGL;
3660 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3661 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3662 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3663 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3664 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3666 descr->iPixelType = PFD_TYPE_RGBA;
3668 mode = &color_modes[pf->color_mode];
3669 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3670 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3671 R8G8B8A0 pixel format). If an app depends on that and expects that
3672 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3673 if (mode->alpha_bits)
3674 descr->cColorBits = mode->color_bits;
3675 else
3676 descr->cColorBits = mode->bits_per_pixel;
3677 descr->cRedBits = mode->red_bits;
3678 descr->cRedShift = mode->red_shift;
3679 descr->cGreenBits = mode->green_bits;
3680 descr->cGreenShift = mode->green_shift;
3681 descr->cBlueBits = mode->blue_bits;
3682 descr->cBlueShift = mode->blue_shift;
3683 descr->cAlphaBits = mode->alpha_bits;
3684 descr->cAlphaShift = mode->alpha_shift;
3686 if (pf->accum_mode)
3688 mode = &color_modes[pf->accum_mode - 1];
3689 descr->cAccumBits = mode->color_bits;
3690 descr->cAccumRedBits = mode->red_bits;
3691 descr->cAccumGreenBits = mode->green_bits;
3692 descr->cAccumBlueBits = mode->blue_bits;
3693 descr->cAccumAlphaBits = mode->alpha_bits;
3696 descr->cDepthBits = pf->depth_bits;
3697 descr->cStencilBits = pf->stencil_bits;
3698 descr->cAuxBuffers = pf->aux_buffers;
3699 descr->iLayerType = PFD_MAIN_PLANE;
3701 TRACE("%s\n", debugstr_pf(pf));
3702 return nb_displayable_formats;
3705 /***********************************************************************
3706 * macdrv_wglCopyContext
3708 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3710 CGLError err;
3712 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3714 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3715 if (err != kCGLNoError)
3716 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3717 return (err == kCGLNoError);
3720 /***********************************************************************
3721 * macdrv_wglCreateContext
3723 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3725 struct wgl_context *context;
3727 TRACE("hdc %p\n", hdc);
3729 context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
3731 return context;
3734 /***********************************************************************
3735 * macdrv_wglDeleteContext
3737 static void macdrv_wglDeleteContext(struct wgl_context *context)
3739 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3741 EnterCriticalSection(&context_section);
3742 list_remove(&context->entry);
3743 LeaveCriticalSection(&context_section);
3745 macdrv_dispose_opengl_context(context->context);
3746 HeapFree(GetProcessHeap(), 0, context);
3749 /***********************************************************************
3750 * macdrv_wglGetPixelFormat
3752 static int macdrv_wglGetPixelFormat(HDC hdc)
3754 int format;
3756 format = get_dc_pixel_format(hdc);
3758 if (!is_valid_pixel_format(format)) /* not set yet */
3759 format = 0;
3760 else if (!is_displayable_pixel_format(format))
3762 /* Non-displayable formats can't be used with traditional WGL calls.
3763 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3764 format = 1;
3767 TRACE(" hdc %p -> %d\n", hdc, format);
3768 return format;
3771 /***********************************************************************
3772 * macdrv_wglGetProcAddress
3774 static PROC macdrv_wglGetProcAddress(const char *proc)
3776 void *ret;
3778 if (!strncmp(proc, "wgl", 3)) return NULL;
3779 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3780 if (ret)
3782 if (TRACE_ON(wgl))
3784 Dl_info info;
3785 if (dladdr(ret, &info))
3786 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3787 else
3788 TRACE("%s -> %p (no library info)\n", proc, ret);
3791 else
3792 WARN("failed to find proc %s\n", debugstr_a(proc));
3793 return ret;
3796 /***********************************************************************
3797 * macdrv_wglMakeCurrent
3799 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3801 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3802 (context ? context->cglcontext : NULL));
3804 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3807 /**********************************************************************
3808 * macdrv_wglSetPixelFormat
3810 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3812 return set_pixel_format(hdc, fmt, FALSE);
3815 /***********************************************************************
3816 * macdrv_wglShareLists
3818 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3820 macdrv_opengl_context saved_context;
3821 CGLContextObj saved_cglcontext;
3823 TRACE("org %p dest %p\n", org, dest);
3825 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3826 * at context creation time but in case of WGL it is done using wglShareLists.
3828 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3829 * and when a program requests sharing we recreate the destination context if it hasn't been made
3830 * current or when it hasn't shared display lists before.
3833 if (dest->has_been_current)
3835 WARN("could not share display lists, the destination context has been current already\n");
3836 return FALSE;
3838 else if (dest->sharing)
3840 WARN("could not share display lists because dest has already shared lists before\n");
3841 return FALSE;
3844 /* Re-create the Mac context and share display lists */
3845 saved_context = dest->context;
3846 saved_cglcontext = dest->cglcontext;
3847 dest->context = NULL;
3848 dest->cglcontext = NULL;
3849 if (!create_context(dest, org->cglcontext, dest->major))
3851 dest->context = saved_context;
3852 dest->cglcontext = saved_cglcontext;
3853 return FALSE;
3856 /* Implicitly disposes of saved_cglcontext. */
3857 macdrv_dispose_opengl_context(saved_context);
3859 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3860 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3862 org->sharing = TRUE;
3863 dest->sharing = TRUE;
3865 return TRUE;
3868 /**********************************************************************
3869 * macdrv_wglSwapBuffers
3871 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3873 struct wgl_context *context = NtCurrentTeb()->glContext;
3874 BOOL match = FALSE;
3875 HWND hwnd;
3877 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3878 (context ? context->cglcontext : NULL));
3880 if (context)
3881 sync_swap_interval(context);
3883 if ((hwnd = WindowFromDC(hdc)))
3885 struct macdrv_win_data *data;
3887 if (!(data = get_win_data(hwnd)))
3889 SetLastError(ERROR_INVALID_HANDLE);
3890 return FALSE;
3893 if (context && context->draw_view == data->gl_view)
3894 match = TRUE;
3896 release_win_data(data);
3898 else
3900 struct wgl_pbuffer *pbuffer;
3902 EnterCriticalSection(&dc_pbuffers_section);
3903 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3904 LeaveCriticalSection(&dc_pbuffers_section);
3906 if (!pbuffer)
3908 SetLastError(ERROR_INVALID_HANDLE);
3909 return FALSE;
3912 if (context && context->draw_pbuffer == pbuffer)
3913 match = TRUE;
3916 if (match)
3917 macdrv_flush_opengl_context(context->context);
3918 else
3920 FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc);
3922 /* If there is a current context, then wglSwapBuffers should do an implicit
3923 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3924 in the other branch, but we have to do it explicitly here. */
3925 if (context)
3926 pglFlush();
3929 return TRUE;
3932 static struct opengl_funcs opengl_funcs =
3935 macdrv_wglCopyContext, /* p_wglCopyContext */
3936 macdrv_wglCreateContext, /* p_wglCreateContext */
3937 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3938 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3939 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3940 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3941 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3942 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3943 macdrv_wglShareLists, /* p_wglShareLists */
3944 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3948 /**********************************************************************
3949 * macdrv_wine_get_wgl_driver
3951 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3953 if (version != WINE_WGL_DRIVER_VERSION)
3955 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3956 return NULL;
3959 if (!init_opengl()) return (void *)-1;
3961 return &opengl_funcs;