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
23 #include "wine/port.h"
29 #include "wine/library.h"
30 #include "wine/debug.h"
32 #include "wine/wgl_driver.h"
33 #include "wine/wglext.h"
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
49 char wglExtensions[4096];
51 GLint max_viewport_dims[2];
54 static struct gl_info gl_info;
61 macdrv_opengl_context context;
62 CGLContextObj cglcontext;
63 macdrv_view draw_view;
64 struct wgl_pbuffer *draw_pbuffer;
65 macdrv_view read_view;
66 struct wgl_pbuffer *read_pbuffer;
67 BOOL has_been_current;
74 CGLPBufferObj pbuffer;
82 static CFMutableDictionaryRef dc_pbuffers;
84 static CRITICAL_SECTION dc_pbuffers_section;
85 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug =
87 0, 0, &dc_pbuffers_section,
88 { &dc_pbuffers_section_debug.ProcessLocksList, &dc_pbuffers_section_debug.ProcessLocksList },
89 0, 0, { (DWORD_PTR)(__FILE__ ": dc_pbuffers_section") }
91 static CRITICAL_SECTION dc_pbuffers_section = { &dc_pbuffers_section_debug, -1, 0, 0, 0, 0 };
94 static struct opengl_funcs opengl_funcs;
96 #define USE_GL_FUNC(name) #name,
97 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
101 static void (*pglCopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y,
103 static void (*pglCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
104 static void (*pglReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
105 GLenum format, GLenum type, void *pixels);
106 static void (*pglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
112 GLint color_bits; /* including alpha_bits */
113 int red_bits, red_shift;
114 int green_bits, green_shift;
115 int blue_bits, blue_shift;
116 GLint alpha_bits, alpha_shift;
121 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
122 observations of the behavior of Windows systems, but also subjective judgments
123 about what color formats are more "normal" than others.
125 On at least some Windows systems, integer color formats are listed before
126 floating-point formats. Within the integer formats, higher color bits were
127 usually listed before lower color bits, while for floating-point formats it
128 was the reverse. However, that leads D3D to select 64-bit integer formats in
129 preference to 32-bit formats when the latter would be sufficient. It seems
130 that a 32-bit format is much more likely to be normally used in that case.
132 Also, there are certain odd color formats supported on the Mac which seem like
133 they would be less appropriate than more common ones. For instance, the color
134 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
135 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
138 For two color formats which differ only in whether or not they have alpha bits,
139 we use the same ordering. pixel_format_comparator() gives alpha bits a
140 different weight than color formats.
142 static const struct color_mode color_modes[] = {
143 { kCGLRGB444Bit, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE, 5 },
144 { kCGLARGB4444Bit, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE, 5 },
145 { kCGLRGB444A8Bit, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE, 10 },
146 { kCGLRGB555Bit, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE, 4 },
147 { kCGLARGB1555Bit, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE, 4 },
148 { kCGLRGB555A8Bit, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE, 9 },
149 { kCGLRGB565Bit, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE, 3 },
150 { kCGLRGB565A8Bit, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE, 8 },
151 { kCGLRGB888Bit, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE, 0 },
152 { kCGLARGB8888Bit, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE, 0 },
153 { kCGLRGB888A8Bit, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE, 7 },
154 { kCGLRGB101010Bit, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE, 6 },
155 { kCGLARGB2101010Bit, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE, 6 },
156 { kCGLRGB101010_A8Bit, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE, 11 },
157 { kCGLRGB121212Bit, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE, 2 },
158 { kCGLARGB12121212Bit, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE, 2 },
159 { kCGLRGB161616Bit, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE, 1 },
160 { kCGLRGBA16161616Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE, 1 },
161 { kCGLRGBFloat64Bit, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE, 12 },
162 { kCGLRGBAFloat64Bit, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE, 12 },
163 { kCGLRGBFloat128Bit, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE, 13 },
164 { kCGLRGBAFloat128Bit, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE, 13 },
165 { kCGLRGBFloat256Bit, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE, 14 },
166 { kCGLRGBAFloat256Bit, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE, 15 },
170 static const struct {
173 } depth_stencil_modes[] = {
201 GLint max_aux_buffers;
202 GLint max_sample_buffers;
209 } renderer_properties;
213 unsigned int window:1;
214 unsigned int pbuffer:1;
215 unsigned int accelerated:1;
216 unsigned int color_mode:5; /* index into color_modes table */
217 unsigned int aux_buffers:3;
218 unsigned int depth_bits:8;
219 unsigned int stencil_bits:8;
220 unsigned int accum_mode:5; /* 1 + index into color_modes table (0 means no accum buffer) */
221 unsigned int double_buffer:1;
222 unsigned int stereo:1;
223 unsigned int sample_buffers:1;
224 unsigned int samples:5;
225 unsigned int backing_store:1;
233 } pixel_format_or_code;
236 static pixel_format *pixel_formats;
237 static int nb_formats, nb_displayable_formats;
240 static void *opengl_handle;
243 static const char* debugstr_attrib(int attrib, int value)
245 static const struct {
249 #define ATTRIB(a) { a, #a }
250 ATTRIB(WGL_ACCELERATION_ARB),
251 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB),
252 ATTRIB(WGL_ACCUM_BITS_ARB),
253 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB),
254 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB),
255 ATTRIB(WGL_ACCUM_RED_BITS_ARB),
256 ATTRIB(WGL_ALPHA_BITS_ARB),
257 ATTRIB(WGL_ALPHA_SHIFT_ARB),
258 ATTRIB(WGL_AUX_BUFFERS_ARB),
259 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV),
260 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV),
261 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB),
262 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB),
263 ATTRIB(WGL_BLUE_BITS_ARB),
264 ATTRIB(WGL_BLUE_SHIFT_ARB),
265 ATTRIB(WGL_COLOR_BITS_ARB),
266 ATTRIB(WGL_DEPTH_BITS_ARB),
267 ATTRIB(WGL_DOUBLE_BUFFER_ARB),
268 ATTRIB(WGL_DRAW_TO_BITMAP_ARB),
269 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB),
270 ATTRIB(WGL_DRAW_TO_WINDOW_ARB),
271 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB),
272 ATTRIB(WGL_GREEN_BITS_ARB),
273 ATTRIB(WGL_GREEN_SHIFT_ARB),
274 ATTRIB(WGL_NEED_PALETTE_ARB),
275 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB),
276 ATTRIB(WGL_NUMBER_OVERLAYS_ARB),
277 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB),
278 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB),
279 ATTRIB(WGL_PIXEL_TYPE_ARB),
280 ATTRIB(WGL_RED_BITS_ARB),
281 ATTRIB(WGL_RED_SHIFT_ARB),
282 ATTRIB(WGL_SAMPLE_BUFFERS_ARB),
283 ATTRIB(WGL_SAMPLES_ARB),
284 ATTRIB(WGL_SHARE_ACCUM_ARB),
285 ATTRIB(WGL_SHARE_DEPTH_ARB),
286 ATTRIB(WGL_SHARE_STENCIL_ARB),
287 ATTRIB(WGL_STENCIL_BITS_ARB),
288 ATTRIB(WGL_STEREO_ARB),
289 ATTRIB(WGL_SUPPORT_GDI_ARB),
290 ATTRIB(WGL_SUPPORT_OPENGL_ARB),
291 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB),
292 ATTRIB(WGL_SWAP_METHOD_ARB),
293 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB),
294 ATTRIB(WGL_TRANSPARENT_ARB),
295 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB),
296 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB),
297 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB),
298 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB),
302 const char *attrib_name = NULL;
303 const char *value_name = NULL;
305 for (i = 0; i < sizeof(attrib_names) / sizeof(attrib_names[0]); i++)
307 if (attrib_names[i].attrib == attrib)
309 attrib_name = attrib_names[i].name;
315 attrib_name = wine_dbg_sprintf("Attrib 0x%04x", attrib);
319 case WGL_ACCELERATION_ARB:
322 case WGL_FULL_ACCELERATION_ARB: value_name = "WGL_FULL_ACCELERATION_ARB"; break;
323 case WGL_GENERIC_ACCELERATION_ARB: value_name = "WGL_GENERIC_ACCELERATION_ARB"; break;
324 case WGL_NO_ACCELERATION_ARB: value_name = "WGL_NO_ACCELERATION_ARB"; break;
327 case WGL_PIXEL_TYPE_ARB:
330 case WGL_TYPE_COLORINDEX_ARB: value_name = "WGL_TYPE_COLORINDEX_ARB"; break;
331 case WGL_TYPE_RGBA_ARB: value_name = "WGL_TYPE_RGBA_ARB"; break;
332 case WGL_TYPE_RGBA_FLOAT_ARB: value_name = "WGL_TYPE_RGBA_FLOAT_ARB"; break;
333 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: value_name = "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
336 case WGL_SWAP_METHOD_ARB:
339 case WGL_SWAP_COPY_ARB: value_name = "WGL_SWAP_COPY_ARB"; break;
340 case WGL_SWAP_EXCHANGE_ARB: value_name = "WGL_SWAP_EXCHANGE_ARB"; break;
341 case WGL_SWAP_UNDEFINED_ARB: value_name = "WGL_SWAP_UNDEFINED_ARB"; break;
347 value_name = wine_dbg_sprintf("%d / 0x%04x", value, value);
349 return wine_dbg_sprintf("%40s: %s", attrib_name, value_name);
353 static BOOL get_renderer_property(CGLRendererInfoObj renderer_info, GLint renderer_index,
354 CGLRendererProperty property, GLint *value)
356 CGLError err = CGLDescribeRenderer(renderer_info, renderer_index, property, value);
357 if (err != kCGLNoError)
358 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property, err, CGLErrorString(err));
359 return (err == kCGLNoError);
363 static void get_renderer_properties(CGLRendererInfoObj renderer_info, int renderer_index, renderer_properties* properties)
367 memset(properties, 0, sizeof(*properties));
369 if (get_renderer_property(renderer_info, renderer_index, kCGLRPRendererID, &value))
370 properties->renderer_id = value & kCGLRendererIDMatchingMask;
372 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBufferModes, &value))
373 properties->buffer_modes = value;
375 if (get_renderer_property(renderer_info, renderer_index, kCGLRPColorModes, &value))
376 properties->color_modes = value;
378 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccumModes, &value))
379 properties->accum_modes = value;
381 if (get_renderer_property(renderer_info, renderer_index, kCGLRPDepthModes, &value))
382 properties->depth_modes = value;
384 if (get_renderer_property(renderer_info, renderer_index, kCGLRPStencilModes, &value))
385 properties->stencil_modes = value;
387 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxAuxBuffers, &value))
388 properties->max_aux_buffers = value;
390 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSampleBuffers, &value))
391 properties->max_sample_buffers = value;
393 if (get_renderer_property(renderer_info, renderer_index, kCGLRPMaxSamples, &value))
394 properties->max_samples = value;
396 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOffScreen, &value))
397 properties->offscreen = (value != 0);
399 if (get_renderer_property(renderer_info, renderer_index, kCGLRPAccelerated, &value))
400 properties->accelerated = (value != 0);
402 if (get_renderer_property(renderer_info, renderer_index, kCGLRPBackingStore, &value))
403 properties->backing_store = (value != 0);
405 if (get_renderer_property(renderer_info, renderer_index, kCGLRPWindow, &value))
406 properties->window = (value != 0);
408 if (get_renderer_property(renderer_info, renderer_index, kCGLRPOnline, &value))
409 properties->online = (value != 0);
413 static void dump_renderer(const renderer_properties* renderer)
417 TRACE("Renderer ID: 0x%08x\n", renderer->renderer_id);
418 TRACE("Buffer modes:\n");
419 TRACE(" Monoscopic: %s\n", (renderer->buffer_modes & kCGLMonoscopicBit) ? "YES" : "NO");
420 TRACE(" Stereoscopic: %s\n", (renderer->buffer_modes & kCGLStereoscopicBit) ? "YES" : "NO");
421 TRACE(" Single buffer: %s\n", (renderer->buffer_modes & kCGLSingleBufferBit) ? "YES" : "NO");
422 TRACE(" Double buffer: %s\n", (renderer->buffer_modes & kCGLDoubleBufferBit) ? "YES" : "NO");
424 TRACE("Color buffer modes:\n");
425 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
427 if (renderer->color_modes & color_modes[i].mode)
429 TRACE(" Color size %d, Alpha size %d", color_modes[i].color_bits, color_modes[i].alpha_bits);
430 if (color_modes[i].is_float)
436 TRACE("Accumulation buffer sizes: { ");
437 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
439 if (renderer->accum_modes & color_modes[i].mode)
440 TRACE("%d, ", color_modes[i].color_bits);
444 TRACE("Depth buffer sizes: { ");
445 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
447 if (renderer->depth_modes & depth_stencil_modes[i].mode)
448 TRACE("%d, ", depth_stencil_modes[i].bits);
452 TRACE("Stencil buffer sizes: { ");
453 for (i = 0; i < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); i++)
455 if (renderer->stencil_modes & depth_stencil_modes[i].mode)
456 TRACE("%d, ", depth_stencil_modes[i].bits);
460 TRACE("Max. Auxiliary Buffers: %d\n", renderer->max_aux_buffers);
461 TRACE("Max. Sample Buffers: %d\n", renderer->max_sample_buffers);
462 TRACE("Max. Samples: %d\n", renderer->max_samples);
463 TRACE("Offscreen: %s\n", renderer->offscreen ? "YES" : "NO");
464 TRACE("Accelerated: %s\n", renderer->accelerated ? "YES" : "NO");
465 TRACE("Backing store: %s\n", renderer->backing_store ? "YES" : "NO");
466 TRACE("Window: %s\n", renderer->window ? "YES" : "NO");
467 TRACE("Online: %s\n", renderer->online ? "YES" : "NO");
471 static inline UInt64 code_for_pixel_format(const pixel_format* format)
473 pixel_format_or_code pfc;
476 pfc.format = *format;
481 static inline pixel_format pixel_format_for_code(UInt64 code)
483 pixel_format_or_code pfc;
490 static const char *debugstr_pf(const pixel_format *pf)
492 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",
496 color_modes[pf->color_mode].color_bits,
497 (color_modes[pf->color_mode].is_float ? "f" : ""),
498 color_modes[pf->color_mode].alpha_bits,
501 pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0,
508 code_for_pixel_format(pf));
512 static unsigned int best_color_mode(GLint modes, GLint color_size, GLint alpha_size, GLint color_float)
517 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
519 if ((modes & color_modes[i].mode) &&
520 color_modes[i].color_bits >= color_size &&
521 color_modes[i].alpha_bits >= alpha_size &&
522 !color_modes[i].is_float == !color_float)
524 if (best < 0) /* no existing best choice */
526 else if (color_modes[i].color_bits == color_size &&
527 color_modes[i].alpha_bits == alpha_size) /* candidate is exact match */
529 /* prefer it over a best which isn't exact or which has a higher bpp */
530 if (color_modes[best].color_bits != color_size ||
531 color_modes[best].alpha_bits != alpha_size ||
532 color_modes[i].bits_per_pixel < color_modes[best].bits_per_pixel)
535 else if (color_modes[i].color_bits < color_modes[best].color_bits ||
536 (color_modes[i].color_bits == color_modes[best].color_bits &&
537 color_modes[i].alpha_bits < color_modes[best].alpha_bits)) /* prefer closer */
544 /* Couldn't find a match. Return first one that renderer supports. */
545 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
547 if (modes & color_modes[i].mode)
556 static unsigned int best_accum_mode(GLint modes, GLint accum_size)
561 for (i = 0; i < sizeof(color_modes)/sizeof(color_modes[0]); i++)
563 if ((modes & color_modes[i].mode) && color_modes[i].color_bits >= accum_size)
565 /* Prefer the fewest color bits, then prefer more alpha bits, then
566 prefer more bits per pixel. */
569 else if (color_modes[i].color_bits < color_modes[best].color_bits)
571 else if (color_modes[i].color_bits == color_modes[best].color_bits)
573 if (color_modes[i].alpha_bits > color_modes[best].alpha_bits)
575 else if (color_modes[i].alpha_bits == color_modes[best].alpha_bits &&
576 color_modes[i].bits_per_pixel > color_modes[best].bits_per_pixel)
584 /* Couldn't find a match. Return last one that renderer supports. */
585 for (i = sizeof(color_modes)/sizeof(color_modes[0]) - 1; i >= 0; i--)
587 if (modes & color_modes[i].mode)
596 static void enum_renderer_pixel_formats(renderer_properties renderer, CFMutableArrayRef pixel_format_array,
597 CFMutableSetRef pixel_format_set)
599 CGLPixelFormatAttribute attribs[64] = {
600 kCGLPFAMinimumPolicy,
601 kCGLPFAClosestPolicy,
602 kCGLPFARendererID, renderer.renderer_id,
603 kCGLPFASingleRenderer,
605 int n = 5, n_stack[16], n_stack_idx = -1;
606 unsigned int tried_pixel_formats = 0, failed_pixel_formats = 0, dupe_pixel_formats = 0,
607 new_pixel_formats = 0;
608 pixel_format request;
609 unsigned int double_buffer;
610 unsigned int accelerated = renderer.accelerated;
614 attribs[n++] = kCGLPFAAccelerated;
615 attribs[n++] = kCGLPFANoRecovery;
618 n_stack[++n_stack_idx] = n;
619 for (double_buffer = 0; double_buffer <= 1; double_buffer++)
623 n = n_stack[n_stack_idx];
625 if ((!double_buffer && !(renderer.buffer_modes & kCGLSingleBufferBit)) ||
626 (double_buffer && !(renderer.buffer_modes & kCGLDoubleBufferBit)))
630 attribs[n++] = kCGLPFADoubleBuffer;
631 memset(&request, 0, sizeof(request));
632 request.accelerated = accelerated;
633 request.double_buffer = double_buffer;
635 /* Don't bother with in-between aux buffers values: either 0 or max. */
636 n_stack[++n_stack_idx] = n;
637 for (aux = 0; aux <= renderer.max_aux_buffers; aux += renderer.max_aux_buffers)
639 unsigned int color_mode;
641 n = n_stack[n_stack_idx];
643 attribs[n++] = kCGLPFAAuxBuffers;
645 request.aux_buffers = aux;
647 n_stack[++n_stack_idx] = n;
648 for (color_mode = 0; color_mode < sizeof(color_modes)/sizeof(color_modes[0]); color_mode++)
650 unsigned int depth_mode;
652 n = n_stack[n_stack_idx];
654 if (!(renderer.color_modes & color_modes[color_mode].mode))
657 attribs[n++] = kCGLPFAColorSize;
658 attribs[n++] = color_modes[color_mode].color_bits;
659 attribs[n++] = kCGLPFAAlphaSize;
660 attribs[n++] = color_modes[color_mode].alpha_bits;
661 if (color_modes[color_mode].is_float)
662 attribs[n++] = kCGLPFAColorFloat;
663 request.color_mode = color_mode;
665 n_stack[++n_stack_idx] = n;
666 for (depth_mode = 0; depth_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); depth_mode++)
668 unsigned int stencil_mode;
670 n = n_stack[n_stack_idx];
672 if (!(renderer.depth_modes & depth_stencil_modes[depth_mode].mode))
675 attribs[n++] = kCGLPFADepthSize;
676 attribs[n++] = depth_stencil_modes[depth_mode].bits;
677 request.depth_bits = depth_stencil_modes[depth_mode].bits;
679 n_stack[++n_stack_idx] = n;
680 for (stencil_mode = 0; stencil_mode < sizeof(depth_stencil_modes)/sizeof(depth_stencil_modes[0]); stencil_mode++)
684 n = n_stack[n_stack_idx];
686 if (!(renderer.stencil_modes & depth_stencil_modes[stencil_mode].mode))
688 if (accelerated && depth_stencil_modes[depth_mode].bits != 24 && stencil_mode > 0)
691 attribs[n++] = kCGLPFAStencilSize;
692 attribs[n++] = depth_stencil_modes[stencil_mode].bits;
693 request.stencil_bits = depth_stencil_modes[stencil_mode].bits;
695 /* FIXME: Could trim search space a bit here depending on GPU.
696 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
697 n_stack[++n_stack_idx] = n;
698 for (stereo = 0; stereo <= 1; stereo++)
702 n = n_stack[n_stack_idx];
704 if ((!stereo && !(renderer.buffer_modes & kCGLMonoscopicBit)) ||
705 (stereo && !(renderer.buffer_modes & kCGLStereoscopicBit)))
709 attribs[n++] = kCGLPFAStereo;
710 request.stereo = stereo;
712 /* Starts at -1 for a 0 accum size */
713 n_stack[++n_stack_idx] = n;
714 for (accum_mode = -1; accum_mode < (int)(sizeof(color_modes)/sizeof(color_modes[0])); accum_mode++)
716 unsigned int target_pass;
718 n = n_stack[n_stack_idx];
722 if (!(renderer.accum_modes & color_modes[accum_mode].mode))
725 attribs[n++] = kCGLPFAAccumSize;
726 attribs[n++] = color_modes[accum_mode].color_bits;
727 request.accum_mode = accum_mode + 1;
730 request.accum_mode = 0;
732 /* Targets to request are:
733 accelerated: window OR window + pbuffer
734 software: window + pbuffer */
735 n_stack[++n_stack_idx] = n;
736 for (target_pass = 0; target_pass <= accelerated; target_pass++)
738 unsigned int samples, max_samples;
740 n = n_stack[n_stack_idx];
742 attribs[n++] = kCGLPFAWindow;
745 if (!accelerated || target_pass > 0)
747 attribs[n++] = kCGLPFAPBuffer;
753 /* FIXME: Could trim search space a bit here depending on GPU.
754 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
755 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
756 n_stack[++n_stack_idx] = n;
757 max_samples = renderer.max_sample_buffers ? max(1, renderer.max_samples) : 1;
758 for (samples = 1; samples <= max_samples; samples *= 2)
760 unsigned int backing_store, min_backing_store, max_backing_store;
762 n = n_stack[n_stack_idx];
766 attribs[n++] = kCGLPFASampleBuffers;
767 attribs[n++] = renderer.max_sample_buffers;
768 attribs[n++] = kCGLPFASamples;
769 attribs[n++] = samples;
770 request.sample_buffers = renderer.max_sample_buffers;
771 request.samples = samples;
774 request.sample_buffers = request.samples = 0;
776 if (renderer.backing_store && double_buffer)
778 /* The software renderer seems to always preserve the backing store, whether
779 we ask for it or not. So don't bother not asking for it. */
780 min_backing_store = accelerated ? 0 : 1;
781 max_backing_store = 1;
784 min_backing_store = max_backing_store = 0;
785 n_stack[++n_stack_idx] = n;
786 for (backing_store = min_backing_store; backing_store <= max_backing_store; backing_store++)
788 CGLPixelFormatObj pix;
789 GLint virtualScreens;
792 n = n_stack[n_stack_idx];
795 attribs[n++] = kCGLPFABackingStore;
796 request.backing_store = backing_store;
800 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
801 if (err == kCGLNoError && pix)
804 GLint value, color_size, alpha_size, color_float;
806 CFNumberRef code_object;
809 memset(&pf, 0, sizeof(pf));
811 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccelerated, &value) == kCGLNoError)
812 pf.accelerated = value;
813 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAuxBuffers, &value) == kCGLNoError)
814 pf.aux_buffers = value;
815 if (CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value) == kCGLNoError)
816 pf.depth_bits = value;
817 if (CGLDescribePixelFormat(pix, 0, kCGLPFADoubleBuffer, &value) == kCGLNoError)
818 pf.double_buffer = value;
819 if (pf.double_buffer &&
820 CGLDescribePixelFormat(pix, 0, kCGLPFABackingStore, &value) == kCGLNoError)
821 pf.backing_store = value;
822 if (CGLDescribePixelFormat(pix, 0, kCGLPFAPBuffer, &value) == kCGLNoError)
824 if (CGLDescribePixelFormat(pix, 0, kCGLPFASampleBuffers, &value) == kCGLNoError)
825 pf.sample_buffers = value;
826 if (pf.sample_buffers &&
827 CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value) == kCGLNoError)
829 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value) == kCGLNoError)
830 pf.stencil_bits = value;
831 if (CGLDescribePixelFormat(pix, 0, kCGLPFAStereo, &value) == kCGLNoError)
833 if (CGLDescribePixelFormat(pix, 0, kCGLPFAWindow, &value) == kCGLNoError)
836 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &color_size) != kCGLNoError)
838 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAlphaSize, &alpha_size) != kCGLNoError)
840 if (CGLDescribePixelFormat(pix, 0, kCGLPFAColorFloat, &color_float) != kCGLNoError)
842 pf.color_mode = best_color_mode(renderer.color_modes, color_size, alpha_size, color_float);
844 if (CGLDescribePixelFormat(pix, 0, kCGLPFAAccumSize, &value) == kCGLNoError && value)
845 pf.accum_mode = best_accum_mode(renderer.accum_modes, value) + 1;
847 CGLReleasePixelFormat(pix);
849 pf_code = code_for_pixel_format(&pf);
851 code_object = CFNumberCreate(NULL, kCFNumberSInt64Type, &pf_code);
852 if ((dupe = CFSetContainsValue(pixel_format_set, code_object)))
853 dupe_pixel_formats++;
856 CFSetAddValue(pixel_format_set, code_object);
857 CFArrayAppendValue(pixel_format_array, code_object);
860 CFRelease(code_object);
862 if (pf_code == code_for_pixel_format(&request))
863 TRACE("%s%s\n", debugstr_pf(&pf), dupe ? " (duplicate)" : "");
866 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf), debugstr_pf(&request),
867 dupe ? " (duplicate)" : "");
872 failed_pixel_formats++;
873 TRACE("%s failed request err %d %s\n", debugstr_pf(&request), err, err ? CGLErrorString(err) : "");
876 tried_pixel_formats++;
908 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats);
909 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats);
910 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats);
911 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats);
915 /* The docs for WGL_ARB_pixel_format say:
916 Indices are assigned to pixel formats in the following order:
917 1. Accelerated pixel formats that are displayable
918 2. Accelerated pixel formats that are displayable and which have
920 3. Generic pixel formats
921 4. Accelerated pixel formats that are non displayable
923 static int pixel_format_category(pixel_format pf)
925 /* non-displayable */
929 /* non-accelerated a.k.a. software a.k.a. generic */
933 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
934 if (color_modes[pf.color_mode].is_float)
937 /* accelerated, displayable, no extended attributes */
942 static CFComparisonResult pixel_format_comparator(const void *val1, const void *val2, void *context)
944 CFNumberRef number1 = val1;
945 CFNumberRef number2 = val2;
947 pixel_format pf1, pf2;
948 int category1, category2;
950 CFNumberGetValue(number1, kCFNumberLongLongType, &code1);
951 CFNumberGetValue(number2, kCFNumberLongLongType, &code2);
952 pf1 = pixel_format_for_code(code1);
953 pf2 = pixel_format_for_code(code2);
954 category1 = pixel_format_category(pf1);
955 category2 = pixel_format_category(pf2);
957 if (category1 < category2)
958 return kCFCompareLessThan;
959 if (category1 > category2)
960 return kCFCompareGreaterThan;
962 /* Within a category, sort the "best" formats toward the front since that's
963 what wglChoosePixelFormatARB() has to do. The ordering implemented here
964 matches at least one Windows 7 machine's behavior.
966 /* Accelerated before unaccelerated. */
967 if (pf1.accelerated && !pf2.accelerated)
968 return kCFCompareLessThan;
969 if (!pf1.accelerated && pf2.accelerated)
970 return kCFCompareGreaterThan;
972 /* Explicit color mode ordering. */
973 if (color_modes[pf1.color_mode].color_ordering < color_modes[pf2.color_mode].color_ordering)
974 return kCFCompareLessThan;
975 if (color_modes[pf1.color_mode].color_ordering > color_modes[pf2.color_mode].color_ordering)
976 return kCFCompareGreaterThan;
978 /* Non-pbuffer-capable before pbuffer-capable. */
979 if (!pf1.pbuffer && pf2.pbuffer)
980 return kCFCompareLessThan;
981 if (pf1.pbuffer && !pf2.pbuffer)
982 return kCFCompareGreaterThan;
984 /* Fewer samples before more samples. */
985 if (pf1.samples < pf2.samples)
986 return kCFCompareLessThan;
987 if (pf1.samples > pf2.samples)
988 return kCFCompareGreaterThan;
990 /* Monoscopic before stereoscopic. (This is a guess.) */
991 if (!pf1.stereo && pf2.stereo)
992 return kCFCompareLessThan;
993 if (pf1.stereo && !pf2.stereo)
994 return kCFCompareGreaterThan;
996 /* Single buffered before double buffered. */
997 if (!pf1.double_buffer && pf2.double_buffer)
998 return kCFCompareLessThan;
999 if (pf1.double_buffer && !pf2.double_buffer)
1000 return kCFCompareGreaterThan;
1002 /* Possibly-optimized double buffering before backing-store-preserving
1003 double buffering. */
1004 if (!pf1.backing_store && pf2.backing_store)
1005 return kCFCompareLessThan;
1006 if (pf1.backing_store && !pf2.backing_store)
1007 return kCFCompareGreaterThan;
1009 /* Bigger depth buffer before smaller depth buffer. */
1010 if (pf1.depth_bits > pf2.depth_bits)
1011 return kCFCompareLessThan;
1012 if (pf1.depth_bits < pf2.depth_bits)
1013 return kCFCompareGreaterThan;
1015 /* Smaller stencil buffer before bigger stencil buffer. */
1016 if (pf1.stencil_bits < pf2.stencil_bits)
1017 return kCFCompareLessThan;
1018 if (pf1.stencil_bits > pf2.stencil_bits)
1019 return kCFCompareGreaterThan;
1021 /* Smaller alpha bits before larger alpha bits. */
1022 if (color_modes[pf1.color_mode].alpha_bits < color_modes[pf2.color_mode].alpha_bits)
1023 return kCFCompareLessThan;
1024 if (color_modes[pf1.color_mode].alpha_bits > color_modes[pf2.color_mode].alpha_bits)
1025 return kCFCompareGreaterThan;
1027 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1032 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits <
1033 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1034 return kCFCompareLessThan;
1035 if (color_modes[pf1.accum_mode - 1].color_bits - color_modes[pf1.accum_mode - 1].alpha_bits >
1036 color_modes[pf2.accum_mode - 1].color_bits - color_modes[pf2.accum_mode - 1].alpha_bits)
1037 return kCFCompareGreaterThan;
1039 if (color_modes[pf1.accum_mode - 1].bits_per_pixel < color_modes[pf2.accum_mode - 1].bits_per_pixel)
1040 return kCFCompareLessThan;
1041 if (color_modes[pf1.accum_mode - 1].bits_per_pixel > color_modes[pf2.accum_mode - 1].bits_per_pixel)
1042 return kCFCompareGreaterThan;
1044 if (color_modes[pf1.accum_mode - 1].alpha_bits < color_modes[pf2.accum_mode - 1].alpha_bits)
1045 return kCFCompareLessThan;
1046 if (color_modes[pf1.accum_mode - 1].alpha_bits > color_modes[pf2.accum_mode - 1].alpha_bits)
1047 return kCFCompareGreaterThan;
1050 return kCFCompareGreaterThan;
1052 else if (pf2.accum_mode)
1053 return kCFCompareLessThan;
1055 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1056 if (pf1.aux_buffers < pf2.aux_buffers)
1057 return kCFCompareLessThan;
1058 if (pf1.aux_buffers > pf2.aux_buffers)
1059 return kCFCompareGreaterThan;
1061 /* If we get here, arbitrarily sort based on code. */
1063 return kCFCompareLessThan;
1065 return kCFCompareGreaterThan;
1066 return kCFCompareEqualTo;
1070 static BOOL init_pixel_formats(void)
1073 CGLRendererInfoObj renderer_info;
1074 GLint rendererCount;
1076 CFMutableSetRef pixel_format_set;
1077 CFMutableArrayRef pixel_format_array;
1083 assert(sizeof(((pixel_format_or_code*)0)->format) <= sizeof(((pixel_format_or_code*)0)->code));
1085 err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info, &rendererCount);
1088 WARN("CGLQueryRendererInfo failed (%d) %s\n", err, CGLErrorString(err));
1092 pixel_format_set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
1093 if (!pixel_format_set)
1095 WARN("CFSetCreateMutable failed\n");
1096 CGLDestroyRendererInfo(renderer_info);
1100 pixel_format_array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1101 if (!pixel_format_array)
1103 WARN("CFArrayCreateMutable failed\n");
1104 CFRelease(pixel_format_set);
1105 CGLDestroyRendererInfo(renderer_info);
1109 for (i = 0; i < rendererCount; i++)
1111 renderer_properties renderer;
1113 get_renderer_properties(renderer_info, i, &renderer);
1116 TRACE("renderer_properties %d:\n", i);
1117 dump_renderer(&renderer);
1120 enum_renderer_pixel_formats(renderer, pixel_format_array, pixel_format_set);
1123 CFRelease(pixel_format_set);
1124 CGLDestroyRendererInfo(renderer_info);
1126 range = CFRangeMake(0, CFArrayGetCount(pixel_format_array));
1129 pixel_formats = HeapAlloc(GetProcessHeap(), 0, range.length * sizeof(*pixel_formats));
1132 CFArraySortValues(pixel_format_array, range, pixel_format_comparator, NULL);
1133 for (i = 0; i < range.length; i++)
1135 CFNumberRef number = CFArrayGetValueAtIndex(pixel_format_array, i);
1138 CFNumberGetValue(number, kCFNumberLongLongType, &code);
1139 pixel_formats[i] = pixel_format_for_code(code);
1140 if (pixel_formats[i].window)
1141 nb_displayable_formats++;
1144 nb_formats = range.length;
1145 TRACE("Total number of unique pixel formats: %d\n", nb_formats);
1149 WARN("failed to allocate pixel format list\n");
1152 WARN("got no pixel formats\n");
1154 CFRelease(pixel_format_array);
1159 static inline BOOL is_valid_pixel_format(int format)
1161 return format > 0 && format <= nb_formats;
1165 static inline BOOL is_displayable_pixel_format(int format)
1167 return format > 0 && format <= nb_displayable_formats;
1171 static const pixel_format *get_pixel_format(int format, BOOL allow_nondisplayable)
1173 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1174 * format in case of probing the number of pixel formats.
1176 if (is_valid_pixel_format(format) && (is_displayable_pixel_format(format) || allow_nondisplayable))
1178 TRACE("Returning format %d\n", format);
1179 return &pixel_formats[format - 1];
1185 static BOOL init_gl_info(void)
1187 CGDirectDisplayID display = CGMainDisplayID();
1188 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(display);
1189 CGLPixelFormatAttribute attribs[] = {
1190 kCGLPFADisplayMask, displayMask,
1193 CGLPixelFormatObj pix;
1194 GLint virtualScreens;
1196 CGLContextObj context;
1197 CGLContextObj old_context = CGLGetCurrentContext();
1200 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
1201 if (err != kCGLNoError || !pix)
1203 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
1207 err = CGLCreateContext(pix, NULL, &context);
1208 CGLReleasePixelFormat(pix);
1209 if (err != kCGLNoError || !context)
1211 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
1215 err = CGLSetCurrentContext(context);
1216 if (err != kCGLNoError)
1218 WARN("CGLSetCurrentContext() failed with error %d %s\n", err, CGLErrorString(err));
1219 CGLReleaseContext(context);
1223 str = (const char*)opengl_funcs.gl.p_glGetString(GL_VERSION);
1224 gl_info.glVersion = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1225 strcpy(gl_info.glVersion, str);
1226 str = (const char*)opengl_funcs.gl.p_glGetString(GL_EXTENSIONS);
1227 gl_info.glExtensions = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
1228 strcpy(gl_info.glExtensions, str);
1230 opengl_funcs.gl.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS, gl_info.max_viewport_dims);
1232 TRACE("GL version : %s\n", gl_info.glVersion);
1233 TRACE("GL renderer : %s\n", opengl_funcs.gl.p_glGetString(GL_RENDERER));
1235 CGLSetCurrentContext(old_context);
1236 CGLReleaseContext(context);
1242 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
1245 *rect = data->client_rect;
1247 if (data->cocoa_window)
1250 *window = data->cocoa_window;
1251 OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top);
1255 HWND top = GetAncestor(data->hwnd, GA_ROOT);
1256 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
1257 struct macdrv_win_data *top_data = get_win_data(top);
1259 if (top_data && top_data->cocoa_window)
1262 *window = top_data->cocoa_window;
1263 MapWindowPoints(parent, 0, (POINT*)rect, 2);
1264 OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top);
1269 release_win_data(top_data);
1276 /***********************************************************************
1279 static BOOL set_win_format(struct macdrv_win_data *data, int format)
1281 macdrv_window cocoa_window;
1283 TRACE("hwnd %p format %d\n", data->hwnd, format);
1285 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1287 ERR("no top-level parent with Cocoa window in this process\n");
1291 if (data->gl_view) macdrv_dispose_view(data->gl_view);
1292 data->gl_view = macdrv_create_view(cocoa_window, cgrect_from_rect(data->gl_rect));
1296 WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect));
1300 TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window,
1301 wine_dbgstr_rect(&data->gl_rect));
1303 data->pixel_format = format;
1309 /**********************************************************************
1312 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1314 static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
1316 struct macdrv_win_data *data;
1317 const pixel_format *pf;
1318 HWND hwnd = WindowFromDC(hdc);
1321 TRACE("hdc %p format %d\n", hdc, fmt);
1323 if (!hwnd || hwnd == GetDesktopWindow())
1325 WARN("not a proper window DC %p/%p\n", hdc, hwnd);
1329 if (!(data = get_win_data(hwnd)))
1331 FIXME("DC for window %p of other process: not implemented\n", hwnd);
1335 if (!allow_reset && data->pixel_format) /* cannot change it if already set */
1337 ret = (data->pixel_format == fmt);
1341 /* Check if fmt is in our list of supported formats to see if it is supported. */
1342 pf = get_pixel_format(fmt, FALSE /* non-displayable */);
1345 ERR("Invalid pixel format: %d\n", fmt);
1351 WARN("Pixel format %d is not compatible for window rendering\n", fmt);
1355 if (!set_win_format(data, fmt))
1357 WARN("Couldn't set format of the window, returning failure\n");
1361 TRACE("pixel format:\n");
1362 TRACE(" window: %u\n", (unsigned int)pf->window);
1363 TRACE(" pBuffer: %u\n", (unsigned int)pf->pbuffer);
1364 TRACE(" accelerated: %u\n", (unsigned int)pf->accelerated);
1365 TRACE(" color bits: %u%s\n", (unsigned int)color_modes[pf->color_mode].color_bits, (color_modes[pf->color_mode].is_float ? " float" : ""));
1366 TRACE(" alpha bits: %u\n", (unsigned int)color_modes[pf->color_mode].alpha_bits);
1367 TRACE(" aux buffers: %u\n", (unsigned int)pf->aux_buffers);
1368 TRACE(" depth bits: %u\n", (unsigned int)pf->depth_bits);
1369 TRACE(" stencil bits: %u\n", (unsigned int)pf->stencil_bits);
1370 TRACE(" accum bits: %u\n", (unsigned int)pf->accum_mode ? color_modes[pf->accum_mode - 1].color_bits : 0);
1371 TRACE(" double_buffer: %u\n", (unsigned int)pf->double_buffer);
1372 TRACE(" stereo: %u\n", (unsigned int)pf->stereo);
1373 TRACE(" sample_buffers: %u\n", (unsigned int)pf->sample_buffers);
1374 TRACE(" samples: %u\n", (unsigned int)pf->samples);
1375 TRACE(" backing_store: %u\n", (unsigned int)pf->backing_store);
1379 release_win_data(data);
1380 if (ret) __wine_set_pixel_format(hwnd, fmt);
1385 /**********************************************************************
1386 * set_gl_view_parent
1388 void set_gl_view_parent(HWND hwnd, HWND parent)
1390 struct macdrv_win_data *data;
1392 if (!(data = get_win_data(hwnd))) return;
1396 macdrv_window cocoa_window;
1398 TRACE("moving GL view %p to parent %p\n", data->gl_view, parent);
1400 if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect))
1402 ERR("no top-level parent with Cocoa window in this process\n");
1403 macdrv_dispose_view(data->gl_view);
1404 data->gl_view = NULL;
1405 release_win_data(data);
1406 __wine_set_pixel_format( hwnd, 0 );
1410 macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
1413 release_win_data(data);
1417 /**********************************************************************
1418 * make_context_current
1420 static void make_context_current(struct wgl_context *context, BOOL read)
1423 struct wgl_pbuffer *pbuffer;
1427 view = context->read_view;
1428 pbuffer = context->read_pbuffer;
1432 view = context->draw_view;
1433 pbuffer = context->draw_pbuffer;
1436 if (view || !pbuffer)
1437 macdrv_make_context_current(context->context, view);
1440 CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
1442 CGLSetCurrentContext(context->cglcontext);
1447 /**********************************************************************
1448 * macdrv_glCopyColorTable
1450 * Hook into glCopyColorTable as part of the implementation of
1451 * wglMakeContextCurrentARB. If the context has a separate readable,
1452 * temporarily make that current, do glCopyColorTable, and then set it
1453 * back to the drawable. This is modeled after what Mesa GLX's Apple
1454 * implementation does.
1456 static void macdrv_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y,
1459 struct wgl_context *context = NtCurrentTeb()->glContext;
1461 if (context->read_view || context->read_pbuffer)
1462 make_context_current(context, TRUE);
1464 pglCopyColorTable(target, internalformat, x, y, width);
1466 if (context->read_view || context->read_pbuffer)
1467 make_context_current(context, FALSE);
1471 /**********************************************************************
1472 * macdrv_glCopyPixels
1474 * Hook into glCopyPixels as part of the implementation of
1475 * wglMakeContextCurrentARB. If the context has a separate readable,
1476 * temporarily make that current, do glCopyPixels, and then set it back
1477 * to the drawable. This is modeled after what Mesa GLX's Apple
1478 * implementation does.
1480 static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
1482 struct wgl_context *context = NtCurrentTeb()->glContext;
1484 if (context->read_view || context->read_pbuffer)
1485 make_context_current(context, TRUE);
1487 pglCopyPixels(x, y, width, height, type);
1489 if (context->read_view || context->read_pbuffer)
1490 make_context_current(context, FALSE);
1494 /**********************************************************************
1495 * macdrv_glReadPixels
1497 * Hook into glReadPixels as part of the implementation of
1498 * wglMakeContextCurrentARB. If the context has a separate readable,
1499 * temporarily make that current, do glReadPixels, and then set it back
1500 * to the drawable. This is modeled after what Mesa GLX's Apple
1501 * implementation does.
1503 static void macdrv_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1504 GLenum format, GLenum type, void *pixels)
1506 struct wgl_context *context = NtCurrentTeb()->glContext;
1508 if (context->read_view || context->read_pbuffer)
1509 make_context_current(context, TRUE);
1511 pglReadPixels(x, y, width, height, format, type, pixels);
1513 if (context->read_view || context->read_pbuffer)
1514 make_context_current(context, FALSE);
1518 /**********************************************************************
1521 * Hook into glViewport as an opportunity to update the OpenGL context
1522 * if necessary. This is modeled after what Mesa GLX's Apple
1523 * implementation does.
1525 static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
1527 struct wgl_context *context = NtCurrentTeb()->glContext;
1529 macdrv_update_opengl_context(context->context);
1530 pglViewport(x, y, width, height);
1534 /***********************************************************************
1535 * macdrv_wglBindTexImageARB
1537 * WGL_ARB_render_texture: wglBindTexImageARB
1539 static BOOL macdrv_wglBindTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
1541 struct wgl_context *context = NtCurrentTeb()->glContext;
1545 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer, iBuffer);
1547 if (pbuffer->no_texture)
1549 SetLastError(ERROR_INVALID_OPERATION);
1553 if (!context->draw_view && context->draw_pbuffer == pbuffer)
1554 opengl_funcs.gl.p_glFlush();
1558 case WGL_FRONT_LEFT_ARB:
1559 if (pixel_formats[pbuffer->format].stereo)
1560 source = GL_FRONT_LEFT;
1564 case WGL_FRONT_RIGHT_ARB:
1565 source = GL_FRONT_RIGHT;
1567 case WGL_BACK_LEFT_ARB:
1568 if (pixel_formats[pbuffer->format].stereo)
1569 source = GL_BACK_LEFT;
1573 case WGL_BACK_RIGHT_ARB:
1574 source = GL_BACK_RIGHT;
1576 case WGL_AUX0_ARB: source = GL_AUX0; break;
1577 case WGL_AUX1_ARB: source = GL_AUX1; break;
1578 case WGL_AUX2_ARB: source = GL_AUX2; break;
1579 case WGL_AUX3_ARB: source = GL_AUX3; break;
1587 FIXME("unsupported source buffer 0x%x\n", iBuffer);
1588 SetLastError(ERROR_INVALID_DATA);
1592 WARN("unknown source buffer 0x%x\n", iBuffer);
1593 SetLastError(ERROR_INVALID_DATA);
1597 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, source);
1598 if (err != kCGLNoError)
1600 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
1601 SetLastError(ERROR_INVALID_OPERATION);
1609 /***********************************************************************
1610 * macdrv_wglChoosePixelFormatARB
1612 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1614 static BOOL macdrv_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
1615 const FLOAT *pfAttribFList, UINT nMaxFormats,
1616 int *piFormats, UINT *nNumFormats)
1618 pixel_format pf, valid;
1620 int color_bits, red_bits, green_bits, blue_bits, alpha_bits;
1621 int accum_bits, accum_red_bits, accum_green_bits, accum_blue_bits, accum_alpha_bits;
1626 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1627 hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
1629 FIXME("unused pfAttribFList\n");
1631 memset(&pf, 0, sizeof(pf));
1632 memset(&valid, 0, sizeof(valid));
1633 color_bits = red_bits = green_bits = blue_bits = alpha_bits = 0;
1634 accum_bits = accum_red_bits = accum_green_bits = accum_blue_bits = accum_alpha_bits = 0;
1638 for (iptr = piAttribIList; iptr && *iptr; iptr += 2)
1641 int value = iptr[1];
1643 TRACE("%s\n", debugstr_attrib(attr, value));
1647 case WGL_DRAW_TO_WINDOW_ARB:
1648 if (valid.window && (!pf.window != !value)) goto cant_match;
1649 pf.window = (value != 0);
1653 case WGL_DRAW_TO_BITMAP_ARB:
1656 case WGL_ACCELERATION_ARB:
1657 if (value == WGL_FULL_ACCELERATION_ARB)
1659 else if (value == WGL_NO_ACCELERATION_ARB)
1663 if (valid.accelerated && pf.accelerated != value) goto cant_match;
1664 pf.accelerated = value;
1665 valid.accelerated = 1;
1668 case WGL_NEED_PALETTE_ARB:
1669 case WGL_NEED_SYSTEM_PALETTE_ARB:
1670 case WGL_SWAP_LAYER_BUFFERS_ARB:
1671 if (value) goto cant_match;
1674 case WGL_SWAP_METHOD_ARB:
1675 if (value == WGL_SWAP_COPY_ARB)
1677 else if (value == WGL_SWAP_UNDEFINED_ARB)
1681 if (valid.backing_store && pf.backing_store != value) goto cant_match;
1682 if (valid.double_buffer && !pf.double_buffer && value) goto cant_match;
1683 pf.backing_store = value;
1684 valid.backing_store = 1;
1687 case WGL_NUMBER_OVERLAYS_ARB:
1688 case WGL_NUMBER_UNDERLAYS_ARB:
1689 if (value) goto cant_match;
1692 case WGL_SHARE_DEPTH_ARB:
1693 case WGL_SHARE_STENCIL_ARB:
1694 case WGL_SHARE_ACCUM_ARB:
1698 case WGL_SUPPORT_GDI_ARB:
1699 if (value) goto cant_match;
1702 case WGL_SUPPORT_OPENGL_ARB:
1703 if (!value) goto cant_match;
1706 case WGL_DOUBLE_BUFFER_ARB:
1707 if (valid.double_buffer && (!pf.double_buffer != !value)) goto cant_match;
1708 pf.double_buffer = (value != 0);
1709 valid.double_buffer = 1;
1710 if (valid.backing_store && pf.backing_store && !pf.double_buffer) goto cant_match;
1713 case WGL_STEREO_ARB:
1714 if (valid.stereo && (!pf.stereo != !value)) goto cant_match;
1715 pf.stereo = (value != 0);
1719 case WGL_PIXEL_TYPE_ARB:
1720 if (value == WGL_TYPE_RGBA_FLOAT_ARB)
1722 else if (value == WGL_TYPE_RGBA_ARB)
1726 /* Mac contexts don't support rendering to unsigned floating
1727 point formats, even if GL_EXT_packed_float is supported.
1728 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1731 if (float_color != -1 && float_color != value) goto cant_match;
1732 if (srgb && value) goto cant_match;
1733 float_color = value;
1736 case WGL_COLOR_BITS_ARB:
1737 if (color_bits < value) color_bits = value;
1740 case WGL_RED_BITS_ARB:
1741 if (srgb && value > 8) goto cant_match;
1742 if (red_bits < value) red_bits = value;
1745 case WGL_GREEN_BITS_ARB:
1746 if (srgb && value > 8) goto cant_match;
1747 if (green_bits < value) green_bits = value;
1750 case WGL_BLUE_BITS_ARB:
1751 if (srgb && value > 8) goto cant_match;
1752 if (blue_bits < value) blue_bits = value;
1755 case WGL_ALPHA_BITS_ARB:
1756 if (alpha_bits < value) alpha_bits = value;
1759 case WGL_ACCUM_BITS_ARB:
1760 if (accum_bits < value) accum_bits = value;
1763 case WGL_ACCUM_RED_BITS_ARB:
1764 if (accum_red_bits < value) accum_red_bits = value;
1767 case WGL_ACCUM_GREEN_BITS_ARB:
1768 if (accum_green_bits < value) accum_green_bits = value;
1771 case WGL_ACCUM_BLUE_BITS_ARB:
1772 if (accum_blue_bits < value) accum_blue_bits = value;
1775 case WGL_ACCUM_ALPHA_BITS_ARB:
1776 if (accum_alpha_bits < value) accum_alpha_bits = value;
1779 case WGL_DEPTH_BITS_ARB:
1780 if (value > 255) goto cant_match;
1781 if (pf.depth_bits < value) pf.depth_bits = value;
1784 case WGL_STENCIL_BITS_ARB:
1785 if (value > 255) goto cant_match;
1786 if (pf.stencil_bits < value) pf.stencil_bits = value;
1789 case WGL_AUX_BUFFERS_ARB:
1790 if (value > 7) goto cant_match;
1791 if (pf.aux_buffers < value) pf.aux_buffers = value;
1794 case WGL_SAMPLE_BUFFERS_ARB:
1795 if (value > 1) goto cant_match;
1796 if (pf.sample_buffers < value) pf.sample_buffers = value;
1799 case WGL_SAMPLES_ARB:
1800 if (value > 31) goto cant_match;
1801 if (pf.samples < value) pf.samples = value;
1804 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1805 /* sRGB is only supported for 8-bit integer color components */
1806 if (float_color >= 1 || red_bits > 8 || green_bits > 8 || blue_bits > 8)
1811 case WGL_NUMBER_PIXEL_FORMATS_ARB:
1812 case WGL_RED_SHIFT_ARB:
1813 case WGL_GREEN_SHIFT_ARB:
1814 case WGL_BLUE_SHIFT_ARB:
1815 case WGL_ALPHA_SHIFT_ARB:
1816 case WGL_TRANSPARENT_ARB:
1817 case WGL_TRANSPARENT_RED_VALUE_ARB:
1818 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
1819 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
1820 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
1821 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
1825 case WGL_DRAW_TO_PBUFFER_ARB:
1826 case WGL_BIND_TO_TEXTURE_RGB_ARB:
1827 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
1828 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
1829 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
1830 if (valid.pbuffer && (!pf.pbuffer != !value)) goto cant_match;
1831 pf.pbuffer = (value != 0);
1833 if ((attr == WGL_BIND_TO_TEXTURE_RGBA_ARB || attr == WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV) &&
1839 WARN("invalid attribute %s\n", debugstr_attrib(attr, value));
1844 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",
1845 valid.window ? (pf.window ? "1" : "0") : "?",
1846 valid.pbuffer ? (pf.pbuffer ? "1" : "0") : "?",
1847 valid.accelerated ? (pf.accelerated ? "1" : "0") : "?",
1849 float_color == -1 ? "?" : float_color ? "f" : "",
1863 valid.backing_store ? (pf.backing_store ? "1" : "0") : "?",
1864 valid.double_buffer ? (pf.double_buffer ? "1" : "0") : "?",
1865 valid.stereo ? (pf.stereo ? "1" : "0") : "?",
1869 for (i = 0; i < nb_formats && found < nMaxFormats; i++)
1871 const struct color_mode *mode;
1873 if (valid.window && pixel_formats[i].window != pf.window) continue;
1874 if (valid.pbuffer && pixel_formats[i].pbuffer != pf.pbuffer) continue;
1875 if (valid.accelerated && pixel_formats[i].accelerated != pf.accelerated) continue;
1876 if (valid.double_buffer && pixel_formats[i].double_buffer != pf.double_buffer) continue;
1877 if (valid.stereo && pixel_formats[i].stereo != pf.stereo) continue;
1878 if (valid.backing_store && pixel_formats[i].backing_store != pf.backing_store) continue;
1880 if (pixel_formats[i].aux_buffers < pf.aux_buffers) continue;
1881 if (pixel_formats[i].depth_bits < pf.depth_bits) continue;
1882 if (pixel_formats[i].stencil_bits < pf.stencil_bits) continue;
1883 if (pixel_formats[i].sample_buffers < pf.sample_buffers) continue;
1884 if (pixel_formats[i].samples < pf.samples) continue;
1886 mode = &color_modes[pixel_formats[i].color_mode];
1887 /* If the mode doesn't have alpha, check requested color bits against
1888 bits per pixel instead of the mode's color bits. On Windows, color
1889 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1890 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1891 expects that to match such a pixel format, we need to accommodate that. */
1892 if (mode->alpha_bits)
1894 if (mode->color_bits < color_bits)
1899 if (mode->bits_per_pixel < color_bits)
1902 if (mode->red_bits < red_bits || mode->green_bits < green_bits ||
1903 mode->blue_bits < blue_bits || mode->alpha_bits < alpha_bits)
1905 if (float_color != -1 && (!mode->is_float != !float_color)) continue;
1906 if (srgb && (mode->red_bits != 8 || mode->green_bits != 8 || mode->blue_bits != 8 || mode->is_float))
1909 if (pixel_formats[i].accum_mode)
1911 mode = &color_modes[pixel_formats[i].accum_mode - 1];
1912 if (mode->color_bits < accum_bits || mode->red_bits < accum_red_bits ||
1913 mode->green_bits < accum_green_bits || mode->blue_bits < accum_blue_bits ||
1914 mode->alpha_bits < accum_alpha_bits)
1917 else if (accum_bits || accum_red_bits || accum_green_bits || accum_blue_bits || accum_alpha_bits)
1920 piFormats[found++] = i;
1921 TRACE("match: pixel format %d %s\n", i, debugstr_pf(&pixel_formats[i]));
1925 *nNumFormats = found;
1931 /**********************************************************************
1932 * macdrv_wglCreatePbufferARB
1934 * WGL_ARB_pbuffer: wglCreatePbufferARB
1936 static struct wgl_pbuffer *macdrv_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight,
1937 const int *piAttribList)
1939 struct wgl_pbuffer* pbuffer;
1941 GLenum internalFormat = 0;
1944 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
1945 hdc, iPixelFormat, iWidth, iHeight, piAttribList);
1947 if (!is_valid_pixel_format(iPixelFormat) || !pixel_formats[iPixelFormat].pbuffer)
1949 WARN("invalid pixel format %d\n", iPixelFormat);
1950 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1954 pbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pbuffer));
1955 pbuffer->format = iPixelFormat;
1957 for ( ; piAttribList && *piAttribList; piAttribList += 2)
1959 int attr = piAttribList[0];
1960 int value = piAttribList[1];
1964 case WGL_PBUFFER_LARGEST_ARB:
1965 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value);
1968 case WGL_TEXTURE_FORMAT_ARB:
1971 case WGL_TEXTURE_RGBA_ARB:
1972 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1973 internalFormat = GL_RGBA;
1975 case WGL_TEXTURE_RGB_ARB:
1976 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
1977 internalFormat = GL_RGB;
1979 case WGL_NO_TEXTURE_ARB:
1980 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
1984 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value);
1985 SetLastError(ERROR_INVALID_DATA);
1990 case WGL_TEXTURE_TARGET_ARB:
1994 case WGL_NO_TEXTURE_ARB:
1995 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
1998 case WGL_TEXTURE_CUBE_MAP_ARB:
1999 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2000 target = GL_TEXTURE_CUBE_MAP;
2001 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2003 case WGL_TEXTURE_1D_ARB:
2004 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2005 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2007 case WGL_TEXTURE_2D_ARB:
2008 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2009 target = GL_TEXTURE_2D;
2011 case WGL_TEXTURE_RECTANGLE_NV:
2012 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2013 target = GL_TEXTURE_RECTANGLE;
2016 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value);
2017 SetLastError(ERROR_INVALID_DATA);
2022 case WGL_MIPMAP_TEXTURE_ARB:
2023 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value);
2024 pbuffer->max_level = 0;
2027 int size = min(iWidth, iHeight) / 2;
2030 pbuffer->max_level++;
2037 WARN("unknown attribute 0x%x\n", attr);
2038 SetLastError(ERROR_INVALID_DATA);
2043 if (!target || !internalFormat)
2045 pbuffer->no_texture = TRUE;
2046 /* no actual way to turn off ability to texture; use most permissive target */
2047 target = GL_TEXTURE_RECTANGLE;
2048 internalFormat = GL_RGB;
2051 err = CGLCreatePBuffer(iWidth, iHeight, target, internalFormat, pbuffer->max_level, &pbuffer->pbuffer);
2052 if (err != kCGLNoError)
2054 WARN("CGLCreatePBuffer failed; err %d %s\n", err, CGLErrorString(err));
2055 pbuffer->pbuffer = NULL;
2056 if (err == kCGLBadAlloc)
2057 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2059 SetLastError(ERROR_INVALID_DATA);
2063 if (!pbuffer->pbuffer)
2065 HeapFree(GetProcessHeap(), 0, pbuffer);
2069 TRACE(" -> %p\n", pbuffer);
2074 /**********************************************************************
2075 * macdrv_wglDestroyPbufferARB
2077 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2079 static BOOL macdrv_wglDestroyPbufferARB(struct wgl_pbuffer *pbuffer)
2081 TRACE("pbuffer %p\n", pbuffer);
2082 if (pbuffer && pbuffer->pbuffer)
2083 CGLReleasePBuffer(pbuffer->pbuffer);
2084 HeapFree(GetProcessHeap(), 0, pbuffer);
2089 /**********************************************************************
2090 * macdrv_wglGetExtensionsStringARB
2092 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2094 static const GLubyte *macdrv_wglGetExtensionsStringARB(HDC hdc)
2096 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2097 this can be specific to the CGL renderer like we're supposed to do. */
2098 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2099 return (const GLubyte*)gl_info.wglExtensions;
2103 /**********************************************************************
2104 * macdrv_wglGetExtensionsStringEXT
2106 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2108 static const GLubyte *macdrv_wglGetExtensionsStringEXT(void)
2110 TRACE("returning \"%s\"\n", gl_info.wglExtensions);
2111 return (const GLubyte*)gl_info.wglExtensions;
2115 /**********************************************************************
2116 * macdrv_wglGetPbufferDCARB
2118 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2120 static HDC macdrv_wglGetPbufferDCARB(struct wgl_pbuffer *pbuffer)
2123 struct wgl_pbuffer *prev;
2125 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2128 EnterCriticalSection(&dc_pbuffers_section);
2129 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2132 CGLReleasePBuffer(prev->pbuffer);
2133 HeapFree(GetProcessHeap(), 0, prev);
2135 CFDictionarySetValue(dc_pbuffers, hdc, pbuffer);
2136 LeaveCriticalSection(&dc_pbuffers_section);
2138 TRACE("pbuffer %p -> hdc %p\n", pbuffer, hdc);
2143 /**********************************************************************
2144 * macdrv_wglGetPixelFormatAttribivARB
2146 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2148 static BOOL macdrv_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2149 UINT nAttributes, const int *piAttributes, int *piValues)
2151 const pixel_format *pf;
2154 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2155 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2157 if (!nAttributes) return GL_TRUE;
2159 if (nAttributes == 1 && piAttributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
2161 piValues[0] = nb_formats;
2162 TRACE("%s\n", debugstr_attrib(piAttributes[0], piValues[0]));
2166 pf = get_pixel_format(iPixelFormat, TRUE /* non-displayable */);
2169 WARN("invalid pixel format %d\n", iPixelFormat);
2170 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2174 for (i = 0; i < nAttributes; ++i)
2176 switch (piAttributes[i])
2178 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2179 piValues[i] = nb_formats;
2182 case WGL_DRAW_TO_WINDOW_ARB:
2183 piValues[i] = pf->window ? GL_TRUE : GL_FALSE;
2186 case WGL_DRAW_TO_BITMAP_ARB:
2187 piValues[i] = GL_FALSE;
2190 case WGL_ACCELERATION_ARB:
2191 if (iLayerPlane) goto invalid_layer;
2192 if (pf->accelerated)
2193 piValues[i] = WGL_FULL_ACCELERATION_ARB;
2195 piValues[i] = WGL_NO_ACCELERATION_ARB;
2198 case WGL_NEED_PALETTE_ARB:
2199 case WGL_NEED_SYSTEM_PALETTE_ARB:
2200 case WGL_SWAP_LAYER_BUFFERS_ARB:
2201 piValues[i] = GL_FALSE;
2204 case WGL_SWAP_METHOD_ARB:
2205 if (pf->double_buffer && pf->backing_store)
2206 piValues[i] = WGL_SWAP_COPY_ARB;
2208 piValues[i] = WGL_SWAP_UNDEFINED_ARB;
2211 case WGL_NUMBER_OVERLAYS_ARB:
2212 case WGL_NUMBER_UNDERLAYS_ARB:
2216 case WGL_TRANSPARENT_ARB:
2217 if (iLayerPlane) goto invalid_layer;
2218 piValues[i] = GL_FALSE;
2221 case WGL_TRANSPARENT_RED_VALUE_ARB:
2222 case WGL_TRANSPARENT_GREEN_VALUE_ARB:
2223 case WGL_TRANSPARENT_BLUE_VALUE_ARB:
2224 case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
2225 case WGL_TRANSPARENT_INDEX_VALUE_ARB:
2226 if (iLayerPlane) goto invalid_layer;
2230 case WGL_SHARE_DEPTH_ARB:
2231 case WGL_SHARE_STENCIL_ARB:
2232 case WGL_SHARE_ACCUM_ARB:
2233 if (iLayerPlane) goto invalid_layer;
2234 piValues[i] = GL_TRUE;
2237 case WGL_SUPPORT_GDI_ARB:
2238 if (iLayerPlane) goto invalid_layer;
2239 piValues[i] = GL_FALSE;
2242 case WGL_SUPPORT_OPENGL_ARB:
2243 if (iLayerPlane) goto invalid_layer;
2244 piValues[i] = GL_TRUE;
2247 case WGL_DOUBLE_BUFFER_ARB:
2248 if (iLayerPlane) goto invalid_layer;
2249 piValues[i] = pf->double_buffer ? GL_TRUE : GL_FALSE;
2252 case WGL_STEREO_ARB:
2253 if (iLayerPlane) goto invalid_layer;
2254 piValues[i] = pf->stereo ? GL_TRUE : GL_FALSE;
2257 case WGL_PIXEL_TYPE_ARB:
2258 if (iLayerPlane) goto invalid_layer;
2259 if (color_modes[pf->color_mode].is_float)
2260 piValues[i] = WGL_TYPE_RGBA_FLOAT_ARB;
2262 piValues[i] = WGL_TYPE_RGBA_ARB;
2263 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2264 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2265 However, Mac contexts don't support rendering to unsigned floating-point
2266 formats, even when GL_EXT_packed_float is supported. */
2269 case WGL_COLOR_BITS_ARB:
2270 if (iLayerPlane) goto invalid_layer;
2271 /* If the mode doesn't have alpha, return bits per pixel instead
2272 of color bits. On Windows, color bits sometimes exceeds r+g+b
2273 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2274 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2275 pixel format, we need to accommodate that. */
2276 if (color_modes[pf->color_mode].alpha_bits)
2277 piValues[i] = color_modes[pf->color_mode].color_bits;
2279 piValues[i] = color_modes[pf->color_mode].bits_per_pixel;
2282 case WGL_RED_BITS_ARB:
2283 if (iLayerPlane) goto invalid_layer;
2284 piValues[i] = color_modes[pf->color_mode].red_bits;
2287 case WGL_RED_SHIFT_ARB:
2288 if (iLayerPlane) goto invalid_layer;
2289 piValues[i] = color_modes[pf->color_mode].red_shift;
2292 case WGL_GREEN_BITS_ARB:
2293 if (iLayerPlane) goto invalid_layer;
2294 piValues[i] = color_modes[pf->color_mode].green_bits;
2297 case WGL_GREEN_SHIFT_ARB:
2298 if (iLayerPlane) goto invalid_layer;
2299 piValues[i] = color_modes[pf->color_mode].green_shift;
2302 case WGL_BLUE_BITS_ARB:
2303 if (iLayerPlane) goto invalid_layer;
2304 piValues[i] = color_modes[pf->color_mode].blue_bits;
2307 case WGL_BLUE_SHIFT_ARB:
2308 if (iLayerPlane) goto invalid_layer;
2309 piValues[i] = color_modes[pf->color_mode].blue_shift;
2312 case WGL_ALPHA_BITS_ARB:
2313 if (iLayerPlane) goto invalid_layer;
2314 piValues[i] = color_modes[pf->color_mode].alpha_bits;
2317 case WGL_ALPHA_SHIFT_ARB:
2318 if (iLayerPlane) goto invalid_layer;
2319 piValues[i] = color_modes[pf->color_mode].alpha_shift;
2322 case WGL_ACCUM_BITS_ARB:
2323 if (iLayerPlane) goto invalid_layer;
2325 piValues[i] = color_modes[pf->accum_mode - 1].color_bits;
2330 case WGL_ACCUM_RED_BITS_ARB:
2331 if (iLayerPlane) goto invalid_layer;
2333 piValues[i] = color_modes[pf->accum_mode - 1].red_bits;
2338 case WGL_ACCUM_GREEN_BITS_ARB:
2339 if (iLayerPlane) goto invalid_layer;
2341 piValues[i] = color_modes[pf->accum_mode - 1].green_bits;
2346 case WGL_ACCUM_BLUE_BITS_ARB:
2347 if (iLayerPlane) goto invalid_layer;
2349 piValues[i] = color_modes[pf->accum_mode - 1].blue_bits;
2354 case WGL_ACCUM_ALPHA_BITS_ARB:
2355 if (iLayerPlane) goto invalid_layer;
2357 piValues[i] = color_modes[pf->accum_mode - 1].alpha_bits;
2362 case WGL_DEPTH_BITS_ARB:
2363 if (iLayerPlane) goto invalid_layer;
2364 piValues[i] = pf->depth_bits;
2367 case WGL_STENCIL_BITS_ARB:
2368 if (iLayerPlane) goto invalid_layer;
2369 piValues[i] = pf->stencil_bits;
2372 case WGL_AUX_BUFFERS_ARB:
2373 if (iLayerPlane) goto invalid_layer;
2374 piValues[i] = pf->aux_buffers;
2377 case WGL_SAMPLE_BUFFERS_ARB:
2378 if (iLayerPlane) goto invalid_layer;
2379 piValues[i] = pf->sample_buffers;
2382 case WGL_SAMPLES_ARB:
2383 if (iLayerPlane) goto invalid_layer;
2384 piValues[i] = pf->samples;
2387 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2388 if (iLayerPlane) goto invalid_layer;
2389 /* sRGB is only supported for 8-bit integer color components */
2390 if (color_modes[pf->color_mode].red_bits == 8 &&
2391 color_modes[pf->color_mode].green_bits == 8 &&
2392 color_modes[pf->color_mode].blue_bits == 8 &&
2393 !color_modes[pf->color_mode].is_float)
2394 piValues[i] = GL_TRUE;
2396 piValues[i] = GL_FALSE;
2399 case WGL_DRAW_TO_PBUFFER_ARB:
2400 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2401 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV:
2402 piValues[i] = pf->pbuffer ? GL_TRUE : GL_FALSE;
2405 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2406 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV:
2407 piValues[i] = (pf->pbuffer && color_modes[pf->color_mode].alpha_bits) ? GL_TRUE : GL_FALSE;
2410 case WGL_MAX_PBUFFER_WIDTH_ARB:
2411 piValues[i] = gl_info.max_viewport_dims[0];
2414 case WGL_MAX_PBUFFER_HEIGHT_ARB:
2415 piValues[i] = gl_info.max_viewport_dims[1];
2418 case WGL_MAX_PBUFFER_PIXELS_ARB:
2419 piValues[i] = gl_info.max_viewport_dims[0] * gl_info.max_viewport_dims[1];
2423 WARN("invalid attribute %x\n", piAttributes[i]);
2427 TRACE("%s\n", debugstr_attrib(piAttributes[i], piValues[i]));
2433 FIXME("unsupported iLayerPlane %d\n", iLayerPlane);
2438 /**********************************************************************
2439 * macdrv_wglGetPixelFormatAttribfvARB
2441 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2443 static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
2444 UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2449 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2450 hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2452 /* Allocate a temporary array to store integer values */
2453 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2456 ERR("couldn't allocate %d array\n", nAttributes);
2460 /* Piggy-back on wglGetPixelFormatAttribivARB */
2461 ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2466 /* Convert integer values to float. Should also check for attributes
2467 that can give decimal values here */
2468 for (i = 0; i < nAttributes; i++)
2469 pfValues[i] = attr[i];
2472 HeapFree(GetProcessHeap(), 0, attr);
2477 /**********************************************************************
2478 * macdrv_wglGetSwapIntervalEXT
2480 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2482 static int macdrv_wglGetSwapIntervalEXT(void)
2484 struct wgl_context *context = NtCurrentTeb()->glContext;
2490 err = CGLGetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2491 if (err != kCGLNoError)
2493 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2494 err, CGLErrorString(err));
2502 /***********************************************************************
2503 * macdrv_wglMakeContextCurrentARB
2505 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2507 * This is not supported directly by OpenGL on the Mac. We emulate it
2508 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2509 * temporarily swap the drawable. This follows the technique used in
2510 * the implementation of Mesa GLX for Apple.
2512 static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct wgl_context *context)
2514 struct macdrv_win_data *data;
2517 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc, read_hdc, context,
2518 (context ? context->context : NULL), (context ? context->cglcontext : NULL));
2522 macdrv_make_context_current(NULL, NULL);
2523 NtCurrentTeb()->glContext = NULL;
2527 if ((hwnd = WindowFromDC(draw_hdc)))
2529 if (!(data = get_win_data(hwnd)))
2531 FIXME("draw DC for window %p of other process: not implemented\n", hwnd);
2535 if (!data->pixel_format)
2537 WARN("no pixel format set\n");
2538 release_win_data(data);
2539 SetLastError(ERROR_INVALID_HANDLE);
2542 if (context->format != data->pixel_format)
2544 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, data->pixel_format, context, context->format);
2545 release_win_data(data);
2546 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2550 context->draw_view = data->gl_view;
2551 context->draw_pbuffer = NULL;
2552 release_win_data(data);
2556 struct wgl_pbuffer *pbuffer;
2558 EnterCriticalSection(&dc_pbuffers_section);
2559 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, draw_hdc);
2562 if (context->format != pbuffer->format)
2564 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc, pbuffer->format, context, context->format);
2565 LeaveCriticalSection(&dc_pbuffers_section);
2566 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2572 WARN("no window or pbuffer for DC\n");
2573 LeaveCriticalSection(&dc_pbuffers_section);
2574 SetLastError(ERROR_INVALID_HANDLE);
2578 context->draw_view = NULL;
2579 context->draw_pbuffer = pbuffer;
2580 LeaveCriticalSection(&dc_pbuffers_section);
2583 context->read_view = NULL;
2584 context->read_pbuffer = NULL;
2585 if (read_hdc && read_hdc != draw_hdc)
2587 if ((hwnd = WindowFromDC(read_hdc)))
2589 if ((data = get_win_data(hwnd)))
2591 if (data->gl_view != context->draw_view)
2592 context->read_view = data->gl_view;
2593 release_win_data(data);
2598 EnterCriticalSection(&dc_pbuffers_section);
2599 context->read_pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, read_hdc);
2600 LeaveCriticalSection(&dc_pbuffers_section);
2604 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2605 context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format);
2607 make_context_current(context, FALSE);
2608 context->has_been_current = TRUE;
2609 NtCurrentTeb()->glContext = context;
2615 /**********************************************************************
2616 * macdrv_wglQueryPbufferARB
2618 * WGL_ARB_pbuffer: wglQueryPbufferARB
2620 static BOOL macdrv_wglQueryPbufferARB(struct wgl_pbuffer *pbuffer, int iAttribute, int *piValue)
2626 GLenum internalFormat;
2629 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer, iAttribute, piValue);
2631 err = CGLDescribePBuffer(pbuffer->pbuffer, &width, &height, &target, &internalFormat, &mipmap);
2632 if (err != kCGLNoError)
2634 WARN("CGLDescribePBuffer failed; error %d %s\n", err, CGLErrorString(err));
2635 SetLastError(ERROR_INVALID_HANDLE);
2641 case WGL_PBUFFER_WIDTH_ARB:
2644 case WGL_PBUFFER_HEIGHT_ARB:
2647 case WGL_PBUFFER_LOST_ARB:
2648 /* Mac PBuffers can't be lost */
2649 *piValue = GL_FALSE;
2651 case WGL_TEXTURE_FORMAT_ARB:
2652 if (pbuffer->no_texture)
2653 *piValue = WGL_NO_TEXTURE_ARB;
2654 else switch (internalFormat)
2657 *piValue = WGL_TEXTURE_RGBA_ARB;
2661 *piValue = WGL_TEXTURE_RGB_ARB;
2665 case WGL_TEXTURE_TARGET_ARB:
2666 if (pbuffer->no_texture)
2667 *piValue = WGL_NO_TEXTURE_ARB;
2668 else switch (target)
2670 case GL_TEXTURE_CUBE_MAP:
2671 *piValue = WGL_TEXTURE_CUBE_MAP_ARB;
2674 *piValue = WGL_TEXTURE_2D_ARB;
2676 case GL_TEXTURE_RECTANGLE:
2678 *piValue = WGL_TEXTURE_RECTANGLE_NV;
2682 case WGL_MIPMAP_TEXTURE_ARB:
2683 *piValue = (pbuffer->max_level > 0);
2685 case WGL_MIPMAP_LEVEL_ARB:
2686 *piValue = pbuffer->level;
2688 case WGL_CUBE_MAP_FACE_ARB:
2689 switch (pbuffer->face)
2691 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2693 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2695 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2696 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2698 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2699 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2701 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2702 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2704 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2705 *piValue = WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2707 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2708 *piValue = WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2713 WARN("invalid attribute 0x%x\n", iAttribute);
2714 SetLastError(ERROR_INVALID_DATA);
2722 /**********************************************************************
2723 * macdrv_wglReleasePbufferDCARB
2725 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2727 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer *pbuffer, HDC hdc)
2729 struct wgl_pbuffer *prev;
2731 TRACE("pbuffer %p hdc %p\n", pbuffer, hdc);
2733 EnterCriticalSection(&dc_pbuffers_section);
2735 prev = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
2738 if (prev != pbuffer)
2739 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc, pbuffer);
2740 CGLReleasePBuffer(prev->pbuffer);
2741 HeapFree(GetProcessHeap(), 0, prev);
2742 CFDictionaryRemoveValue(dc_pbuffers, hdc);
2746 LeaveCriticalSection(&dc_pbuffers_section);
2748 return hdc && DeleteDC(hdc);
2752 /**********************************************************************
2753 * macdrv_wglReleaseTexImageARB
2755 * WGL_ARB_render_texture: wglReleaseTexImageARB
2757 static BOOL macdrv_wglReleaseTexImageARB(struct wgl_pbuffer *pbuffer, int iBuffer)
2759 struct wgl_context *context = NtCurrentTeb()->glContext;
2762 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer, iBuffer);
2764 if (pbuffer->no_texture)
2766 SetLastError(ERROR_INVALID_OPERATION);
2770 err = CGLTexImagePBuffer(context->cglcontext, pbuffer->pbuffer, GL_NONE);
2771 if (err != kCGLNoError)
2773 WARN("CGLTexImagePBuffer failed with err %d %s\n", err, CGLErrorString(err));
2774 SetLastError(ERROR_INVALID_OPERATION);
2782 /**********************************************************************
2783 * macdrv_wglSetPbufferAttribARB
2785 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2787 static BOOL macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer *pbuffer, const int *piAttribList)
2789 struct wgl_context *context = NtCurrentTeb()->glContext;
2791 TRACE("pbuffer %p piAttribList %p\n", pbuffer, piAttribList);
2793 for ( ; piAttribList && *piAttribList; piAttribList += 2)
2795 int attr = piAttribList[0];
2796 int value = piAttribList[1];
2799 case WGL_MIPMAP_LEVEL_ARB:
2800 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value);
2801 pbuffer->level = value;
2803 case WGL_CUBE_MAP_FACE_ARB:
2806 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2807 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2808 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2810 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2811 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2812 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
2814 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2815 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2816 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
2818 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2819 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2820 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
2822 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2823 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2824 pbuffer->face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
2826 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2827 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2828 pbuffer->face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2831 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value);
2832 SetLastError(ERROR_INVALID_DATA);
2837 WARN("invalide attribute 0x%x\n", attr);
2838 SetLastError(ERROR_INVALID_DATA);
2843 if (context && context->draw_pbuffer == pbuffer)
2844 make_context_current(context, FALSE);
2850 /**********************************************************************
2851 * macdrv_wglSetPixelFormatWINE
2853 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2855 static BOOL macdrv_wglSetPixelFormatWINE(HDC hdc, int fmt)
2857 return set_pixel_format(hdc, fmt, TRUE);
2861 /**********************************************************************
2862 * macdrv_wglSwapIntervalEXT
2864 * WGL_EXT_swap_control: wglSwapIntervalEXT
2866 static BOOL macdrv_wglSwapIntervalEXT(int interval)
2868 struct wgl_context *context = NtCurrentTeb()->glContext;
2872 TRACE("interval %d\n", interval);
2876 SetLastError(ERROR_INVALID_DATA);
2884 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&value);
2885 if (err != kCGLNoError)
2887 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2888 err, CGLErrorString(err));
2889 SetLastError(ERROR_GEN_FAILURE);
2897 static void register_extension(const char *ext)
2899 if (gl_info.wglExtensions[0])
2900 strcat(gl_info.wglExtensions, " ");
2901 strcat(gl_info.wglExtensions, ext);
2903 TRACE("'%s'\n", ext);
2906 static void load_extensions(void)
2911 register_extension("WGL_ARB_extensions_string");
2912 opengl_funcs.ext.p_wglGetExtensionsStringARB = macdrv_wglGetExtensionsStringARB;
2914 register_extension("WGL_ARB_make_current_read");
2915 opengl_funcs.ext.p_wglGetCurrentReadDCARB = (void *)1; /* never called */
2916 opengl_funcs.ext.p_wglMakeContextCurrentARB = macdrv_wglMakeContextCurrentARB;
2918 register_extension("WGL_ARB_pixel_format");
2919 opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
2920 opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
2921 opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
2923 if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))
2925 register_extension("WGL_ARB_pixel_format_float");
2926 register_extension("WGL_ATI_pixel_format_float");
2929 if (gluCheckExtension((GLubyte*)"GL_ARB_multisample", (GLubyte*)gl_info.glExtensions))
2930 register_extension("WGL_ARB_multisample");
2932 if (gluCheckExtension((GLubyte*)"GL_ARB_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2933 register_extension("WGL_ARB_framebuffer_sRGB");
2935 if (gluCheckExtension((GLubyte*)"GL_APPLE_pixel_buffer", (GLubyte*)gl_info.glExtensions))
2937 register_extension("WGL_ARB_pbuffer");
2938 opengl_funcs.ext.p_wglCreatePbufferARB = macdrv_wglCreatePbufferARB;
2939 opengl_funcs.ext.p_wglDestroyPbufferARB = macdrv_wglDestroyPbufferARB;
2940 opengl_funcs.ext.p_wglGetPbufferDCARB = macdrv_wglGetPbufferDCARB;
2941 opengl_funcs.ext.p_wglQueryPbufferARB = macdrv_wglQueryPbufferARB;
2942 opengl_funcs.ext.p_wglReleasePbufferDCARB = macdrv_wglReleasePbufferDCARB;
2944 register_extension("WGL_ARB_render_texture");
2945 opengl_funcs.ext.p_wglBindTexImageARB = macdrv_wglBindTexImageARB;
2946 opengl_funcs.ext.p_wglReleaseTexImageARB = macdrv_wglReleaseTexImageARB;
2947 opengl_funcs.ext.p_wglSetPbufferAttribARB = macdrv_wglSetPbufferAttribARB;
2949 if (gluCheckExtension((GLubyte*)"GL_ARB_texture_rectangle", (GLubyte*)gl_info.glExtensions) ||
2950 gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", (GLubyte*)gl_info.glExtensions))
2951 register_extension("WGL_NV_render_texture_rectangle");
2955 WGL_ARB_create_context: wglCreateContextAttribsARB
2956 WGL_ARB_create_context_profile
2962 register_extension("WGL_EXT_extensions_string");
2963 opengl_funcs.ext.p_wglGetExtensionsStringEXT = macdrv_wglGetExtensionsStringEXT;
2965 register_extension("WGL_EXT_swap_control");
2966 opengl_funcs.ext.p_wglSwapIntervalEXT = macdrv_wglSwapIntervalEXT;
2967 opengl_funcs.ext.p_wglGetSwapIntervalEXT = macdrv_wglGetSwapIntervalEXT;
2969 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
2970 check for either, so register them separately. */
2971 if (gluCheckExtension((GLubyte*)"GL_EXT_framebuffer_sRGB", (GLubyte*)gl_info.glExtensions))
2972 register_extension("WGL_EXT_framebuffer_sRGB");
2974 if (gluCheckExtension((GLubyte*)"GL_EXT_packed_float", (GLubyte*)gl_info.glExtensions))
2975 register_extension("WGL_EXT_pixel_format_packed_float");
2978 * WINE-specific WGL Extensions
2981 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
2982 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
2984 register_extension("WGL_WINE_pixel_format_passthrough");
2985 opengl_funcs.ext.p_wglSetPixelFormatWINE = macdrv_wglSetPixelFormatWINE;
2989 static BOOL init_opengl(void)
2991 static int init_done;
2995 if (init_done) return (opengl_handle != NULL);
3000 dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
3003 WARN("CFDictionaryCreateMutable failed\n");
3007 opengl_handle = wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD, buffer, sizeof(buffer));
3010 ERR("Failed to load OpenGL: %s\n", buffer);
3011 ERR("OpenGL support is disabled.\n");
3015 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
3017 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym(opengl_handle, opengl_func_names[i], NULL, 0)))
3019 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names[i]);
3024 /* redirect some standard OpenGL functions */
3025 #define REDIRECT(func) \
3026 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3027 REDIRECT(glCopyPixels);
3028 REDIRECT(glReadPixels);
3029 REDIRECT(glViewport);
3032 /* redirect some OpenGL extension functions */
3033 #define REDIRECT(func) \
3034 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3035 REDIRECT(glCopyColorTable);
3038 if (!init_gl_info())
3042 if (!init_pixel_formats())
3048 wine_dlclose(opengl_handle, NULL, 0);
3049 opengl_handle = NULL;
3054 /***********************************************************************
3057 * Synchronize the Mac GL view position with the Windows child window
3060 void sync_gl_view(struct macdrv_win_data *data)
3064 TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view);
3066 if (!data->gl_view) return;
3068 if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect)))
3070 TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
3071 macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
3072 data->gl_rect = rect;
3077 static int get_dc_pixel_format(HDC hdc)
3082 if ((hwnd = WindowFromDC(hdc)))
3084 struct macdrv_win_data *data;
3086 if (!(data = get_win_data(hwnd)))
3088 FIXME("DC for window %p of other process: not implemented\n", hwnd);
3092 format = data->pixel_format;
3093 release_win_data(data);
3097 struct wgl_pbuffer *pbuffer;
3099 EnterCriticalSection(&dc_pbuffers_section);
3100 pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
3102 format = pbuffer->format;
3105 WARN("no window or pbuffer for DC %p\n", hdc);
3108 LeaveCriticalSection(&dc_pbuffers_section);
3115 /**********************************************************************
3118 static BOOL create_context(struct wgl_context *context, CGLContextObj share)
3120 const pixel_format *pf;
3121 CGLPixelFormatAttribute attribs[64];
3123 CGLPixelFormatObj pix;
3124 GLint virtualScreens;
3128 pf = get_pixel_format(context->format, TRUE /* non-displayable */);
3131 ERR("Invalid pixel format %d, expect problems!\n", context->format);
3132 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3136 attribs[n++] = kCGLPFAMinimumPolicy;
3137 attribs[n++] = kCGLPFAClosestPolicy;
3139 if (pf->accelerated)
3141 attribs[n++] = kCGLPFAAccelerated;
3142 attribs[n++] = kCGLPFANoRecovery;
3146 attribs[n++] = kCGLPFARendererID;
3147 attribs[n++] = kCGLRendererGenericFloatID;
3150 if (pf->double_buffer)
3151 attribs[n++] = kCGLPFADoubleBuffer;
3153 attribs[n++] = kCGLPFAAuxBuffers;
3154 attribs[n++] = pf->aux_buffers;
3156 attribs[n++] = kCGLPFAColorSize;
3157 attribs[n++] = color_modes[pf->color_mode].color_bits;
3158 attribs[n++] = kCGLPFAAlphaSize;
3159 attribs[n++] = color_modes[pf->color_mode].alpha_bits;
3160 if (color_modes[pf->color_mode].is_float)
3161 attribs[n++] = kCGLPFAColorFloat;
3163 attribs[n++] = kCGLPFADepthSize;
3164 attribs[n++] = pf->depth_bits;
3166 attribs[n++] = kCGLPFAStencilSize;
3167 attribs[n++] = pf->stencil_bits;
3170 attribs[n++] = kCGLPFAStereo;
3174 attribs[n++] = kCGLPFAAccumSize;
3175 attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
3179 attribs[n++] = kCGLPFAWindow;
3181 attribs[n++] = kCGLPFAPBuffer;
3183 if (pf->sample_buffers && pf->samples)
3185 attribs[n++] = kCGLPFASampleBuffers;
3186 attribs[n++] = pf->sample_buffers;
3187 attribs[n++] = kCGLPFASamples;
3188 attribs[n++] = pf->samples;
3191 if (pf->backing_store)
3192 attribs[n++] = kCGLPFABackingStore;
3196 err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
3197 if (err != kCGLNoError || !pix)
3199 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
3203 err = CGLCreateContext(pix, share, &context->cglcontext);
3204 CGLReleasePixelFormat(pix);
3205 if (err != kCGLNoError || !context->cglcontext)
3207 context->cglcontext = NULL;
3208 WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
3212 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3213 a context is 1. CGL contexts default to 0, so we need to set it. */
3215 err = CGLSetParameter(context->cglcontext, kCGLCPSwapInterval, (GLint*)&swap_interval);
3216 if (err != kCGLNoError)
3217 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err, CGLErrorString(err));
3219 context->context = macdrv_create_opengl_context(context->cglcontext);
3220 CGLReleaseContext(context->cglcontext);
3221 if (!context->context)
3223 WARN("macdrv_create_opengl_context() failed\n");
3227 TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
3233 /**********************************************************************
3234 * macdrv_wglDescribePixelFormat
3236 int macdrv_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr)
3238 int ret = nb_formats;
3239 const pixel_format *pf;
3240 const struct color_mode *mode;
3242 TRACE("hdc %p fmt %d size %u descr %p\n", hdc, fmt, size, descr);
3244 if (fmt <= 0 || fmt > ret) return ret;
3245 if (size < sizeof(*descr)) return 0;
3247 pf = &pixel_formats[fmt - 1];
3249 memset(descr, 0, sizeof(*descr));
3250 descr->nSize = sizeof(*descr);
3251 descr->nVersion = 1;
3253 descr->dwFlags = PFD_SUPPORT_OPENGL;
3254 if (pf->window) descr->dwFlags |= PFD_DRAW_TO_WINDOW;
3255 if (!pf->accelerated) descr->dwFlags |= PFD_GENERIC_FORMAT;
3256 if (pf->double_buffer) descr->dwFlags |= PFD_DOUBLEBUFFER;
3257 if (pf->stereo) descr->dwFlags |= PFD_STEREO;
3258 if (pf->backing_store) descr->dwFlags |= PFD_SWAP_COPY;
3260 descr->iPixelType = PFD_TYPE_RGBA;
3262 mode = &color_modes[pf->color_mode];
3263 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3264 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3265 R8G8B8A0 pixel format). If an app depends on that and expects that
3266 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3267 if (mode->alpha_bits)
3268 descr->cColorBits = mode->color_bits;
3270 descr->cColorBits = mode->bits_per_pixel;
3271 descr->cRedBits = mode->red_bits;
3272 descr->cRedShift = mode->red_shift;
3273 descr->cGreenBits = mode->green_bits;
3274 descr->cGreenShift = mode->green_shift;
3275 descr->cBlueBits = mode->blue_bits;
3276 descr->cBlueShift = mode->blue_shift;
3277 descr->cAlphaBits = mode->alpha_bits;
3278 descr->cAlphaShift = mode->alpha_shift;
3282 mode = &color_modes[pf->accum_mode - 1];
3283 descr->cAccumBits = mode->color_bits;
3284 descr->cAccumRedBits = mode->red_bits;
3285 descr->cAccumGreenBits = mode->green_bits;
3286 descr->cAccumBlueBits = mode->blue_bits;
3287 descr->cAccumAlphaBits = mode->alpha_bits;
3290 descr->cDepthBits = pf->depth_bits;
3291 descr->cStencilBits = pf->stencil_bits;
3292 descr->cAuxBuffers = pf->aux_buffers;
3293 descr->iLayerType = PFD_MAIN_PLANE;
3297 /***********************************************************************
3298 * macdrv_wglCopyContext
3300 static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *dst, UINT mask)
3304 TRACE("src %p dst %p mask %x\n", src, dst, mask);
3306 err = CGLCopyContext(src->cglcontext, dst->cglcontext, mask);
3307 if (err != kCGLNoError)
3308 WARN("CGLCopyContext() failed with err %d %s\n", err, CGLErrorString(err));
3309 return (err == kCGLNoError);
3312 /***********************************************************************
3313 * macdrv_wglCreateContext
3315 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
3318 struct wgl_context *context;
3320 TRACE("hdc %p\n", hdc);
3322 format = get_dc_pixel_format(hdc);
3324 if (!is_valid_pixel_format(format))
3326 ERR("Invalid pixel format %d, expect problems!\n", format);
3327 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
3331 if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
3333 context->format = format;
3334 if (!create_context(context, NULL))
3336 HeapFree(GetProcessHeap(), 0, context);
3343 /***********************************************************************
3344 * macdrv_wglDeleteContext
3346 static void macdrv_wglDeleteContext(struct wgl_context *context)
3348 TRACE("deleting context %p/%p/%p\n", context, context->context, context->cglcontext);
3349 macdrv_dispose_opengl_context(context->context);
3350 HeapFree(GetProcessHeap(), 0, context);
3353 /***********************************************************************
3354 * macdrv_wglGetPixelFormat
3356 static int macdrv_wglGetPixelFormat(HDC hdc)
3360 format = get_dc_pixel_format(hdc);
3362 if (!is_valid_pixel_format(format)) /* not set yet */
3364 else if (!is_displayable_pixel_format(format))
3366 /* Non-displayable formats can't be used with traditional WGL calls.
3367 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3371 TRACE(" hdc %p -> %d\n", hdc, format);
3375 /***********************************************************************
3376 * macdrv_wglGetProcAddress
3378 static PROC macdrv_wglGetProcAddress(const char *proc)
3382 if (!strncmp(proc, "wgl", 3)) return NULL;
3383 ret = wine_dlsym(opengl_handle, proc, NULL, 0);
3389 if (dladdr(ret, &info))
3390 TRACE("%s -> %s from %s\n", proc, info.dli_sname, info.dli_fname);
3392 TRACE("%s -> %p (no library info)\n", proc, ret);
3396 WARN("failed to find proc %s\n", debugstr_a(proc));
3400 /***********************************************************************
3401 * macdrv_wglMakeCurrent
3403 static BOOL macdrv_wglMakeCurrent(HDC hdc, struct wgl_context *context)
3405 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3406 (context ? context->cglcontext : NULL));
3408 return macdrv_wglMakeContextCurrentARB(hdc, hdc, context);
3411 /**********************************************************************
3412 * macdrv_wglSetPixelFormat
3414 static BOOL macdrv_wglSetPixelFormat(HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr)
3416 return set_pixel_format(hdc, fmt, FALSE);
3419 /***********************************************************************
3420 * macdrv_wglShareLists
3422 static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *dest)
3424 macdrv_opengl_context saved_context;
3425 CGLContextObj saved_cglcontext;
3427 TRACE("org %p dest %p\n", org, dest);
3429 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3430 * at context creation time but in case of WGL it is done using wglShareLists.
3432 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3433 * and when a program requests sharing we recreate the destination context if it hasn't been made
3434 * current or when it hasn't shared display lists before.
3437 if (dest->has_been_current)
3439 WARN("could not share display lists, the destination context has been current already\n");
3442 else if (dest->sharing)
3444 WARN("could not share display lists because dest has already shared lists before\n");
3448 /* Re-create the Mac context and share display lists */
3449 saved_context = dest->context;
3450 saved_cglcontext = dest->cglcontext;
3451 dest->context = NULL;
3452 dest->cglcontext = NULL;
3453 if (!create_context(dest, org->cglcontext))
3455 dest->context = saved_context;
3456 dest->cglcontext = saved_cglcontext;
3460 /* Implicitly disposes of saved_cglcontext. */
3461 macdrv_dispose_opengl_context(saved_context);
3463 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3464 dest, dest->context, dest->cglcontext, org, org->context, org->cglcontext);
3466 org->sharing = TRUE;
3467 dest->sharing = TRUE;
3472 /**********************************************************************
3473 * macdrv_wglSwapBuffers
3475 static BOOL macdrv_wglSwapBuffers(HDC hdc)
3477 struct wgl_context *context = NtCurrentTeb()->glContext;
3479 TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL),
3480 (context ? context->cglcontext : NULL));
3484 SetLastError(ERROR_INVALID_HANDLE);
3488 macdrv_flush_opengl_context(context->context);
3492 static struct opengl_funcs opengl_funcs =
3495 macdrv_wglCopyContext, /* p_wglCopyContext */
3496 macdrv_wglCreateContext, /* p_wglCreateContext */
3497 macdrv_wglDeleteContext, /* p_wglDeleteContext */
3498 macdrv_wglDescribePixelFormat, /* p_wglDescribePixelFormat */
3499 macdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
3500 macdrv_wglGetProcAddress, /* p_wglGetProcAddress */
3501 macdrv_wglMakeCurrent, /* p_wglMakeCurrent */
3502 macdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
3503 macdrv_wglShareLists, /* p_wglShareLists */
3504 macdrv_wglSwapBuffers, /* p_wglSwapBuffers */
3508 /**********************************************************************
3509 * macdrv_wine_get_wgl_driver
3511 struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version)
3513 if (version != WINE_WGL_DRIVER_VERSION)
3515 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION);
3519 if (!init_opengl()) return (void *)-1;
3521 return &opengl_funcs;