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
33 #include "wine/debug.h"
35 #include "wine/wgl_driver.h"
37 #define GL_SILENCE_DEPRECATION
40 #include <OpenGL/OpenGL.h>
41 #include <OpenGL/glu.h>
42 #include <OpenGL/CGLRenderers.h>
45 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
51 char wglExtensions
[4096];
53 GLint max_viewport_dims
[2];
55 unsigned int max_major
, max_minor
;
58 static struct gl_info gl_info
;
66 macdrv_opengl_context context
;
67 CGLContextObj cglcontext
;
69 macdrv_view draw_view
;
71 struct wgl_pbuffer
*draw_pbuffer
;
72 macdrv_view read_view
;
74 struct wgl_pbuffer
*read_pbuffer
;
75 BOOL has_been_current
;
77 LONG update_swap_interval
;
79 DWORD last_flush_time
;
83 static struct list context_list
= LIST_INIT(context_list
);
84 static pthread_mutex_t context_mutex
= PTHREAD_MUTEX_INITIALIZER
;
89 CGLPBufferObj pbuffer
;
97 static CFMutableDictionaryRef dc_pbuffers
;
98 static pthread_mutex_t dc_pbuffers_mutex
= PTHREAD_MUTEX_INITIALIZER
;
101 static struct opengl_funcs opengl_funcs
;
103 #define USE_GL_FUNC(name) #name,
104 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
108 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
110 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
111 static void (*pglFinish
)(void);
112 static void (*pglFlush
)(void);
113 static void (*pglFlushRenderAPPLE
)(void);
114 static const GLubyte
*(*pglGetString
)(GLenum name
);
115 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
116 GLenum format
, GLenum type
, void *pixels
);
117 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
123 GLint color_bits
; /* including alpha_bits */
124 int red_bits
, red_shift
;
125 int green_bits
, green_shift
;
126 int blue_bits
, blue_shift
;
127 GLint alpha_bits
, alpha_shift
;
132 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
133 observations of the behavior of Windows systems, but also subjective judgments
134 about what color formats are more "normal" than others.
136 On at least some Windows systems, integer color formats are listed before
137 floating-point formats. Within the integer formats, higher color bits were
138 usually listed before lower color bits, while for floating-point formats it
139 was the reverse. However, that leads D3D to select 64-bit integer formats in
140 preference to 32-bit formats when the latter would be sufficient. It seems
141 that a 32-bit format is much more likely to be normally used in that case.
143 Also, there are certain odd color formats supported on the Mac which seem like
144 they would be less appropriate than more common ones. For instance, the color
145 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
146 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
149 For two color formats which differ only in whether or not they have alpha bits,
150 we use the same ordering. pixel_format_comparator() gives alpha bits a
151 different weight than color formats.
153 static const struct color_mode color_modes
[] = {
154 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
155 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
156 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
157 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
158 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
159 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
160 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
161 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
162 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
163 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
164 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
165 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
166 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
167 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
168 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
169 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
170 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
171 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
172 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
173 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
174 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
175 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
176 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
177 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
181 static const struct {
184 } depth_stencil_modes
[] = {
212 GLint max_aux_buffers
;
213 GLint max_sample_buffers
;
220 } renderer_properties
;
224 unsigned int window
:1;
225 unsigned int pbuffer
:1;
226 unsigned int accelerated
:1;
227 unsigned int color_mode
:5; /* index into color_modes table */
228 unsigned int aux_buffers
:3;
229 unsigned int depth_bits
:8;
230 unsigned int stencil_bits
:8;
231 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
232 unsigned int double_buffer
:1;
233 unsigned int stereo
:1;
234 unsigned int sample_buffers
:1;
235 unsigned int samples
:5;
236 unsigned int backing_store
:1;
244 } pixel_format_or_code
;
245 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
248 static pixel_format
*pixel_formats
;
249 static int nb_formats
, nb_displayable_formats
;
252 static void *opengl_handle
;
255 static const char* debugstr_attrib(int attrib
, int value
)
257 static const struct {
261 #define ATTRIB(a) { a, #a }
262 ATTRIB(WGL_ACCELERATION_ARB
),
263 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
264 ATTRIB(WGL_ACCUM_BITS_ARB
),
265 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
266 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
267 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
268 ATTRIB(WGL_ALPHA_BITS_ARB
),
269 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
270 ATTRIB(WGL_AUX_BUFFERS_ARB
),
271 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
272 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
273 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
274 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
275 ATTRIB(WGL_BLUE_BITS_ARB
),
276 ATTRIB(WGL_BLUE_SHIFT_ARB
),
277 ATTRIB(WGL_COLOR_BITS_ARB
),
278 ATTRIB(WGL_DEPTH_BITS_ARB
),
279 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
280 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
281 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
282 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
283 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
284 ATTRIB(WGL_GREEN_BITS_ARB
),
285 ATTRIB(WGL_GREEN_SHIFT_ARB
),
286 ATTRIB(WGL_NEED_PALETTE_ARB
),
287 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
288 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
289 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
290 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
291 ATTRIB(WGL_PIXEL_TYPE_ARB
),
292 ATTRIB(WGL_RED_BITS_ARB
),
293 ATTRIB(WGL_RED_SHIFT_ARB
),
294 ATTRIB(WGL_RENDERER_ID_WINE
),
295 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
296 ATTRIB(WGL_SAMPLES_ARB
),
297 ATTRIB(WGL_SHARE_ACCUM_ARB
),
298 ATTRIB(WGL_SHARE_DEPTH_ARB
),
299 ATTRIB(WGL_SHARE_STENCIL_ARB
),
300 ATTRIB(WGL_STENCIL_BITS_ARB
),
301 ATTRIB(WGL_STEREO_ARB
),
302 ATTRIB(WGL_SUPPORT_GDI_ARB
),
303 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
304 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
305 ATTRIB(WGL_SWAP_METHOD_ARB
),
306 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
307 ATTRIB(WGL_TRANSPARENT_ARB
),
308 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
309 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
310 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
311 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
315 const char *attrib_name
= NULL
;
316 const char *value_name
= NULL
;
318 for (i
= 0; i
< ARRAY_SIZE(attrib_names
); i
++)
320 if (attrib_names
[i
].attrib
== attrib
)
322 attrib_name
= attrib_names
[i
].name
;
328 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
332 case WGL_ACCELERATION_ARB
:
335 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
336 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
337 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
340 case WGL_PIXEL_TYPE_ARB
:
343 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
344 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
345 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
346 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
349 case WGL_SWAP_METHOD_ARB
:
352 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
353 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
354 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
360 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
362 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
366 /**********************************************************************
367 * active_displays_mask
369 static CGOpenGLDisplayMask
active_displays_mask(void)
372 CGDirectDisplayID displays
[32];
374 CGOpenGLDisplayMask mask
;
376 err
= CGGetActiveDisplayList(ARRAY_SIZE(displays
), displays
, &count
);
377 if (err
!= kCGErrorSuccess
)
379 displays
[0] = CGMainDisplayID();
384 for (i
= 0; i
< count
; i
++)
385 mask
|= CGDisplayIDToOpenGLDisplayMask(displays
[i
]);
391 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
392 CGLRendererProperty property
, GLint
*value
)
394 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
395 if (err
!= kCGLNoError
)
396 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
397 return (err
== kCGLNoError
);
401 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
405 memset(properties
, 0, sizeof(*properties
));
407 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
408 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
410 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
411 properties
->buffer_modes
= value
;
413 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
414 properties
->color_modes
= value
;
416 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
417 properties
->accum_modes
= value
;
419 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
420 properties
->depth_modes
= value
;
422 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
423 properties
->stencil_modes
= value
;
425 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
426 properties
->max_aux_buffers
= value
;
428 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
429 properties
->max_sample_buffers
= value
;
431 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
432 properties
->max_samples
= value
;
434 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
435 properties
->offscreen
= (value
!= 0);
437 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
438 properties
->accelerated
= (value
!= 0);
440 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
441 properties
->backing_store
= (value
!= 0);
443 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
444 properties
->window
= (value
!= 0);
446 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
447 properties
->online
= (value
!= 0);
451 static void dump_renderer(const renderer_properties
* renderer
)
455 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
456 TRACE("Buffer modes:\n");
457 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
458 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
459 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
460 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
462 TRACE("Color buffer modes:\n");
463 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
465 if (renderer
->color_modes
& color_modes
[i
].mode
)
467 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
468 if (color_modes
[i
].is_float
)
474 TRACE("Accumulation buffer sizes: { ");
475 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
477 if (renderer
->accum_modes
& color_modes
[i
].mode
)
478 TRACE("%d, ", color_modes
[i
].color_bits
);
482 TRACE("Depth buffer sizes: { ");
483 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
485 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
486 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
490 TRACE("Stencil buffer sizes: { ");
491 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
493 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
494 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
498 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
499 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
500 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
501 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
502 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
503 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
504 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
505 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
509 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
511 pixel_format_or_code pfc
;
514 pfc
.format
= *format
;
519 static inline pixel_format
pixel_format_for_code(UInt64 code
)
521 pixel_format_or_code pfc
;
528 static const char *debugstr_pf(const pixel_format
*pf
)
530 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",
534 color_modes
[pf
->color_mode
].color_bits
,
535 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
536 color_modes
[pf
->color_mode
].alpha_bits
,
539 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
546 code_for_pixel_format(pf
));
550 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
555 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
557 if ((modes
& color_modes
[i
].mode
) &&
558 color_modes
[i
].color_bits
>= color_size
&&
559 color_modes
[i
].alpha_bits
>= alpha_size
&&
560 !color_modes
[i
].is_float
== !color_float
)
562 if (best
< 0) /* no existing best choice */
564 else if (color_modes
[i
].color_bits
== color_size
&&
565 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
567 /* prefer it over a best which isn't exact or which has a higher bpp */
568 if (color_modes
[best
].color_bits
!= color_size
||
569 color_modes
[best
].alpha_bits
!= alpha_size
||
570 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
573 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
574 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
575 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
582 /* Couldn't find a match. Return first one that renderer supports. */
583 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
585 if (modes
& color_modes
[i
].mode
)
594 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
599 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
601 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
603 /* Prefer the fewest color bits, then prefer more alpha bits, then
604 prefer more bits per pixel. */
607 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
609 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
611 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
613 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
614 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
622 /* Couldn't find a match. Return last one that renderer supports. */
623 for (i
= ARRAY_SIZE(color_modes
) - 1; i
>= 0; i
--)
625 if (modes
& color_modes
[i
].mode
)
634 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
635 CFMutableSetRef pixel_format_set
)
637 CGLPixelFormatAttribute attribs
[64] = {
638 kCGLPFAMinimumPolicy
,
639 kCGLPFAClosestPolicy
,
640 kCGLPFARendererID
, renderer
.renderer_id
,
641 kCGLPFASingleRenderer
,
643 int n
= 5, n_stack
[16], n_stack_idx
= -1;
644 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
645 new_pixel_formats
= 0;
646 pixel_format request
;
647 unsigned int double_buffer
;
648 unsigned int accelerated
= renderer
.accelerated
;
652 attribs
[n
++] = kCGLPFAAccelerated
;
653 attribs
[n
++] = kCGLPFANoRecovery
;
655 else if (!allow_software_rendering
)
657 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
661 n_stack
[++n_stack_idx
] = n
;
662 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
666 n
= n_stack
[n_stack_idx
];
668 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
669 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
673 attribs
[n
++] = kCGLPFADoubleBuffer
;
674 memset(&request
, 0, sizeof(request
));
675 request
.accelerated
= accelerated
;
676 request
.double_buffer
= double_buffer
;
678 /* Don't bother with in-between aux buffers values: either 0 or max. */
679 n_stack
[++n_stack_idx
] = n
;
680 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
682 unsigned int color_mode
;
684 n
= n_stack
[n_stack_idx
];
686 attribs
[n
++] = kCGLPFAAuxBuffers
;
688 request
.aux_buffers
= aux
;
690 n_stack
[++n_stack_idx
] = n
;
691 for (color_mode
= 0; color_mode
< ARRAY_SIZE(color_modes
); color_mode
++)
693 unsigned int depth_mode
;
695 n
= n_stack
[n_stack_idx
];
697 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
700 attribs
[n
++] = kCGLPFAColorSize
;
701 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
702 attribs
[n
++] = kCGLPFAAlphaSize
;
703 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
704 if (color_modes
[color_mode
].is_float
)
705 attribs
[n
++] = kCGLPFAColorFloat
;
706 request
.color_mode
= color_mode
;
708 n_stack
[++n_stack_idx
] = n
;
709 for (depth_mode
= 0; depth_mode
< ARRAY_SIZE(depth_stencil_modes
); depth_mode
++)
711 unsigned int stencil_mode
;
713 n
= n_stack
[n_stack_idx
];
715 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
718 attribs
[n
++] = kCGLPFADepthSize
;
719 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
720 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
722 n_stack
[++n_stack_idx
] = n
;
723 for (stencil_mode
= 0; stencil_mode
< ARRAY_SIZE(depth_stencil_modes
); stencil_mode
++)
727 n
= n_stack
[n_stack_idx
];
729 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
731 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 &&
732 depth_stencil_modes
[depth_mode
].bits
!= 32 && stencil_mode
> 0)
735 attribs
[n
++] = kCGLPFAStencilSize
;
736 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
737 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
739 /* FIXME: Could trim search space a bit here depending on GPU.
740 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
741 n_stack
[++n_stack_idx
] = n
;
742 for (stereo
= 0; stereo
<= 1; stereo
++)
746 n
= n_stack
[n_stack_idx
];
748 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
749 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
753 attribs
[n
++] = kCGLPFAStereo
;
754 request
.stereo
= stereo
;
756 /* Starts at -1 for a 0 accum size */
757 n_stack
[++n_stack_idx
] = n
;
758 for (accum_mode
= -1; accum_mode
< (int) ARRAY_SIZE(color_modes
); accum_mode
++)
760 unsigned int target_pass
;
762 n
= n_stack
[n_stack_idx
];
766 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
769 attribs
[n
++] = kCGLPFAAccumSize
;
770 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
771 request
.accum_mode
= accum_mode
+ 1;
774 request
.accum_mode
= 0;
776 /* Targets to request are:
777 accelerated: window OR window + pbuffer
778 software: window + pbuffer */
779 n_stack
[++n_stack_idx
] = n
;
780 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
782 unsigned int samples
, max_samples
;
784 n
= n_stack
[n_stack_idx
];
786 attribs
[n
++] = kCGLPFAWindow
;
789 if (!accelerated
|| target_pass
> 0)
791 attribs
[n
++] = kCGLPFAPBuffer
;
797 /* FIXME: Could trim search space a bit here depending on GPU.
798 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
799 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
800 n_stack
[++n_stack_idx
] = n
;
801 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
802 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
804 unsigned int backing_store
, min_backing_store
, max_backing_store
;
806 n
= n_stack
[n_stack_idx
];
810 attribs
[n
++] = kCGLPFASampleBuffers
;
811 attribs
[n
++] = renderer
.max_sample_buffers
;
812 attribs
[n
++] = kCGLPFASamples
;
813 attribs
[n
++] = samples
;
814 request
.sample_buffers
= renderer
.max_sample_buffers
;
815 request
.samples
= samples
;
818 request
.sample_buffers
= request
.samples
= 0;
820 if (renderer
.backing_store
&& double_buffer
)
822 /* The software renderer seems to always preserve the backing store, whether
823 we ask for it or not. So don't bother not asking for it. */
824 min_backing_store
= accelerated
? 0 : 1;
825 max_backing_store
= 1;
828 min_backing_store
= max_backing_store
= 0;
829 n_stack
[++n_stack_idx
] = n
;
830 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
832 CGLPixelFormatObj pix
;
833 GLint virtualScreens
;
836 n
= n_stack
[n_stack_idx
];
839 attribs
[n
++] = kCGLPFABackingStore
;
840 request
.backing_store
= backing_store
;
844 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
845 if (err
== kCGLNoError
&& pix
)
848 GLint value
, color_size
, alpha_size
, color_float
;
850 CFNumberRef code_object
;
853 memset(&pf
, 0, sizeof(pf
));
855 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
856 pf
.accelerated
= value
;
857 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
858 pf
.aux_buffers
= value
;
859 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
860 pf
.depth_bits
= value
;
861 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
862 pf
.double_buffer
= value
;
863 if (pf
.double_buffer
&&
864 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
865 pf
.backing_store
= value
;
866 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
868 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
869 pf
.sample_buffers
= value
;
870 if (pf
.sample_buffers
&&
871 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
873 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
874 pf
.stencil_bits
= value
;
875 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
877 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
880 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
882 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
884 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
886 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
888 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
889 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
891 CGLReleasePixelFormat(pix
);
893 pf_code
= code_for_pixel_format(&pf
);
895 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
896 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
897 dupe_pixel_formats
++;
900 CFSetAddValue(pixel_format_set
, code_object
);
901 CFArrayAppendValue(pixel_format_array
, code_object
);
904 CFRelease(code_object
);
906 if (pf_code
== code_for_pixel_format(&request
))
907 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
910 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
911 dupe
? " (duplicate)" : "");
916 failed_pixel_formats
++;
917 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
920 tried_pixel_formats
++;
952 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
953 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
954 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
955 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
959 /* The docs for WGL_ARB_pixel_format say:
960 Indices are assigned to pixel formats in the following order:
961 1. Accelerated pixel formats that are displayable
962 2. Accelerated pixel formats that are displayable and which have
964 3. Generic pixel formats
965 4. Accelerated pixel formats that are non displayable
967 static int pixel_format_category(pixel_format pf
)
969 /* non-displayable */
973 /* non-accelerated a.k.a. software a.k.a. generic */
977 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
978 if (color_modes
[pf
.color_mode
].is_float
)
981 /* accelerated, displayable, no extended attributes */
986 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
988 CFNumberRef number1
= val1
;
989 CFNumberRef number2
= val2
;
991 pixel_format pf1
, pf2
;
992 int category1
, category2
;
994 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
995 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
996 pf1
= pixel_format_for_code(code1
);
997 pf2
= pixel_format_for_code(code2
);
998 category1
= pixel_format_category(pf1
);
999 category2
= pixel_format_category(pf2
);
1001 if (category1
< category2
)
1002 return kCFCompareLessThan
;
1003 if (category1
> category2
)
1004 return kCFCompareGreaterThan
;
1006 /* Within a category, sort the "best" formats toward the front since that's
1007 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1008 matches at least one Windows 7 machine's behavior.
1010 /* Accelerated before unaccelerated. */
1011 if (pf1
.accelerated
&& !pf2
.accelerated
)
1012 return kCFCompareLessThan
;
1013 if (!pf1
.accelerated
&& pf2
.accelerated
)
1014 return kCFCompareGreaterThan
;
1016 /* Explicit color mode ordering. */
1017 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1018 return kCFCompareLessThan
;
1019 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1020 return kCFCompareGreaterThan
;
1022 /* Non-pbuffer-capable before pbuffer-capable. */
1023 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1024 return kCFCompareLessThan
;
1025 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1026 return kCFCompareGreaterThan
;
1028 /* Fewer samples before more samples. */
1029 if (pf1
.samples
< pf2
.samples
)
1030 return kCFCompareLessThan
;
1031 if (pf1
.samples
> pf2
.samples
)
1032 return kCFCompareGreaterThan
;
1034 /* Monoscopic before stereoscopic. (This is a guess.) */
1035 if (!pf1
.stereo
&& pf2
.stereo
)
1036 return kCFCompareLessThan
;
1037 if (pf1
.stereo
&& !pf2
.stereo
)
1038 return kCFCompareGreaterThan
;
1040 /* Single buffered before double buffered. */
1041 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1042 return kCFCompareLessThan
;
1043 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1044 return kCFCompareGreaterThan
;
1046 /* Possibly-optimized double buffering before backing-store-preserving
1047 double buffering. */
1048 if (!pf1
.backing_store
&& pf2
.backing_store
)
1049 return kCFCompareLessThan
;
1050 if (pf1
.backing_store
&& !pf2
.backing_store
)
1051 return kCFCompareGreaterThan
;
1053 /* Bigger depth buffer before smaller depth buffer. */
1054 if (pf1
.depth_bits
> pf2
.depth_bits
)
1055 return kCFCompareLessThan
;
1056 if (pf1
.depth_bits
< pf2
.depth_bits
)
1057 return kCFCompareGreaterThan
;
1059 /* Smaller stencil buffer before bigger stencil buffer. */
1060 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1061 return kCFCompareLessThan
;
1062 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1063 return kCFCompareGreaterThan
;
1065 /* Smaller alpha bits before larger alpha bits. */
1066 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1067 return kCFCompareLessThan
;
1068 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1069 return kCFCompareGreaterThan
;
1071 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1076 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1077 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1078 return kCFCompareLessThan
;
1079 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1080 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1081 return kCFCompareGreaterThan
;
1083 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1084 return kCFCompareLessThan
;
1085 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1086 return kCFCompareGreaterThan
;
1088 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1089 return kCFCompareLessThan
;
1090 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1091 return kCFCompareGreaterThan
;
1094 return kCFCompareGreaterThan
;
1096 else if (pf2
.accum_mode
)
1097 return kCFCompareLessThan
;
1099 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1100 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1101 return kCFCompareLessThan
;
1102 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1103 return kCFCompareGreaterThan
;
1105 /* If we get here, arbitrarily sort based on code. */
1107 return kCFCompareLessThan
;
1109 return kCFCompareGreaterThan
;
1110 return kCFCompareEqualTo
;
1114 static BOOL
init_pixel_formats(void)
1117 CGLRendererInfoObj renderer_info
;
1118 GLint rendererCount
;
1120 CFMutableSetRef pixel_format_set
;
1121 CFMutableArrayRef pixel_format_array
;
1127 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1130 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1134 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1135 if (!pixel_format_set
)
1137 WARN("CFSetCreateMutable failed\n");
1138 CGLDestroyRendererInfo(renderer_info
);
1142 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1143 if (!pixel_format_array
)
1145 WARN("CFArrayCreateMutable failed\n");
1146 CFRelease(pixel_format_set
);
1147 CGLDestroyRendererInfo(renderer_info
);
1151 for (i
= 0; i
< rendererCount
; i
++)
1153 renderer_properties renderer
;
1155 get_renderer_properties(renderer_info
, i
, &renderer
);
1158 TRACE("renderer_properties %d:\n", i
);
1159 dump_renderer(&renderer
);
1162 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1165 CFRelease(pixel_format_set
);
1166 CGLDestroyRendererInfo(renderer_info
);
1168 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1171 pixel_formats
= malloc(range
.length
* sizeof(*pixel_formats
));
1174 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1175 for (i
= 0; i
< range
.length
; i
++)
1177 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1180 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1181 pixel_formats
[i
] = pixel_format_for_code(code
);
1182 if (pixel_formats
[i
].window
)
1183 nb_displayable_formats
++;
1186 nb_formats
= range
.length
;
1187 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1191 WARN("failed to allocate pixel format list\n");
1194 WARN("got no pixel formats\n");
1196 CFRelease(pixel_format_array
);
1201 static inline BOOL
is_valid_pixel_format(int format
)
1203 return format
> 0 && format
<= nb_formats
;
1207 static inline BOOL
is_displayable_pixel_format(int format
)
1209 return format
> 0 && format
<= nb_displayable_formats
;
1213 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1215 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1216 * format in case of probing the number of pixel formats.
1218 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1220 TRACE("Returning format %d\n", format
);
1221 return &pixel_formats
[format
- 1];
1227 static BOOL
init_gl_info(void)
1229 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1230 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1232 CGDirectDisplayID display
= CGMainDisplayID();
1233 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1234 CGLPixelFormatAttribute attribs
[] = {
1235 kCGLPFADisplayMask
, displayMask
,
1238 CGLPixelFormatAttribute core_attribs
[] =
1240 kCGLPFADisplayMask
, displayMask
,
1242 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1245 CGLPixelFormatObj pix
;
1246 GLint virtualScreens
;
1248 CGLContextObj context
;
1249 CGLContextObj old_context
= CGLGetCurrentContext();
1253 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1254 if (err
!= kCGLNoError
|| !pix
)
1256 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1260 err
= CGLCreateContext(pix
, NULL
, &context
);
1261 CGLReleasePixelFormat(pix
);
1262 if (err
!= kCGLNoError
|| !context
)
1264 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1268 err
= CGLSetCurrentContext(context
);
1269 if (err
!= kCGLNoError
)
1271 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1272 CGLReleaseContext(context
);
1276 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1277 length
= strlen(str
) + sizeof(legacy_extensions
);
1279 length
+= strlen(legacy_ext_swap_control
);
1280 gl_info
.glExtensions
= malloc(length
);
1281 strcpy(gl_info
.glExtensions
, str
);
1282 strcat(gl_info
.glExtensions
, legacy_extensions
);
1284 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1286 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1288 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1289 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1290 TRACE("GL version : %s\n", str
);
1291 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1293 CGLSetCurrentContext(old_context
);
1294 CGLReleaseContext(context
);
1296 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1297 if (err
!= kCGLNoError
|| !pix
)
1299 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1300 err
, CGLErrorString(err
));
1304 err
= CGLCreateContext(pix
, NULL
, &context
);
1305 CGLReleasePixelFormat(pix
);
1306 if (err
!= kCGLNoError
|| !context
)
1308 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1309 err
, CGLErrorString(err
));
1313 err
= CGLSetCurrentContext(context
);
1314 if (err
!= kCGLNoError
)
1316 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1317 err
, CGLErrorString(err
));
1318 CGLReleaseContext(context
);
1322 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1323 TRACE("Core context GL version: %s\n", str
);
1324 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1325 CGLSetCurrentContext(old_context
);
1326 CGLReleaseContext(context
);
1332 static int get_dc_pixel_format(HDC hdc
)
1337 if ((hwnd
= NtUserWindowFromDC(hdc
)))
1339 struct macdrv_win_data
*data
;
1341 if (!(data
= get_win_data(hwnd
)))
1343 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1347 format
= data
->pixel_format
;
1348 release_win_data(data
);
1352 struct wgl_pbuffer
*pbuffer
;
1354 pthread_mutex_lock(&dc_pbuffers_mutex
);
1355 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1357 format
= pbuffer
->format
;
1360 WARN("no window or pbuffer for DC %p\n", hdc
);
1363 pthread_mutex_unlock(&dc_pbuffers_mutex
);
1370 /**********************************************************************
1373 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1375 const pixel_format
*pf
;
1376 CGLPixelFormatAttribute attribs
[64];
1378 CGLPixelFormatObj pix
;
1379 GLint virtualScreens
;
1381 BOOL core
= major
>= 3;
1383 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1386 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1387 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
1391 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1392 attribs
[n
++] = kCGLPFAClosestPolicy
;
1394 if (context
->renderer_id
)
1396 attribs
[n
++] = kCGLPFARendererID
;
1397 attribs
[n
++] = context
->renderer_id
;
1398 attribs
[n
++] = kCGLPFASingleRenderer
;
1399 attribs
[n
++] = kCGLPFANoRecovery
;
1402 if (pf
->accelerated
)
1404 attribs
[n
++] = kCGLPFAAccelerated
;
1405 attribs
[n
++] = kCGLPFANoRecovery
;
1409 attribs
[n
++] = kCGLPFARendererID
;
1410 attribs
[n
++] = kCGLRendererGenericFloatID
;
1413 if (pf
->double_buffer
)
1414 attribs
[n
++] = kCGLPFADoubleBuffer
;
1418 attribs
[n
++] = kCGLPFAAuxBuffers
;
1419 attribs
[n
++] = pf
->aux_buffers
;
1422 attribs
[n
++] = kCGLPFAColorSize
;
1423 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1424 attribs
[n
++] = kCGLPFAAlphaSize
;
1425 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1426 if (color_modes
[pf
->color_mode
].is_float
)
1427 attribs
[n
++] = kCGLPFAColorFloat
;
1429 attribs
[n
++] = kCGLPFADepthSize
;
1430 attribs
[n
++] = pf
->depth_bits
;
1432 attribs
[n
++] = kCGLPFAStencilSize
;
1433 attribs
[n
++] = pf
->stencil_bits
;
1436 attribs
[n
++] = kCGLPFAStereo
;
1438 if (pf
->accum_mode
&& !core
)
1440 attribs
[n
++] = kCGLPFAAccumSize
;
1441 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1444 if (pf
->pbuffer
&& !core
)
1445 attribs
[n
++] = kCGLPFAPBuffer
;
1447 if (pf
->sample_buffers
&& pf
->samples
)
1449 attribs
[n
++] = kCGLPFASampleBuffers
;
1450 attribs
[n
++] = pf
->sample_buffers
;
1451 attribs
[n
++] = kCGLPFASamples
;
1452 attribs
[n
++] = pf
->samples
;
1455 if (pf
->backing_store
)
1456 attribs
[n
++] = kCGLPFABackingStore
;
1460 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1461 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1463 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1465 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1467 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1473 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1474 if (err
!= kCGLNoError
|| !pix
)
1476 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1477 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
1481 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1482 CGLReleasePixelFormat(pix
);
1483 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1485 context
->cglcontext
= NULL
;
1486 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1487 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
1491 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1494 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1495 if (err
!= kCGLNoError
)
1496 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1498 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1501 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1502 if (err
!= kCGLNoError
)
1503 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1506 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1507 CGLReleaseContext(context
->cglcontext
);
1508 if (!context
->context
)
1510 WARN("macdrv_create_opengl_context() failed\n");
1511 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
1514 context
->major
= major
;
1516 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1518 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1524 /**********************************************************************
1527 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1529 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1531 struct macdrv_win_data
*data
;
1532 const pixel_format
*pf
;
1533 HWND hwnd
= NtUserWindowFromDC(hdc
);
1536 TRACE("hdc %p format %d\n", hdc
, fmt
);
1538 if (!hwnd
|| hwnd
== NtUserGetDesktopWindow())
1540 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1544 if (!(data
= get_win_data(hwnd
)))
1546 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1550 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1552 ret
= (data
->pixel_format
== fmt
);
1556 /* Check if fmt is in our list of supported formats to see if it is supported. */
1557 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1560 ERR("Invalid pixel format: %d\n", fmt
);
1566 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1570 data
->pixel_format
= fmt
;
1572 TRACE("pixel format:\n");
1573 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1574 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1575 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1576 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1577 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1578 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1579 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1580 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1581 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1582 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1583 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1584 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1585 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1586 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1590 release_win_data(data
);
1591 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) NtUserSetWindowPixelFormat(hwnd
, fmt
);
1596 /**********************************************************************
1597 * mark_contexts_for_moved_view
1599 static void mark_contexts_for_moved_view(macdrv_view view
)
1601 struct wgl_context
*context
;
1603 pthread_mutex_lock(&context_mutex
);
1604 LIST_FOR_EACH_ENTRY(context
, &context_list
, struct wgl_context
, entry
)
1606 if (context
->draw_view
== view
)
1607 InterlockedExchange(&context
->view_moved
, TRUE
);
1609 pthread_mutex_unlock(&context_mutex
);
1613 /**********************************************************************
1616 static BOOL
sync_context_rect(struct wgl_context
*context
)
1619 if (InterlockedCompareExchange(&context
->view_moved
, FALSE
, TRUE
))
1621 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1623 if (data
&& data
->client_cocoa_view
== context
->draw_view
)
1625 RECT rect
= data
->client_rect
;
1626 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1627 if (!EqualRect(&context
->draw_rect
, &rect
))
1629 context
->draw_rect
= rect
;
1633 release_win_data(data
);
1639 /**********************************************************************
1640 * make_context_current
1642 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1646 struct wgl_pbuffer
*pbuffer
;
1650 view
= context
->read_view
;
1651 view_rect
= context
->read_rect
;
1652 pbuffer
= context
->read_pbuffer
;
1656 sync_context_rect(context
);
1658 view
= context
->draw_view
;
1659 view_rect
= context
->draw_rect
;
1660 pbuffer
= context
->draw_pbuffer
;
1663 if (view
|| !pbuffer
)
1664 macdrv_make_context_current(context
->context
, view
, cgrect_from_rect(view_rect
));
1669 if (CGLIsEnabled(context
->cglcontext
, kCGLCESurfaceBackingSize
, &enabled
) == kCGLNoError
&& enabled
)
1670 CGLDisable(context
->cglcontext
, kCGLCESurfaceBackingSize
);
1671 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1673 CGLSetCurrentContext(context
->cglcontext
);
1678 /**********************************************************************
1681 static void sync_context(struct wgl_context
*context
)
1683 if (sync_context_rect(context
))
1684 make_context_current(context
, FALSE
);
1688 /**********************************************************************
1691 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1695 /* In theory, for single-buffered contexts, there's no such thing as a swap
1696 so the swap interval shouldn't matter. But OS X will synchronize flushes
1697 of single-buffered contexts if the interval is set to non-zero. */
1698 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1701 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1702 if (err
!= kCGLNoError
)
1703 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1705 return err
== kCGLNoError
;
1709 /**********************************************************************
1710 * sync_swap_interval
1712 static void sync_swap_interval(struct wgl_context
*context
)
1714 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1720 else if (context
->draw_hwnd
)
1722 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1725 interval
= data
->swap_interval
;
1726 release_win_data(data
);
1728 else /* window was destroyed? */
1734 set_swap_interval(context
, interval
);
1739 /**********************************************************************
1740 * get_iokit_display_property
1742 static BOOL
get_iokit_display_property(CGLRendererInfoObj renderer_info
, GLint renderer
, CFStringRef property
, GLuint
* value
)
1748 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, &accelerated
) || !accelerated
)
1750 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1754 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPDisplayMask
, &display_mask
))
1756 WARN("failed to get kCGLRPDisplayMask\n");
1760 for (i
= 0; i
< sizeof(GLint
) * 8; i
++)
1762 GLint this_display_mask
= (GLint
)(1U << i
);
1763 if (this_display_mask
& display_mask
)
1765 CGDirectDisplayID display_id
= CGOpenGLDisplayMaskToDisplayID(this_display_mask
);
1766 io_service_t service
;
1768 uint32_t prop_value
;
1772 service
= CGDisplayIOServicePort(display_id
);
1775 WARN("CGDisplayIOServicePort(%u) failed\n", display_id
);
1779 data
= IORegistryEntrySearchCFProperty(service
, kIOServicePlane
, property
, NULL
,
1780 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1783 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property
), display_id
);
1786 if (CFGetTypeID(data
) != CFDataGetTypeID())
1788 WARN("property %s is not a data object: %s\n", debugstr_cf(property
), debugstr_cf(data
));
1792 if (CFDataGetLength(data
) != sizeof(prop_value
))
1794 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property
), display_id
,
1795 (unsigned long long)CFDataGetLength(data
));
1800 CFDataGetBytes(data
, CFRangeMake(0, sizeof(prop_value
)), (UInt8
*)&prop_value
);
1802 *value
= prop_value
;
1811 /**********************************************************************
1812 * create_pixel_format_for_renderer
1814 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1815 * responsible for releasing the pixel format object.
1817 static CGLPixelFormatObj
create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info
, GLint renderer
, BOOL core
)
1820 CGLPixelFormatAttribute attrs
[] = {
1821 kCGLPFARendererID
, 0,
1822 kCGLPFASingleRenderer
,
1823 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1827 CGLPixelFormatObj pixel_format
;
1828 GLint virtual_screens
;
1832 attrs
[3] = kCGLPFAOpenGLProfile
;
1833 attrs
[4] = (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
;
1836 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
1839 attrs
[1] = renderer_id
;
1840 err
= CGLChoosePixelFormat(attrs
, &pixel_format
, &virtual_screens
);
1841 if (err
!= kCGLNoError
)
1842 pixel_format
= NULL
;
1843 return pixel_format
;
1847 /**********************************************************************
1848 * map_renderer_index
1850 * We can't create pixel formats for all renderers listed. For example,
1851 * in a dual-GPU system, the integrated GPU is typically unavailable
1852 * when the discrete GPU is active.
1854 * This function conceptually creates a list of "good" renderers from the
1855 * list of all renderers. It treats the input "renderer" parameter as an
1856 * index into that list of good renderers and returns the corresponding
1857 * index into the list of all renderers.
1859 static GLint
map_renderer_index(CGLRendererInfoObj renderer_info
, GLint renderer_count
, GLint renderer
)
1861 GLint good_count
, i
;
1864 for (i
= 0; i
< renderer_count
; i
++)
1866 CGLPixelFormatObj pix
= create_pixel_format_for_renderer(renderer_info
, i
, FALSE
);
1869 CGLReleasePixelFormat(pix
);
1871 if (good_count
> renderer
)
1875 TRACE("skipping bad renderer %d\n", i
);
1878 TRACE("mapped requested renderer %d to index %d\n", renderer
, i
);
1883 /**********************************************************************
1886 static const char* get_gl_string(CGLPixelFormatObj pixel_format
, GLenum name
)
1888 const char* ret
= NULL
;
1889 CGLContextObj context
, old_context
;
1892 err
= CGLCreateContext(pixel_format
, NULL
, &context
);
1893 if (err
== kCGLNoError
&& context
)
1895 old_context
= CGLGetCurrentContext();
1896 err
= CGLSetCurrentContext(context
);
1897 if (err
== kCGLNoError
)
1899 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(name
);
1900 CGLSetCurrentContext(old_context
);
1903 WARN("CGLSetCurrentContext failed: %d %s\n", err
, CGLErrorString(err
));
1904 CGLReleaseContext(context
);
1907 WARN("CGLCreateContext failed: %d %s\n", err
, CGLErrorString(err
));
1913 /**********************************************************************
1914 * get_fallback_renderer_version
1916 static void get_fallback_renderer_version(GLuint
*value
)
1918 BOOL got_it
= FALSE
;
1919 CFURLRef url
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1920 kCFURLPOSIXPathStyle
, TRUE
);
1923 CFBundleRef bundle
= CFBundleCreate(NULL
, url
);
1927 CFStringRef version
= CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleVersionKey
);
1928 if (version
&& CFGetTypeID(version
) == CFStringGetTypeID())
1930 size_t len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(version
), kCFStringEncodingUTF8
);
1931 char* buf
= malloc(len
);
1932 if (buf
&& CFStringGetCString(version
, buf
, len
, kCFStringEncodingUTF8
))
1934 unsigned int major
, minor
, bugfix
;
1935 int count
= sscanf(buf
, "%u.%u.%u", &major
, &minor
, &bugfix
);
1955 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1956 earliest version that the Mac driver supports. */
1964 /**********************************************************************
1965 * parse_renderer_version
1967 * Get the renderer version from the OpenGL version string. Assumes
1968 * the string is of the form
1969 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1970 * where major, minor, and bugfix are what we're interested in. This
1971 * form for the vendor specific information is not generally applicable,
1972 * but seems reliable on OS X.
1974 static BOOL
parse_renderer_version(const char* version
, GLuint
*value
)
1976 const char* p
= strchr(version
, ' ');
1978 unsigned int major
, minor
, bugfix
;
1980 if (p
) p
= strchr(p
+ 1, '-');
1981 if (!p
) return FALSE
;
1983 count
= sscanf(p
+ 1, "%u.%u.%u", &major
, &minor
, &bugfix
);
1998 /**********************************************************************
1999 * query_renderer_integer
2001 static BOOL
query_renderer_integer(CGLRendererInfoObj renderer_info
, GLint renderer
, GLenum attribute
, GLuint
*value
)
2009 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
2011 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer
, renderer_id
, attribute
, value
);
2016 case WGL_RENDERER_ACCELERATED_WINE
:
2017 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, (GLint
*)value
))
2021 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value
);
2024 case WGL_RENDERER_DEVICE_ID_WINE
:
2025 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("device-id"), value
);
2028 *value
= 0xffffffff;
2031 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value
);
2034 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE
:
2035 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
:
2037 BOOL core
= (attribute
== WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
);
2038 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, core
);
2042 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2044 CGLReleasePixelFormat(pixel_format
);
2047 unsigned int major
, minor
;
2049 if (sscanf(version
, "%u.%u", &major
, &minor
) == 2)
2060 value
[0] = value
[1] = 0;
2063 TRACE("%s -> %u.%u\n", core
? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2064 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value
[0], value
[1]);
2068 case WGL_RENDERER_PREFERRED_PROFILE_WINE
:
2070 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2074 CGLReleasePixelFormat(pixel_format
);
2075 *value
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
2076 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2080 *value
= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
2081 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2087 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE
:
2088 /* FIXME: no API to query this */
2091 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value
);
2094 case WGL_RENDERER_VENDOR_ID_WINE
:
2095 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("vendor-id"), value
);
2098 *value
= 0xffffffff;
2101 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value
);
2104 case WGL_RENDERER_VERSION_WINE
:
2106 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2109 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
2112 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2114 CGLReleasePixelFormat(pixel_format
);
2116 ret
= parse_renderer_version(version
, value
);
2121 get_fallback_renderer_version(value
);
2124 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
2128 case WGL_RENDERER_VIDEO_MEMORY_WINE
:
2129 err
= CGLDescribeRenderer(renderer_info
, renderer
, kCGLRPVideoMemoryMegabytes
, (GLint
*)value
);
2130 if (err
!= kCGLNoError
&& err
!= kCGLBadProperty
)
2131 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err
, CGLErrorString(err
));
2132 if (err
!= kCGLNoError
)
2134 if (get_renderer_property(renderer_info
, renderer
, kCGLRPVideoMemory
, (GLint
*)value
))
2135 *value
/= 1024 * 1024;
2140 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value
);
2144 FIXME("unrecognized attribute 0x%04x\n", attribute
);
2152 /**********************************************************************
2153 * macdrv_glCopyColorTable
2155 * Hook into glCopyColorTable as part of the implementation of
2156 * wglMakeContextCurrentARB. If the context has a separate readable,
2157 * temporarily make that current, do glCopyColorTable, and then set it
2158 * back to the drawable. This is modeled after what Mesa GLX's Apple
2159 * implementation does.
2161 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
2164 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2166 if (context
->read_view
|| context
->read_pbuffer
)
2167 make_context_current(context
, TRUE
);
2169 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
2171 if (context
->read_view
|| context
->read_pbuffer
)
2172 make_context_current(context
, FALSE
);
2176 /**********************************************************************
2177 * macdrv_glCopyPixels
2179 * Hook into glCopyPixels as part of the implementation of
2180 * wglMakeContextCurrentARB. If the context has a separate readable,
2181 * temporarily make that current, do glCopyPixels, and then set it back
2182 * to the drawable. This is modeled after what Mesa GLX's Apple
2183 * implementation does.
2185 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
2187 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2189 if (context
->read_view
|| context
->read_pbuffer
)
2190 make_context_current(context
, TRUE
);
2192 pglCopyPixels(x
, y
, width
, height
, type
);
2194 if (context
->read_view
|| context
->read_pbuffer
)
2195 make_context_current(context
, FALSE
);
2199 /**********************************************************************
2202 static void macdrv_glFinish(void)
2204 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2206 sync_swap_interval(context
);
2207 sync_context(context
);
2212 /**********************************************************************
2215 static void macdrv_glFlush(void)
2217 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2219 sync_swap_interval(context
);
2220 sync_context(context
);
2222 if (skip_single_buffer_flushes
)
2224 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
2225 DWORD now
= NtGetTickCount();
2227 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
2228 context
->last_flush_time
, now
);
2229 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
2231 TRACE("calling glFlushRenderAPPLE()\n");
2232 pglFlushRenderAPPLE();
2237 TRACE("calling glFlush()\n");
2238 context
->last_flush_time
= now
;
2246 /**********************************************************************
2247 * macdrv_glGetString
2249 * Hook into glGetString in order to return some legacy WGL extensions
2250 * that couldn't be advertised via the standard
2251 * WGL_ARB_extensions_string mechanism. Some programs, especially
2252 * older ones, expect to find certain older extensions, such as
2253 * WGL_EXT_extensions_string itself, in the standard GL extensions
2254 * string, and won't query any other WGL extensions unless they find
2255 * that particular extension there.
2257 static const GLubyte
*macdrv_glGetString(GLenum name
)
2259 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
2260 return (const GLubyte
*)gl_info
.glExtensions
;
2262 return pglGetString(name
);
2266 /**********************************************************************
2267 * macdrv_glReadPixels
2269 * Hook into glReadPixels as part of the implementation of
2270 * wglMakeContextCurrentARB. If the context has a separate readable,
2271 * temporarily make that current, do glReadPixels, and then set it back
2272 * to the drawable. This is modeled after what Mesa GLX's Apple
2273 * implementation does.
2275 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2276 GLenum format
, GLenum type
, void *pixels
)
2278 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2280 if (context
->read_view
|| context
->read_pbuffer
)
2281 make_context_current(context
, TRUE
);
2283 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2285 if (context
->read_view
|| context
->read_pbuffer
)
2286 make_context_current(context
, FALSE
);
2290 /**********************************************************************
2293 * Hook into glViewport as an opportunity to update the OpenGL context
2294 * if necessary. This is modeled after what Mesa GLX's Apple
2295 * implementation does.
2297 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2299 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2301 sync_context(context
);
2302 macdrv_update_opengl_context(context
->context
);
2303 pglViewport(x
, y
, width
, height
);
2307 /***********************************************************************
2308 * macdrv_wglBindTexImageARB
2310 * WGL_ARB_render_texture: wglBindTexImageARB
2312 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2314 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2318 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
2320 if (pbuffer
->no_texture
)
2322 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
2326 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
2327 opengl_funcs
.gl
.p_glFlush();
2331 case WGL_FRONT_LEFT_ARB
:
2332 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2333 source
= GL_FRONT_LEFT
;
2337 case WGL_FRONT_RIGHT_ARB
:
2338 source
= GL_FRONT_RIGHT
;
2340 case WGL_BACK_LEFT_ARB
:
2341 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2342 source
= GL_BACK_LEFT
;
2346 case WGL_BACK_RIGHT_ARB
:
2347 source
= GL_BACK_RIGHT
;
2349 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
2350 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
2351 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
2352 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
2360 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
2361 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
2365 WARN("unknown source buffer 0x%x\n", iBuffer
);
2366 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
2370 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
2371 if (err
!= kCGLNoError
)
2373 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2374 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
2382 /***********************************************************************
2383 * macdrv_wglChoosePixelFormatARB
2385 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2387 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2388 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2389 int *piFormats
, UINT
*nNumFormats
)
2391 pixel_format pf
, valid
;
2393 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2394 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2399 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2400 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2402 FIXME("unused pfAttribFList\n");
2404 memset(&pf
, 0, sizeof(pf
));
2405 memset(&valid
, 0, sizeof(valid
));
2406 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2407 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2411 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2414 int value
= iptr
[1];
2416 TRACE("%s\n", debugstr_attrib(attr
, value
));
2420 case WGL_DRAW_TO_WINDOW_ARB
:
2421 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2422 pf
.window
= (value
!= 0);
2426 case WGL_DRAW_TO_BITMAP_ARB
:
2429 case WGL_ACCELERATION_ARB
:
2430 if (value
== WGL_FULL_ACCELERATION_ARB
)
2432 else if (value
== WGL_NO_ACCELERATION_ARB
)
2436 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2437 pf
.accelerated
= value
;
2438 valid
.accelerated
= 1;
2441 case WGL_NEED_PALETTE_ARB
:
2442 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2443 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2444 if (value
) goto cant_match
;
2447 case WGL_SWAP_METHOD_ARB
:
2448 if (value
== WGL_SWAP_COPY_ARB
)
2450 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2454 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2455 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2456 pf
.backing_store
= value
;
2457 valid
.backing_store
= 1;
2460 case WGL_NUMBER_OVERLAYS_ARB
:
2461 case WGL_NUMBER_UNDERLAYS_ARB
:
2462 if (value
) goto cant_match
;
2465 case WGL_SHARE_DEPTH_ARB
:
2466 case WGL_SHARE_STENCIL_ARB
:
2467 case WGL_SHARE_ACCUM_ARB
:
2471 case WGL_SUPPORT_GDI_ARB
:
2472 if (value
) goto cant_match
;
2475 case WGL_SUPPORT_OPENGL_ARB
:
2476 if (!value
) goto cant_match
;
2479 case WGL_DOUBLE_BUFFER_ARB
:
2480 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2481 pf
.double_buffer
= (value
!= 0);
2482 valid
.double_buffer
= 1;
2483 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2486 case WGL_STEREO_ARB
:
2487 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2488 pf
.stereo
= (value
!= 0);
2492 case WGL_PIXEL_TYPE_ARB
:
2493 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2495 else if (value
== WGL_TYPE_RGBA_ARB
)
2499 /* Mac contexts don't support rendering to unsigned floating
2500 point formats, even if GL_EXT_packed_float is supported.
2501 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2504 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2505 if (srgb
&& value
) goto cant_match
;
2506 float_color
= value
;
2509 case WGL_COLOR_BITS_ARB
:
2510 if (color_bits
< value
) color_bits
= value
;
2513 case WGL_RED_BITS_ARB
:
2514 if (srgb
&& value
> 8) goto cant_match
;
2515 if (red_bits
< value
) red_bits
= value
;
2518 case WGL_GREEN_BITS_ARB
:
2519 if (srgb
&& value
> 8) goto cant_match
;
2520 if (green_bits
< value
) green_bits
= value
;
2523 case WGL_BLUE_BITS_ARB
:
2524 if (srgb
&& value
> 8) goto cant_match
;
2525 if (blue_bits
< value
) blue_bits
= value
;
2528 case WGL_ALPHA_BITS_ARB
:
2529 if (alpha_bits
< value
) alpha_bits
= value
;
2532 case WGL_ACCUM_BITS_ARB
:
2533 if (accum_bits
< value
) accum_bits
= value
;
2536 case WGL_ACCUM_RED_BITS_ARB
:
2537 if (accum_red_bits
< value
) accum_red_bits
= value
;
2540 case WGL_ACCUM_GREEN_BITS_ARB
:
2541 if (accum_green_bits
< value
) accum_green_bits
= value
;
2544 case WGL_ACCUM_BLUE_BITS_ARB
:
2545 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2548 case WGL_ACCUM_ALPHA_BITS_ARB
:
2549 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2552 case WGL_DEPTH_BITS_ARB
:
2553 if (value
> 255) goto cant_match
;
2554 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2557 case WGL_STENCIL_BITS_ARB
:
2558 if (value
> 255) goto cant_match
;
2559 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2562 case WGL_AUX_BUFFERS_ARB
:
2563 if (value
> 7) goto cant_match
;
2564 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2567 case WGL_SAMPLE_BUFFERS_ARB
:
2568 if (value
> 1) goto cant_match
;
2569 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2572 case WGL_SAMPLES_ARB
:
2573 if (value
> 31) goto cant_match
;
2574 if (pf
.samples
< value
) pf
.samples
= value
;
2577 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2578 /* sRGB is only supported for 8-bit integer color components */
2579 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2584 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2585 case WGL_RED_SHIFT_ARB
:
2586 case WGL_GREEN_SHIFT_ARB
:
2587 case WGL_BLUE_SHIFT_ARB
:
2588 case WGL_ALPHA_SHIFT_ARB
:
2589 case WGL_TRANSPARENT_ARB
:
2590 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2591 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2592 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2593 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2594 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2598 case WGL_DRAW_TO_PBUFFER_ARB
:
2599 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2600 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2601 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2602 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2603 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2604 pf
.pbuffer
= (value
!= 0);
2606 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2612 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2617 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",
2618 valid
.window
? (pf
.window
? "1" : "0") : "?",
2619 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2620 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2622 float_color
== -1 ? "?" : float_color
? "f" : "",
2636 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2637 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2638 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2642 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2644 const struct color_mode
*mode
;
2646 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2647 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2648 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2649 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2650 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2651 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2653 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2654 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2655 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2656 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2657 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2659 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2660 /* If the mode doesn't have alpha, check requested color bits against
2661 bits per pixel instead of the mode's color bits. On Windows, color
2662 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2663 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2664 expects that to match such a pixel format, we need to accommodate that. */
2665 if (mode
->alpha_bits
)
2667 if (mode
->color_bits
< color_bits
)
2672 if (mode
->bits_per_pixel
< color_bits
)
2675 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2676 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2678 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2679 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2682 if (pixel_formats
[i
].accum_mode
)
2684 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2685 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2686 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2687 mode
->alpha_bits
< accum_alpha_bits
)
2690 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2693 piFormats
[found
++] = i
+ 1;
2694 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2698 *nNumFormats
= found
;
2704 /***********************************************************************
2705 * macdrv_wglCreateContextAttribsARB
2707 * WGL_ARB_create_context: wglCreateContextAttribsARB
2709 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2710 struct wgl_context
*share_context
,
2711 const int *attrib_list
)
2714 struct wgl_context
*context
;
2716 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2718 GLint renderer_id
= 0;
2720 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2722 format
= get_dc_pixel_format(hdc
);
2724 if (!is_valid_pixel_format(format
))
2726 ERR("Invalid pixel format %d, expect problems!\n", format
);
2727 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
2731 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2734 int value
= iptr
[1];
2736 TRACE("%s\n", debugstr_attrib(attr
, value
));
2740 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2744 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2748 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2749 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2752 case WGL_CONTEXT_FLAGS_ARB
:
2754 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2755 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2756 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2759 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2760 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2761 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2763 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2764 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB
);
2770 case WGL_RENDERER_ID_WINE
:
2773 CGLRendererInfoObj renderer_info
;
2774 GLint renderer_count
, temp
;
2776 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
2777 if (err
!= kCGLNoError
)
2779 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
2780 RtlSetLastWin32Error(ERROR_GEN_FAILURE
);
2784 value
= map_renderer_index(renderer_info
, renderer_count
, value
);
2786 if (value
>= renderer_count
)
2788 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value
, renderer_count
);
2789 CGLDestroyRendererInfo(renderer_info
);
2790 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER
);
2794 if (!get_renderer_property(renderer_info
, value
, kCGLRPRendererID
, &temp
))
2796 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value
);
2797 CGLDestroyRendererInfo(renderer_info
);
2798 RtlSetLastWin32Error(ERROR_GEN_FAILURE
);
2802 CGLDestroyRendererInfo(renderer_info
);
2804 if (renderer_id
&& temp
!= renderer_id
)
2806 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id
, temp
);
2807 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER
);
2815 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2816 RtlSetLastWin32Error(ERROR_INVALID_PARAMETER
);
2821 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2822 (major
== 4 && (minor
== 0 || minor
== 1)))
2824 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2826 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2827 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB
);
2830 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2832 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2833 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB
);
2836 if (major
> gl_info
.max_major
||
2837 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2839 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2841 RtlSetLastWin32Error(ERROR_INVALID_PROFILE_ARB
);
2846 else if (major
>= 3)
2848 WARN("Profile version %u.%u not supported\n", major
, minor
);
2849 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB
);
2852 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2853 (major
== 2 && (minor
< 0 || minor
> 1)))
2855 WARN("Invalid GL version requested\n");
2856 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB
);
2859 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2861 WARN("Forward compatible context requested for GL version < 3\n");
2862 RtlSetLastWin32Error(ERROR_INVALID_VERSION_ARB
);
2866 if (!(context
= calloc(1, sizeof(*context
)))) return NULL
;
2868 context
->format
= format
;
2869 context
->renderer_id
= renderer_id
;
2870 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2876 pthread_mutex_lock(&context_mutex
);
2877 list_add_tail(&context_list
, &context
->entry
);
2878 pthread_mutex_unlock(&context_mutex
);
2884 /**********************************************************************
2885 * macdrv_wglCreatePbufferARB
2887 * WGL_ARB_pbuffer: wglCreatePbufferARB
2889 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2890 const int *piAttribList
)
2892 struct wgl_pbuffer
* pbuffer
;
2894 GLenum internalFormat
= 0;
2897 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2898 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2900 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2902 WARN("invalid pixel format %d\n", iPixelFormat
);
2903 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
2907 pbuffer
= calloc(1, sizeof(*pbuffer
));
2908 pbuffer
->format
= iPixelFormat
;
2910 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2912 int attr
= piAttribList
[0];
2913 int value
= piAttribList
[1];
2917 case WGL_PBUFFER_LARGEST_ARB
:
2918 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2921 case WGL_TEXTURE_FORMAT_ARB
:
2924 case WGL_TEXTURE_RGBA_ARB
:
2925 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2926 internalFormat
= GL_RGBA
;
2928 case WGL_TEXTURE_RGB_ARB
:
2929 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2930 internalFormat
= GL_RGB
;
2932 case WGL_NO_TEXTURE_ARB
:
2933 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2937 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2938 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
2943 case WGL_TEXTURE_TARGET_ARB
:
2947 case WGL_NO_TEXTURE_ARB
:
2948 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2951 case WGL_TEXTURE_CUBE_MAP_ARB
:
2952 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2953 target
= GL_TEXTURE_CUBE_MAP
;
2954 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2956 case WGL_TEXTURE_1D_ARB
:
2957 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2958 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2960 case WGL_TEXTURE_2D_ARB
:
2961 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2962 target
= GL_TEXTURE_2D
;
2964 case WGL_TEXTURE_RECTANGLE_NV
:
2965 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2966 target
= GL_TEXTURE_RECTANGLE
;
2969 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2970 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
2975 case WGL_MIPMAP_TEXTURE_ARB
:
2976 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2977 pbuffer
->max_level
= 0;
2980 int size
= min(iWidth
, iHeight
) / 2;
2983 pbuffer
->max_level
++;
2990 WARN("unknown attribute 0x%x\n", attr
);
2991 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
2996 if (!target
|| !internalFormat
)
2998 pbuffer
->no_texture
= TRUE
;
2999 /* no actual way to turn off ability to texture; use most permissive target */
3000 target
= GL_TEXTURE_RECTANGLE
;
3001 internalFormat
= GL_RGB
;
3004 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
3005 if (err
!= kCGLNoError
)
3007 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
3008 pbuffer
->pbuffer
= NULL
;
3009 if (err
== kCGLBadAlloc
)
3010 RtlSetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
3012 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
3016 if (!pbuffer
->pbuffer
)
3022 TRACE(" -> %p\n", pbuffer
);
3027 /**********************************************************************
3028 * macdrv_wglDestroyPbufferARB
3030 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3032 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
3034 TRACE("pbuffer %p\n", pbuffer
);
3035 if (pbuffer
&& pbuffer
->pbuffer
)
3036 CGLReleasePBuffer(pbuffer
->pbuffer
);
3042 /**********************************************************************
3043 * macdrv_wglGetExtensionsStringARB
3045 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3047 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
3049 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3050 this can be specific to the CGL renderer like we're supposed to do. */
3051 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3052 return gl_info
.wglExtensions
;
3056 /**********************************************************************
3057 * macdrv_wglGetExtensionsStringEXT
3059 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3061 static const char *macdrv_wglGetExtensionsStringEXT(void)
3063 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3064 return gl_info
.wglExtensions
;
3068 /**********************************************************************
3069 * macdrv_wglGetPbufferDCARB
3071 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3073 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
3076 struct wgl_pbuffer
*prev
;
3078 hdc
= NtGdiOpenDCW(NULL
, NULL
, NULL
, 0, TRUE
, NULL
, NULL
, NULL
);
3081 pthread_mutex_lock(&dc_pbuffers_mutex
);
3082 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3085 CGLReleasePBuffer(prev
->pbuffer
);
3088 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
3089 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3091 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
3096 /**********************************************************************
3097 * macdrv_wglGetPixelFormatAttribivARB
3099 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3101 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3102 UINT nAttributes
, const int *piAttributes
, int *piValues
)
3104 const pixel_format
*pf
;
3107 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3108 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
3110 if (!nAttributes
) return GL_TRUE
;
3112 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
3114 piValues
[0] = nb_formats
;
3115 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
3119 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
3122 WARN("invalid pixel format %d\n", iPixelFormat
);
3123 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
3127 for (i
= 0; i
< nAttributes
; ++i
)
3129 switch (piAttributes
[i
])
3131 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
3132 piValues
[i
] = nb_formats
;
3135 case WGL_DRAW_TO_WINDOW_ARB
:
3136 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
3139 case WGL_DRAW_TO_BITMAP_ARB
:
3140 piValues
[i
] = GL_FALSE
;
3143 case WGL_ACCELERATION_ARB
:
3144 if (iLayerPlane
) goto invalid_layer
;
3145 if (pf
->accelerated
)
3146 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
3148 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
3151 case WGL_NEED_PALETTE_ARB
:
3152 case WGL_NEED_SYSTEM_PALETTE_ARB
:
3153 case WGL_SWAP_LAYER_BUFFERS_ARB
:
3154 piValues
[i
] = GL_FALSE
;
3157 case WGL_SWAP_METHOD_ARB
:
3158 if (pf
->double_buffer
&& pf
->backing_store
)
3159 piValues
[i
] = WGL_SWAP_COPY_ARB
;
3161 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
3164 case WGL_NUMBER_OVERLAYS_ARB
:
3165 case WGL_NUMBER_UNDERLAYS_ARB
:
3169 case WGL_TRANSPARENT_ARB
:
3170 if (iLayerPlane
) goto invalid_layer
;
3171 piValues
[i
] = GL_FALSE
;
3174 case WGL_TRANSPARENT_RED_VALUE_ARB
:
3175 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
3176 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
3177 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
3178 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
3179 if (iLayerPlane
) goto invalid_layer
;
3183 case WGL_SHARE_DEPTH_ARB
:
3184 case WGL_SHARE_STENCIL_ARB
:
3185 case WGL_SHARE_ACCUM_ARB
:
3186 if (iLayerPlane
) goto invalid_layer
;
3187 piValues
[i
] = GL_TRUE
;
3190 case WGL_SUPPORT_GDI_ARB
:
3191 if (iLayerPlane
) goto invalid_layer
;
3192 piValues
[i
] = GL_FALSE
;
3195 case WGL_SUPPORT_OPENGL_ARB
:
3196 if (iLayerPlane
) goto invalid_layer
;
3197 piValues
[i
] = GL_TRUE
;
3200 case WGL_DOUBLE_BUFFER_ARB
:
3201 if (iLayerPlane
) goto invalid_layer
;
3202 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
3205 case WGL_STEREO_ARB
:
3206 if (iLayerPlane
) goto invalid_layer
;
3207 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
3210 case WGL_PIXEL_TYPE_ARB
:
3211 if (iLayerPlane
) goto invalid_layer
;
3212 if (color_modes
[pf
->color_mode
].is_float
)
3213 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
3215 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
3216 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3217 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3218 However, Mac contexts don't support rendering to unsigned floating-point
3219 formats, even when GL_EXT_packed_float is supported. */
3222 case WGL_COLOR_BITS_ARB
:
3223 if (iLayerPlane
) goto invalid_layer
;
3224 /* If the mode doesn't have alpha, return bits per pixel instead
3225 of color bits. On Windows, color bits sometimes exceeds r+g+b
3226 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3227 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3228 pixel format, we need to accommodate that. */
3229 if (color_modes
[pf
->color_mode
].alpha_bits
)
3230 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
3232 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
3235 case WGL_RED_BITS_ARB
:
3236 if (iLayerPlane
) goto invalid_layer
;
3237 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
3240 case WGL_RED_SHIFT_ARB
:
3241 if (iLayerPlane
) goto invalid_layer
;
3242 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
3245 case WGL_GREEN_BITS_ARB
:
3246 if (iLayerPlane
) goto invalid_layer
;
3247 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
3250 case WGL_GREEN_SHIFT_ARB
:
3251 if (iLayerPlane
) goto invalid_layer
;
3252 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
3255 case WGL_BLUE_BITS_ARB
:
3256 if (iLayerPlane
) goto invalid_layer
;
3257 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
3260 case WGL_BLUE_SHIFT_ARB
:
3261 if (iLayerPlane
) goto invalid_layer
;
3262 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
3265 case WGL_ALPHA_BITS_ARB
:
3266 if (iLayerPlane
) goto invalid_layer
;
3267 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
3270 case WGL_ALPHA_SHIFT_ARB
:
3271 if (iLayerPlane
) goto invalid_layer
;
3272 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
3275 case WGL_ACCUM_BITS_ARB
:
3276 if (iLayerPlane
) goto invalid_layer
;
3278 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3283 case WGL_ACCUM_RED_BITS_ARB
:
3284 if (iLayerPlane
) goto invalid_layer
;
3286 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
3291 case WGL_ACCUM_GREEN_BITS_ARB
:
3292 if (iLayerPlane
) goto invalid_layer
;
3294 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
3299 case WGL_ACCUM_BLUE_BITS_ARB
:
3300 if (iLayerPlane
) goto invalid_layer
;
3302 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
3307 case WGL_ACCUM_ALPHA_BITS_ARB
:
3308 if (iLayerPlane
) goto invalid_layer
;
3310 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
3315 case WGL_DEPTH_BITS_ARB
:
3316 if (iLayerPlane
) goto invalid_layer
;
3317 piValues
[i
] = pf
->depth_bits
;
3320 case WGL_STENCIL_BITS_ARB
:
3321 if (iLayerPlane
) goto invalid_layer
;
3322 piValues
[i
] = pf
->stencil_bits
;
3325 case WGL_AUX_BUFFERS_ARB
:
3326 if (iLayerPlane
) goto invalid_layer
;
3327 piValues
[i
] = pf
->aux_buffers
;
3330 case WGL_SAMPLE_BUFFERS_ARB
:
3331 if (iLayerPlane
) goto invalid_layer
;
3332 piValues
[i
] = pf
->sample_buffers
;
3335 case WGL_SAMPLES_ARB
:
3336 if (iLayerPlane
) goto invalid_layer
;
3337 piValues
[i
] = pf
->samples
;
3340 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3341 if (iLayerPlane
) goto invalid_layer
;
3342 /* sRGB is only supported for 8-bit integer color components */
3343 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
3344 color_modes
[pf
->color_mode
].green_bits
== 8 &&
3345 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
3346 !color_modes
[pf
->color_mode
].is_float
)
3347 piValues
[i
] = GL_TRUE
;
3349 piValues
[i
] = GL_FALSE
;
3352 case WGL_DRAW_TO_PBUFFER_ARB
:
3353 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
3354 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
3355 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
3358 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
3359 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
3360 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
3363 case WGL_MAX_PBUFFER_WIDTH_ARB
:
3364 piValues
[i
] = gl_info
.max_viewport_dims
[0];
3367 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
3368 piValues
[i
] = gl_info
.max_viewport_dims
[1];
3371 case WGL_MAX_PBUFFER_PIXELS_ARB
:
3372 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
3376 WARN("invalid attribute %x\n", piAttributes
[i
]);
3380 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
3386 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
3391 /**********************************************************************
3392 * macdrv_wglGetPixelFormatAttribfvARB
3394 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3396 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3397 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
3402 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3403 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
3405 /* Allocate a temporary array to store integer values */
3406 attr
= malloc(nAttributes
* sizeof(int));
3409 ERR("couldn't allocate %d array\n", nAttributes
);
3413 /* Piggy-back on wglGetPixelFormatAttribivARB */
3414 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
3419 /* Convert integer values to float. Should also check for attributes
3420 that can give decimal values here */
3421 for (i
= 0; i
< nAttributes
; i
++)
3422 pfValues
[i
] = attr
[i
];
3430 /**********************************************************************
3431 * macdrv_wglGetSwapIntervalEXT
3433 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3435 static int macdrv_wglGetSwapIntervalEXT(void)
3437 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3438 struct macdrv_win_data
*data
;
3444 if ((data
= get_win_data(context
->draw_hwnd
)))
3446 value
= data
->swap_interval
;
3447 release_win_data(data
);
3449 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3450 set_swap_interval(context
, allow_vsync
? value
: 0);
3454 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3455 if (err
!= kCGLNoError
)
3457 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3458 err
, CGLErrorString(err
));
3467 /***********************************************************************
3468 * macdrv_wglMakeContextCurrentARB
3470 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3472 * This is not supported directly by OpenGL on the Mac. We emulate it
3473 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3474 * temporarily swap the drawable. This follows the technique used in
3475 * the implementation of Mesa GLX for Apple.
3477 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3479 struct macdrv_win_data
*data
;
3482 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3483 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3487 macdrv_make_context_current(NULL
, NULL
, CGRectNull
);
3488 NtCurrentTeb()->glContext
= NULL
;
3492 if ((hwnd
= NtUserWindowFromDC(draw_hdc
)))
3494 if (!(data
= get_win_data(hwnd
)))
3496 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3500 if (!data
->pixel_format
)
3502 WARN("no pixel format set\n");
3503 release_win_data(data
);
3504 RtlSetLastWin32Error(ERROR_INVALID_HANDLE
);
3507 if (context
->format
!= data
->pixel_format
)
3509 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3510 release_win_data(data
);
3511 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
3515 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
)
3516 set_swap_interval(context
, allow_vsync
? data
->swap_interval
: 0);
3518 context
->draw_hwnd
= hwnd
;
3519 context
->draw_view
= data
->client_cocoa_view
;
3520 context
->draw_rect
= data
->client_rect
;
3521 OffsetRect(&context
->draw_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3522 context
->draw_pbuffer
= NULL
;
3523 release_win_data(data
);
3527 struct wgl_pbuffer
*pbuffer
;
3529 pthread_mutex_lock(&dc_pbuffers_mutex
);
3530 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3533 if (context
->format
!= pbuffer
->format
)
3535 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3536 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3537 RtlSetLastWin32Error(ERROR_INVALID_PIXEL_FORMAT
);
3541 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
)
3542 set_swap_interval(context
, 0);
3546 WARN("no window or pbuffer for DC\n");
3547 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3548 RtlSetLastWin32Error(ERROR_INVALID_HANDLE
);
3552 context
->draw_hwnd
= NULL
;
3553 context
->draw_view
= NULL
;
3554 context
->draw_pbuffer
= pbuffer
;
3555 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3558 context
->read_view
= NULL
;
3559 context
->read_pbuffer
= NULL
;
3560 if (read_hdc
&& read_hdc
!= draw_hdc
)
3562 if ((hwnd
= NtUserWindowFromDC(read_hdc
)))
3564 if ((data
= get_win_data(hwnd
)))
3566 if (data
->client_cocoa_view
!= context
->draw_view
)
3568 context
->read_view
= data
->client_cocoa_view
;
3569 context
->read_rect
= data
->client_rect
;
3570 OffsetRect(&context
->read_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3572 release_win_data(data
);
3577 pthread_mutex_lock(&dc_pbuffers_mutex
);
3578 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3579 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3583 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3584 context
->draw_view
, wine_dbgstr_rect(&context
->draw_rect
), context
->draw_pbuffer
,
3585 context
->read_view
, wine_dbgstr_rect(&context
->read_rect
), context
->read_pbuffer
, context
->format
);
3587 make_context_current(context
, FALSE
);
3588 context
->has_been_current
= TRUE
;
3589 NtCurrentTeb()->glContext
= context
;
3595 /**********************************************************************
3596 * macdrv_wglQueryCurrentRendererIntegerWINE
3598 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3600 static BOOL
macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute
, GLuint
*value
)
3603 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3604 CGLPixelFormatObj pixel_format
;
3606 GLint virtual_screen
;
3608 GLint pf_renderer_id
;
3609 CGLRendererInfoObj renderer_info
;
3610 GLint renderer_count
;
3613 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context
, (context
? context
->context
: NULL
),
3614 (context
? context
->cglcontext
: NULL
), attribute
, value
);
3616 if (attribute
== WGL_RENDERER_VERSION_WINE
)
3618 if (!parse_renderer_version((const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
), value
))
3619 get_fallback_renderer_version(value
);
3620 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
3624 pixel_format
= CGLGetPixelFormat(context
->cglcontext
);
3625 err
= CGLGetVirtualScreen(context
->cglcontext
, &virtual_screen
);
3626 if (err
!= kCGLNoError
)
3628 WARN("CGLGetVirtualScreen failed: %d %s\n", err
, CGLErrorString(err
));
3632 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFADisplayMask
, &display_mask
);
3633 if (err
!= kCGLNoError
)
3635 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err
, CGLErrorString(err
));
3639 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFARendererID
, &pf_renderer_id
);
3640 if (err
!= kCGLNoError
)
3642 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err
, CGLErrorString(err
));
3646 err
= CGLQueryRendererInfo(display_mask
, &renderer_info
, &renderer_count
);
3647 if (err
!= kCGLNoError
)
3649 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3653 for (renderer
= 0; renderer
< renderer_count
; renderer
++)
3657 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
3660 if (renderer_id
== pf_renderer_id
)
3662 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3667 if (renderer
>= renderer_count
)
3668 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id
, display_mask
);
3670 CGLDestroyRendererInfo(renderer_info
);
3675 /**********************************************************************
3676 * macdrv_wglQueryCurrentRendererStringWINE
3678 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3680 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute
)
3682 const char* ret
= NULL
;
3683 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3685 TRACE("context %p/%p/%p attribute 0x%04x\n", context
, (context
? context
->context
: NULL
),
3686 (context
? context
->cglcontext
: NULL
), attribute
);
3690 case WGL_RENDERER_DEVICE_ID_WINE
:
3692 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_RENDERER
);
3693 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret
));
3697 case WGL_RENDERER_VENDOR_ID_WINE
:
3699 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VENDOR
);
3700 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret
));
3705 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3713 /**********************************************************************
3714 * macdrv_wglQueryPbufferARB
3716 * WGL_ARB_pbuffer: wglQueryPbufferARB
3718 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3724 GLenum internalFormat
;
3727 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3729 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3730 if (err
!= kCGLNoError
)
3732 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3733 RtlSetLastWin32Error(ERROR_INVALID_HANDLE
);
3739 case WGL_PBUFFER_WIDTH_ARB
:
3742 case WGL_PBUFFER_HEIGHT_ARB
:
3745 case WGL_PBUFFER_LOST_ARB
:
3746 /* Mac PBuffers can't be lost */
3747 *piValue
= GL_FALSE
;
3749 case WGL_TEXTURE_FORMAT_ARB
:
3750 if (pbuffer
->no_texture
)
3751 *piValue
= WGL_NO_TEXTURE_ARB
;
3752 else switch (internalFormat
)
3755 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3759 *piValue
= WGL_TEXTURE_RGB_ARB
;
3763 case WGL_TEXTURE_TARGET_ARB
:
3764 if (pbuffer
->no_texture
)
3765 *piValue
= WGL_NO_TEXTURE_ARB
;
3766 else switch (target
)
3768 case GL_TEXTURE_CUBE_MAP
:
3769 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3772 *piValue
= WGL_TEXTURE_2D_ARB
;
3774 case GL_TEXTURE_RECTANGLE
:
3776 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3780 case WGL_MIPMAP_TEXTURE_ARB
:
3781 *piValue
= (pbuffer
->max_level
> 0);
3783 case WGL_MIPMAP_LEVEL_ARB
:
3784 *piValue
= pbuffer
->level
;
3786 case WGL_CUBE_MAP_FACE_ARB
:
3787 switch (pbuffer
->face
)
3789 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3791 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3793 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3794 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3796 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3797 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3800 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3802 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3803 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3805 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3806 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3811 WARN("invalid attribute 0x%x\n", iAttribute
);
3812 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
3820 /**********************************************************************
3821 * macdrv_wglQueryRendererIntegerWINE
3823 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3825 static BOOL
macdrv_wglQueryRendererIntegerWINE(HDC dc
, GLint renderer
, GLenum attribute
, GLuint
*value
)
3828 CGLRendererInfoObj renderer_info
;
3829 GLint renderer_count
;
3832 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc
, renderer
, attribute
, value
);
3834 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3835 if (err
!= kCGLNoError
)
3837 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3841 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3843 if (renderer
< renderer_count
)
3844 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3846 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3848 CGLDestroyRendererInfo(renderer_info
);
3853 /**********************************************************************
3854 * macdrv_wglQueryRendererStringWINE
3856 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3858 static const char *macdrv_wglQueryRendererStringWINE(HDC dc
, GLint renderer
, GLenum attribute
)
3860 const char* ret
= NULL
;
3861 CGLRendererInfoObj renderer_info
;
3862 GLint renderer_count
;
3865 TRACE("dc %p renderer %d attribute 0x%04x\n", dc
, renderer
, attribute
);
3867 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3868 if (err
!= kCGLNoError
)
3870 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3874 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3876 if (renderer
>= renderer_count
)
3878 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3884 case WGL_RENDERER_DEVICE_ID_WINE
:
3885 case WGL_RENDERER_VENDOR_ID_WINE
:
3887 BOOL device
= (attribute
== WGL_RENDERER_DEVICE_ID_WINE
);
3888 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
3891 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
3894 ret
= get_gl_string(pixel_format
, device
? GL_RENDERER
: GL_VENDOR
);
3895 CGLReleasePixelFormat(pixel_format
);
3898 TRACE("%s -> %s\n", device
? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret
));
3903 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3908 CGLDestroyRendererInfo(renderer_info
);
3913 /**********************************************************************
3914 * macdrv_wglReleasePbufferDCARB
3916 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3918 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3920 struct wgl_pbuffer
*prev
;
3922 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3924 pthread_mutex_lock(&dc_pbuffers_mutex
);
3926 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3929 if (prev
!= pbuffer
)
3930 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3931 CGLReleasePBuffer(prev
->pbuffer
);
3933 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3937 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3939 return hdc
&& NtGdiDeleteObjectApp(hdc
);
3943 /**********************************************************************
3944 * macdrv_wglReleaseTexImageARB
3946 * WGL_ARB_render_texture: wglReleaseTexImageARB
3948 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3950 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3953 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3955 if (pbuffer
->no_texture
)
3957 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
3961 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3962 if (err
!= kCGLNoError
)
3964 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3965 RtlSetLastWin32Error(ERROR_INVALID_OPERATION
);
3973 /**********************************************************************
3974 * macdrv_wglSetPbufferAttribARB
3976 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3978 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
3980 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3982 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
3984 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3986 int attr
= piAttribList
[0];
3987 int value
= piAttribList
[1];
3990 case WGL_MIPMAP_LEVEL_ARB
:
3991 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
3992 pbuffer
->level
= value
;
3994 case WGL_CUBE_MAP_FACE_ARB
:
3997 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3998 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3999 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
4001 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4002 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4003 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
4005 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4006 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4007 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
4009 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4010 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4011 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
4013 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4014 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4015 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
4017 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4018 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4019 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
4022 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
4023 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
4028 WARN("invalid attribute 0x%x\n", attr
);
4029 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
4034 if (context
&& context
->draw_pbuffer
== pbuffer
)
4035 make_context_current(context
, FALSE
);
4041 /**********************************************************************
4042 * macdrv_wglSetPixelFormatWINE
4044 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4046 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
4048 return set_pixel_format(hdc
, fmt
, TRUE
);
4052 /**********************************************************************
4053 * macdrv_wglSwapIntervalEXT
4055 * WGL_EXT_swap_control: wglSwapIntervalEXT
4057 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
4059 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4060 BOOL changed
= FALSE
;
4062 TRACE("interval %d\n", interval
);
4066 RtlSetLastWin32Error(ERROR_INVALID_DATA
);
4072 if (context
->draw_hwnd
)
4074 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
4077 changed
= data
->swap_interval
!= interval
;
4079 data
->swap_interval
= interval
;
4080 release_win_data(data
);
4089 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
4090 if (!set_swap_interval(context
, interval
))
4092 RtlSetLastWin32Error(ERROR_GEN_FAILURE
);
4098 struct wgl_context
*ctx
;
4100 pthread_mutex_lock(&context_mutex
);
4101 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
4103 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
4104 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
4106 pthread_mutex_unlock(&context_mutex
);
4113 static void register_extension(const char *ext
)
4115 if (gl_info
.wglExtensions
[0])
4116 strcat(gl_info
.wglExtensions
, " ");
4117 strcat(gl_info
.wglExtensions
, ext
);
4119 TRACE("'%s'\n", ext
);
4122 static void load_extensions(void)
4127 register_extension("WGL_ARB_extensions_string");
4128 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
4130 register_extension("WGL_ARB_make_current_read");
4131 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
4132 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
4134 register_extension("WGL_ARB_pixel_format");
4135 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
4136 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
4137 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
4139 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
4141 register_extension("WGL_ARB_pixel_format_float");
4142 register_extension("WGL_ATI_pixel_format_float");
4145 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
4146 register_extension("WGL_ARB_multisample");
4148 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4149 register_extension("WGL_ARB_framebuffer_sRGB");
4151 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
4153 register_extension("WGL_ARB_pbuffer");
4154 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
4155 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
4156 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
4157 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
4158 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
4160 register_extension("WGL_ARB_render_texture");
4161 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
4162 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
4163 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
4165 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
4166 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
4167 register_extension("WGL_NV_render_texture_rectangle");
4170 register_extension("WGL_ARB_create_context");
4171 register_extension("WGL_ARB_create_context_profile");
4172 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
4177 register_extension("WGL_EXT_extensions_string");
4178 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
4182 register_extension("WGL_EXT_swap_control");
4183 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
4184 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
4187 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4188 check for either, so register them separately. */
4189 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4190 register_extension("WGL_EXT_framebuffer_sRGB");
4192 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
4193 register_extension("WGL_EXT_pixel_format_packed_float");
4196 * WINE-specific WGL Extensions
4199 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4200 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4202 register_extension("WGL_WINE_pixel_format_passthrough");
4203 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
4205 register_extension("WGL_WINE_query_renderer");
4206 opengl_funcs
.ext
.p_wglQueryCurrentRendererIntegerWINE
= macdrv_wglQueryCurrentRendererIntegerWINE
;
4207 opengl_funcs
.ext
.p_wglQueryCurrentRendererStringWINE
= macdrv_wglQueryCurrentRendererStringWINE
;
4208 opengl_funcs
.ext
.p_wglQueryRendererIntegerWINE
= macdrv_wglQueryRendererIntegerWINE
;
4209 opengl_funcs
.ext
.p_wglQueryRendererStringWINE
= macdrv_wglQueryRendererStringWINE
;
4213 static void init_opengl(void)
4219 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
4222 WARN("CFDictionaryCreateMutable failed\n");
4226 opengl_handle
= dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
);
4229 ERR("Failed to load OpenGL: %s\n", dlerror());
4230 ERR("OpenGL support is disabled.\n");
4234 for (i
= 0; i
< ARRAY_SIZE(opengl_func_names
); i
++)
4236 if (!(((void **)&opengl_funcs
.gl
)[i
] = dlsym(opengl_handle
, opengl_func_names
[i
])))
4238 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
4243 if (!init_gl_info())
4246 /* redirect some standard OpenGL functions */
4247 #define REDIRECT(func) \
4248 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4249 REDIRECT(glCopyPixels
);
4250 REDIRECT(glGetString
);
4251 REDIRECT(glReadPixels
);
4252 REDIRECT(glViewport
);
4253 if (skip_single_buffer_flushes
|| allow_vsync
)
4259 /* redirect some OpenGL extension functions */
4260 #define REDIRECT(func) \
4261 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4262 REDIRECT(glCopyColorTable
);
4265 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
4266 pglFlushRenderAPPLE
= dlsym(opengl_handle
, "glFlushRenderAPPLE");
4269 if (!init_pixel_formats())
4275 dlclose(opengl_handle
);
4276 opengl_handle
= NULL
;
4280 /***********************************************************************
4283 * Synchronize the Mac GL view position with the Windows child window
4286 void sync_gl_view(struct macdrv_win_data
* data
, const RECT
* old_whole_rect
, const RECT
* old_client_rect
)
4288 if (data
->client_cocoa_view
&& data
->pixel_format
)
4290 RECT old
= *old_client_rect
, new = data
->client_rect
;
4292 OffsetRect(&old
, -old_whole_rect
->left
, -old_whole_rect
->top
);
4293 OffsetRect(&new, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
4294 if (!EqualRect(&old
, &new))
4296 TRACE("GL view %p changed position; marking contexts\n", data
->client_cocoa_view
);
4297 mark_contexts_for_moved_view(data
->client_cocoa_view
);
4303 /**********************************************************************
4304 * macdrv_wglDescribePixelFormat
4306 static int WINAPI
macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
4308 const pixel_format
*pf
;
4309 const struct color_mode
*mode
;
4311 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
4313 if (!descr
) return nb_displayable_formats
;
4314 if (size
< sizeof(*descr
)) return 0;
4316 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
4319 memset(descr
, 0, sizeof(*descr
));
4320 descr
->nSize
= sizeof(*descr
);
4321 descr
->nVersion
= 1;
4323 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
4324 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
4325 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
4326 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
4327 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
4328 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
4330 descr
->iPixelType
= PFD_TYPE_RGBA
;
4332 mode
= &color_modes
[pf
->color_mode
];
4333 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4334 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4335 R8G8B8A0 pixel format). If an app depends on that and expects that
4336 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4337 if (mode
->alpha_bits
)
4338 descr
->cColorBits
= mode
->color_bits
;
4340 descr
->cColorBits
= mode
->bits_per_pixel
;
4341 descr
->cRedBits
= mode
->red_bits
;
4342 descr
->cRedShift
= mode
->red_shift
;
4343 descr
->cGreenBits
= mode
->green_bits
;
4344 descr
->cGreenShift
= mode
->green_shift
;
4345 descr
->cBlueBits
= mode
->blue_bits
;
4346 descr
->cBlueShift
= mode
->blue_shift
;
4347 descr
->cAlphaBits
= mode
->alpha_bits
;
4348 descr
->cAlphaShift
= mode
->alpha_shift
;
4352 mode
= &color_modes
[pf
->accum_mode
- 1];
4353 descr
->cAccumBits
= mode
->color_bits
;
4354 descr
->cAccumRedBits
= mode
->red_bits
;
4355 descr
->cAccumGreenBits
= mode
->green_bits
;
4356 descr
->cAccumBlueBits
= mode
->blue_bits
;
4357 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
4360 descr
->cDepthBits
= pf
->depth_bits
;
4361 descr
->cStencilBits
= pf
->stencil_bits
;
4362 descr
->cAuxBuffers
= pf
->aux_buffers
;
4363 descr
->iLayerType
= PFD_MAIN_PLANE
;
4365 TRACE("%s\n", debugstr_pf(pf
));
4366 return nb_displayable_formats
;
4369 /***********************************************************************
4370 * macdrv_wglCopyContext
4372 static BOOL WINAPI
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
4376 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
4378 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
4379 if (err
!= kCGLNoError
)
4380 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
4381 return (err
== kCGLNoError
);
4384 /***********************************************************************
4385 * macdrv_wglCreateContext
4387 static struct wgl_context
* WINAPI
macdrv_wglCreateContext(HDC hdc
)
4389 struct wgl_context
*context
;
4391 TRACE("hdc %p\n", hdc
);
4393 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
4398 /***********************************************************************
4399 * macdrv_wglDeleteContext
4401 static BOOL WINAPI
macdrv_wglDeleteContext(struct wgl_context
*context
)
4403 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
4405 pthread_mutex_lock(&context_mutex
);
4406 list_remove(&context
->entry
);
4407 pthread_mutex_unlock(&context_mutex
);
4409 macdrv_dispose_opengl_context(context
->context
);
4414 /***********************************************************************
4415 * macdrv_wglGetPixelFormat
4417 static int WINAPI
macdrv_wglGetPixelFormat(HDC hdc
)
4421 format
= get_dc_pixel_format(hdc
);
4423 if (!is_valid_pixel_format(format
)) /* not set yet */
4425 else if (!is_displayable_pixel_format(format
))
4427 /* Non-displayable formats can't be used with traditional WGL calls.
4428 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4432 TRACE(" hdc %p -> %d\n", hdc
, format
);
4436 /***********************************************************************
4437 * macdrv_wglGetProcAddress
4439 static PROC WINAPI
macdrv_wglGetProcAddress(const char *proc
)
4443 if (!strncmp(proc
, "wgl", 3)) return NULL
;
4444 ret
= dlsym(opengl_handle
, proc
);
4450 if (dladdr(ret
, &info
))
4451 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
4453 TRACE("%s -> %p (no library info)\n", proc
, ret
);
4457 WARN("failed to find proc %s\n", debugstr_a(proc
));
4461 /***********************************************************************
4462 * macdrv_wglMakeCurrent
4464 static BOOL WINAPI
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
4466 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4467 (context
? context
->cglcontext
: NULL
));
4469 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
4472 /**********************************************************************
4473 * macdrv_wglSetPixelFormat
4475 static BOOL WINAPI
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
4477 return set_pixel_format(hdc
, fmt
, FALSE
);
4480 /***********************************************************************
4481 * macdrv_wglShareLists
4483 static BOOL WINAPI
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
4485 macdrv_opengl_context saved_context
;
4486 CGLContextObj saved_cglcontext
;
4488 TRACE("org %p dest %p\n", org
, dest
);
4490 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4491 * at context creation time but in case of WGL it is done using wglShareLists.
4493 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4494 * and when a program requests sharing we recreate the destination context if it hasn't been made
4495 * current or when it hasn't shared display lists before.
4498 if (dest
->has_been_current
)
4500 WARN("could not share display lists, the destination context has been current already\n");
4503 else if (dest
->sharing
)
4505 WARN("could not share display lists because dest has already shared lists before\n");
4509 /* Re-create the Mac context and share display lists */
4510 saved_context
= dest
->context
;
4511 saved_cglcontext
= dest
->cglcontext
;
4512 dest
->context
= NULL
;
4513 dest
->cglcontext
= NULL
;
4514 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
4516 dest
->context
= saved_context
;
4517 dest
->cglcontext
= saved_cglcontext
;
4521 /* Implicitly disposes of saved_cglcontext. */
4522 macdrv_dispose_opengl_context(saved_context
);
4524 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4525 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
4527 org
->sharing
= TRUE
;
4528 dest
->sharing
= TRUE
;
4533 /**********************************************************************
4534 * macdrv_wglSwapBuffers
4536 static BOOL WINAPI
macdrv_wglSwapBuffers(HDC hdc
)
4538 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4542 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4543 (context
? context
->cglcontext
: NULL
));
4547 sync_swap_interval(context
);
4548 sync_context(context
);
4551 if ((hwnd
= NtUserWindowFromDC(hdc
)))
4553 struct macdrv_win_data
*data
;
4555 if (!(data
= get_win_data(hwnd
)))
4557 RtlSetLastWin32Error(ERROR_INVALID_HANDLE
);
4561 if (context
&& context
->draw_view
== data
->client_cocoa_view
)
4564 release_win_data(data
);
4568 struct wgl_pbuffer
*pbuffer
;
4570 pthread_mutex_lock(&dc_pbuffers_mutex
);
4571 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4572 pthread_mutex_unlock(&dc_pbuffers_mutex
);
4576 RtlSetLastWin32Error(ERROR_INVALID_HANDLE
);
4580 if (context
&& context
->draw_pbuffer
== pbuffer
)
4585 macdrv_flush_opengl_context(context
->context
);
4588 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
4590 /* If there is a current context, then wglSwapBuffers should do an implicit
4591 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4592 in the other branch, but we have to do it explicitly here. */
4600 static struct opengl_funcs opengl_funcs
=
4603 macdrv_wglCopyContext
, /* p_wglCopyContext */
4604 macdrv_wglCreateContext
, /* p_wglCreateContext */
4605 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
4606 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
4607 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
4608 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
4609 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
4610 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
4611 macdrv_wglShareLists
, /* p_wglShareLists */
4612 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
4616 /**********************************************************************
4617 * macdrv_wine_get_wgl_driver
4619 struct opengl_funcs
*macdrv_wine_get_wgl_driver(UINT version
)
4621 static pthread_once_t init_once
= PTHREAD_ONCE_INIT
;
4623 if (version
!= WINE_WGL_DRIVER_VERSION
)
4625 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
4629 pthread_once(&init_once
, init_opengl
);
4630 return opengl_handle
? &opengl_funcs
: (void *)-1;