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
29 #include "wine/debug.h"
31 #include "wine/wgl_driver.h"
33 #define GL_SILENCE_DEPRECATION
36 #include <OpenGL/OpenGL.h>
37 #include <OpenGL/glu.h>
38 #include <OpenGL/CGLRenderers.h>
41 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
47 char wglExtensions
[4096];
49 GLint max_viewport_dims
[2];
51 unsigned int max_major
, max_minor
;
54 static struct gl_info gl_info
;
62 macdrv_opengl_context context
;
63 CGLContextObj cglcontext
;
65 macdrv_view draw_view
;
67 struct wgl_pbuffer
*draw_pbuffer
;
68 macdrv_view read_view
;
70 struct wgl_pbuffer
*read_pbuffer
;
71 BOOL has_been_current
;
73 LONG update_swap_interval
;
75 DWORD last_flush_time
;
79 static struct list context_list
= LIST_INIT(context_list
);
80 static pthread_mutex_t context_mutex
= PTHREAD_MUTEX_INITIALIZER
;
85 CGLPBufferObj pbuffer
;
93 static CFMutableDictionaryRef dc_pbuffers
;
94 static pthread_mutex_t dc_pbuffers_mutex
= PTHREAD_MUTEX_INITIALIZER
;
97 static struct opengl_funcs opengl_funcs
;
99 #define USE_GL_FUNC(name) #name,
100 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
104 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
106 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
107 static void (*pglFinish
)(void);
108 static void (*pglFlush
)(void);
109 static void (*pglFlushRenderAPPLE
)(void);
110 static const GLubyte
*(*pglGetString
)(GLenum name
);
111 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
112 GLenum format
, GLenum type
, void *pixels
);
113 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
119 GLint color_bits
; /* including alpha_bits */
120 int red_bits
, red_shift
;
121 int green_bits
, green_shift
;
122 int blue_bits
, blue_shift
;
123 GLint alpha_bits
, alpha_shift
;
128 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
129 observations of the behavior of Windows systems, but also subjective judgments
130 about what color formats are more "normal" than others.
132 On at least some Windows systems, integer color formats are listed before
133 floating-point formats. Within the integer formats, higher color bits were
134 usually listed before lower color bits, while for floating-point formats it
135 was the reverse. However, that leads D3D to select 64-bit integer formats in
136 preference to 32-bit formats when the latter would be sufficient. It seems
137 that a 32-bit format is much more likely to be normally used in that case.
139 Also, there are certain odd color formats supported on the Mac which seem like
140 they would be less appropriate than more common ones. For instance, the color
141 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
142 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
145 For two color formats which differ only in whether or not they have alpha bits,
146 we use the same ordering. pixel_format_comparator() gives alpha bits a
147 different weight than color formats.
149 static const struct color_mode color_modes
[] = {
150 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
151 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
152 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
153 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
154 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
155 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
156 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
157 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
158 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
159 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
160 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
161 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
162 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
163 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
164 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
165 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
166 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
167 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
168 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
169 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
170 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
171 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
172 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
173 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
177 static const struct {
180 } depth_stencil_modes
[] = {
208 GLint max_aux_buffers
;
209 GLint max_sample_buffers
;
216 } renderer_properties
;
220 unsigned int window
:1;
221 unsigned int pbuffer
:1;
222 unsigned int accelerated
:1;
223 unsigned int color_mode
:5; /* index into color_modes table */
224 unsigned int aux_buffers
:3;
225 unsigned int depth_bits
:8;
226 unsigned int stencil_bits
:8;
227 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
228 unsigned int double_buffer
:1;
229 unsigned int stereo
:1;
230 unsigned int sample_buffers
:1;
231 unsigned int samples
:5;
232 unsigned int backing_store
:1;
240 } pixel_format_or_code
;
241 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
244 static pixel_format
*pixel_formats
;
245 static int nb_formats
, nb_displayable_formats
;
248 static void *opengl_handle
;
251 static const char* debugstr_attrib(int attrib
, int value
)
253 static const struct {
257 #define ATTRIB(a) { a, #a }
258 ATTRIB(WGL_ACCELERATION_ARB
),
259 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
260 ATTRIB(WGL_ACCUM_BITS_ARB
),
261 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
262 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
263 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
264 ATTRIB(WGL_ALPHA_BITS_ARB
),
265 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
266 ATTRIB(WGL_AUX_BUFFERS_ARB
),
267 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
268 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
269 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
270 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
271 ATTRIB(WGL_BLUE_BITS_ARB
),
272 ATTRIB(WGL_BLUE_SHIFT_ARB
),
273 ATTRIB(WGL_COLOR_BITS_ARB
),
274 ATTRIB(WGL_DEPTH_BITS_ARB
),
275 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
276 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
277 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
278 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
279 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
280 ATTRIB(WGL_GREEN_BITS_ARB
),
281 ATTRIB(WGL_GREEN_SHIFT_ARB
),
282 ATTRIB(WGL_NEED_PALETTE_ARB
),
283 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
284 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
285 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
286 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
287 ATTRIB(WGL_PIXEL_TYPE_ARB
),
288 ATTRIB(WGL_RED_BITS_ARB
),
289 ATTRIB(WGL_RED_SHIFT_ARB
),
290 ATTRIB(WGL_RENDERER_ID_WINE
),
291 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
292 ATTRIB(WGL_SAMPLES_ARB
),
293 ATTRIB(WGL_SHARE_ACCUM_ARB
),
294 ATTRIB(WGL_SHARE_DEPTH_ARB
),
295 ATTRIB(WGL_SHARE_STENCIL_ARB
),
296 ATTRIB(WGL_STENCIL_BITS_ARB
),
297 ATTRIB(WGL_STEREO_ARB
),
298 ATTRIB(WGL_SUPPORT_GDI_ARB
),
299 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
300 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
301 ATTRIB(WGL_SWAP_METHOD_ARB
),
302 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
303 ATTRIB(WGL_TRANSPARENT_ARB
),
304 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
305 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
306 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
307 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
311 const char *attrib_name
= NULL
;
312 const char *value_name
= NULL
;
314 for (i
= 0; i
< ARRAY_SIZE(attrib_names
); i
++)
316 if (attrib_names
[i
].attrib
== attrib
)
318 attrib_name
= attrib_names
[i
].name
;
324 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
328 case WGL_ACCELERATION_ARB
:
331 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
332 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
333 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
336 case WGL_PIXEL_TYPE_ARB
:
339 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
340 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
341 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
342 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
345 case WGL_SWAP_METHOD_ARB
:
348 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
349 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
350 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
356 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
358 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
362 /**********************************************************************
363 * active_displays_mask
365 static CGOpenGLDisplayMask
active_displays_mask(void)
368 CGDirectDisplayID displays
[32];
370 CGOpenGLDisplayMask mask
;
372 err
= CGGetActiveDisplayList(ARRAY_SIZE(displays
), displays
, &count
);
373 if (err
!= kCGErrorSuccess
)
375 displays
[0] = CGMainDisplayID();
380 for (i
= 0; i
< count
; i
++)
381 mask
|= CGDisplayIDToOpenGLDisplayMask(displays
[i
]);
387 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
388 CGLRendererProperty property
, GLint
*value
)
390 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
391 if (err
!= kCGLNoError
)
392 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
393 return (err
== kCGLNoError
);
397 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
401 memset(properties
, 0, sizeof(*properties
));
403 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
404 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
406 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
407 properties
->buffer_modes
= value
;
409 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
410 properties
->color_modes
= value
;
412 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
413 properties
->accum_modes
= value
;
415 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
416 properties
->depth_modes
= value
;
418 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
419 properties
->stencil_modes
= value
;
421 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
422 properties
->max_aux_buffers
= value
;
424 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
425 properties
->max_sample_buffers
= value
;
427 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
428 properties
->max_samples
= value
;
430 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
431 properties
->offscreen
= (value
!= 0);
433 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
434 properties
->accelerated
= (value
!= 0);
436 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
437 properties
->backing_store
= (value
!= 0);
439 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
440 properties
->window
= (value
!= 0);
442 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
443 properties
->online
= (value
!= 0);
447 static void dump_renderer(const renderer_properties
* renderer
)
451 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
452 TRACE("Buffer modes:\n");
453 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
454 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
455 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
456 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
458 TRACE("Color buffer modes:\n");
459 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
461 if (renderer
->color_modes
& color_modes
[i
].mode
)
463 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
464 if (color_modes
[i
].is_float
)
470 TRACE("Accumulation buffer sizes: { ");
471 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
473 if (renderer
->accum_modes
& color_modes
[i
].mode
)
474 TRACE("%d, ", color_modes
[i
].color_bits
);
478 TRACE("Depth buffer sizes: { ");
479 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
481 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
482 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
486 TRACE("Stencil buffer sizes: { ");
487 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
489 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
490 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
494 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
495 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
496 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
497 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
498 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
499 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
500 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
501 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
505 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
507 pixel_format_or_code pfc
;
510 pfc
.format
= *format
;
515 static inline pixel_format
pixel_format_for_code(UInt64 code
)
517 pixel_format_or_code pfc
;
524 static const char *debugstr_pf(const pixel_format
*pf
)
526 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",
530 color_modes
[pf
->color_mode
].color_bits
,
531 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
532 color_modes
[pf
->color_mode
].alpha_bits
,
535 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
542 code_for_pixel_format(pf
));
546 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
551 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
553 if ((modes
& color_modes
[i
].mode
) &&
554 color_modes
[i
].color_bits
>= color_size
&&
555 color_modes
[i
].alpha_bits
>= alpha_size
&&
556 !color_modes
[i
].is_float
== !color_float
)
558 if (best
< 0) /* no existing best choice */
560 else if (color_modes
[i
].color_bits
== color_size
&&
561 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
563 /* prefer it over a best which isn't exact or which has a higher bpp */
564 if (color_modes
[best
].color_bits
!= color_size
||
565 color_modes
[best
].alpha_bits
!= alpha_size
||
566 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
569 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
570 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
571 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
578 /* Couldn't find a match. Return first one that renderer supports. */
579 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
581 if (modes
& color_modes
[i
].mode
)
590 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
595 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
597 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
599 /* Prefer the fewest color bits, then prefer more alpha bits, then
600 prefer more bits per pixel. */
603 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
605 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
607 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
609 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
610 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
618 /* Couldn't find a match. Return last one that renderer supports. */
619 for (i
= ARRAY_SIZE(color_modes
) - 1; i
>= 0; i
--)
621 if (modes
& color_modes
[i
].mode
)
630 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
631 CFMutableSetRef pixel_format_set
)
633 CGLPixelFormatAttribute attribs
[64] = {
634 kCGLPFAMinimumPolicy
,
635 kCGLPFAClosestPolicy
,
636 kCGLPFARendererID
, renderer
.renderer_id
,
637 kCGLPFASingleRenderer
,
639 int n
= 5, n_stack
[16], n_stack_idx
= -1;
640 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
641 new_pixel_formats
= 0;
642 pixel_format request
;
643 unsigned int double_buffer
;
644 unsigned int accelerated
= renderer
.accelerated
;
648 attribs
[n
++] = kCGLPFAAccelerated
;
649 attribs
[n
++] = kCGLPFANoRecovery
;
651 else if (!allow_software_rendering
)
653 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
657 n_stack
[++n_stack_idx
] = n
;
658 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
662 n
= n_stack
[n_stack_idx
];
664 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
665 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
669 attribs
[n
++] = kCGLPFADoubleBuffer
;
670 memset(&request
, 0, sizeof(request
));
671 request
.accelerated
= accelerated
;
672 request
.double_buffer
= double_buffer
;
674 /* Don't bother with in-between aux buffers values: either 0 or max. */
675 n_stack
[++n_stack_idx
] = n
;
676 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
678 unsigned int color_mode
;
680 n
= n_stack
[n_stack_idx
];
682 attribs
[n
++] = kCGLPFAAuxBuffers
;
684 request
.aux_buffers
= aux
;
686 n_stack
[++n_stack_idx
] = n
;
687 for (color_mode
= 0; color_mode
< ARRAY_SIZE(color_modes
); color_mode
++)
689 unsigned int depth_mode
;
691 n
= n_stack
[n_stack_idx
];
693 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
696 attribs
[n
++] = kCGLPFAColorSize
;
697 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
698 attribs
[n
++] = kCGLPFAAlphaSize
;
699 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
700 if (color_modes
[color_mode
].is_float
)
701 attribs
[n
++] = kCGLPFAColorFloat
;
702 request
.color_mode
= color_mode
;
704 n_stack
[++n_stack_idx
] = n
;
705 for (depth_mode
= 0; depth_mode
< ARRAY_SIZE(depth_stencil_modes
); depth_mode
++)
707 unsigned int stencil_mode
;
709 n
= n_stack
[n_stack_idx
];
711 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
714 attribs
[n
++] = kCGLPFADepthSize
;
715 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
716 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
718 n_stack
[++n_stack_idx
] = n
;
719 for (stencil_mode
= 0; stencil_mode
< ARRAY_SIZE(depth_stencil_modes
); stencil_mode
++)
723 n
= n_stack
[n_stack_idx
];
725 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
727 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 &&
728 depth_stencil_modes
[depth_mode
].bits
!= 32 && stencil_mode
> 0)
731 attribs
[n
++] = kCGLPFAStencilSize
;
732 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
733 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
735 /* FIXME: Could trim search space a bit here depending on GPU.
736 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
737 n_stack
[++n_stack_idx
] = n
;
738 for (stereo
= 0; stereo
<= 1; stereo
++)
742 n
= n_stack
[n_stack_idx
];
744 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
745 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
749 attribs
[n
++] = kCGLPFAStereo
;
750 request
.stereo
= stereo
;
752 /* Starts at -1 for a 0 accum size */
753 n_stack
[++n_stack_idx
] = n
;
754 for (accum_mode
= -1; accum_mode
< (int) ARRAY_SIZE(color_modes
); accum_mode
++)
756 unsigned int target_pass
;
758 n
= n_stack
[n_stack_idx
];
762 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
765 attribs
[n
++] = kCGLPFAAccumSize
;
766 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
767 request
.accum_mode
= accum_mode
+ 1;
770 request
.accum_mode
= 0;
772 /* Targets to request are:
773 accelerated: window OR window + pbuffer
774 software: window + pbuffer */
775 n_stack
[++n_stack_idx
] = n
;
776 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
778 unsigned int samples
, max_samples
;
780 n
= n_stack
[n_stack_idx
];
782 attribs
[n
++] = kCGLPFAWindow
;
785 if (!accelerated
|| target_pass
> 0)
787 attribs
[n
++] = kCGLPFAPBuffer
;
793 /* FIXME: Could trim search space a bit here depending on GPU.
794 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
795 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
796 n_stack
[++n_stack_idx
] = n
;
797 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
798 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
800 unsigned int backing_store
, min_backing_store
, max_backing_store
;
802 n
= n_stack
[n_stack_idx
];
806 attribs
[n
++] = kCGLPFASampleBuffers
;
807 attribs
[n
++] = renderer
.max_sample_buffers
;
808 attribs
[n
++] = kCGLPFASamples
;
809 attribs
[n
++] = samples
;
810 request
.sample_buffers
= renderer
.max_sample_buffers
;
811 request
.samples
= samples
;
814 request
.sample_buffers
= request
.samples
= 0;
816 if (renderer
.backing_store
&& double_buffer
)
818 /* The software renderer seems to always preserve the backing store, whether
819 we ask for it or not. So don't bother not asking for it. */
820 min_backing_store
= accelerated
? 0 : 1;
821 max_backing_store
= 1;
824 min_backing_store
= max_backing_store
= 0;
825 n_stack
[++n_stack_idx
] = n
;
826 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
828 CGLPixelFormatObj pix
;
829 GLint virtualScreens
;
832 n
= n_stack
[n_stack_idx
];
835 attribs
[n
++] = kCGLPFABackingStore
;
836 request
.backing_store
= backing_store
;
840 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
841 if (err
== kCGLNoError
&& pix
)
844 GLint value
, color_size
, alpha_size
, color_float
;
846 CFNumberRef code_object
;
849 memset(&pf
, 0, sizeof(pf
));
851 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
852 pf
.accelerated
= value
;
853 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
854 pf
.aux_buffers
= value
;
855 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
856 pf
.depth_bits
= value
;
857 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
858 pf
.double_buffer
= value
;
859 if (pf
.double_buffer
&&
860 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
861 pf
.backing_store
= value
;
862 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
864 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
865 pf
.sample_buffers
= value
;
866 if (pf
.sample_buffers
&&
867 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
869 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
870 pf
.stencil_bits
= value
;
871 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
873 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
876 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
878 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
880 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
882 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
884 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
885 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
887 CGLReleasePixelFormat(pix
);
889 pf_code
= code_for_pixel_format(&pf
);
891 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
892 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
893 dupe_pixel_formats
++;
896 CFSetAddValue(pixel_format_set
, code_object
);
897 CFArrayAppendValue(pixel_format_array
, code_object
);
900 CFRelease(code_object
);
902 if (pf_code
== code_for_pixel_format(&request
))
903 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
906 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
907 dupe
? " (duplicate)" : "");
912 failed_pixel_formats
++;
913 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
916 tried_pixel_formats
++;
948 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
949 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
950 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
951 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
955 /* The docs for WGL_ARB_pixel_format say:
956 Indices are assigned to pixel formats in the following order:
957 1. Accelerated pixel formats that are displayable
958 2. Accelerated pixel formats that are displayable and which have
960 3. Generic pixel formats
961 4. Accelerated pixel formats that are non displayable
963 static int pixel_format_category(pixel_format pf
)
965 /* non-displayable */
969 /* non-accelerated a.k.a. software a.k.a. generic */
973 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
974 if (color_modes
[pf
.color_mode
].is_float
)
977 /* accelerated, displayable, no extended attributes */
982 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
984 CFNumberRef number1
= val1
;
985 CFNumberRef number2
= val2
;
987 pixel_format pf1
, pf2
;
988 int category1
, category2
;
990 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
991 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
992 pf1
= pixel_format_for_code(code1
);
993 pf2
= pixel_format_for_code(code2
);
994 category1
= pixel_format_category(pf1
);
995 category2
= pixel_format_category(pf2
);
997 if (category1
< category2
)
998 return kCFCompareLessThan
;
999 if (category1
> category2
)
1000 return kCFCompareGreaterThan
;
1002 /* Within a category, sort the "best" formats toward the front since that's
1003 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1004 matches at least one Windows 7 machine's behavior.
1006 /* Accelerated before unaccelerated. */
1007 if (pf1
.accelerated
&& !pf2
.accelerated
)
1008 return kCFCompareLessThan
;
1009 if (!pf1
.accelerated
&& pf2
.accelerated
)
1010 return kCFCompareGreaterThan
;
1012 /* Explicit color mode ordering. */
1013 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1014 return kCFCompareLessThan
;
1015 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1016 return kCFCompareGreaterThan
;
1018 /* Non-pbuffer-capable before pbuffer-capable. */
1019 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1020 return kCFCompareLessThan
;
1021 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1022 return kCFCompareGreaterThan
;
1024 /* Fewer samples before more samples. */
1025 if (pf1
.samples
< pf2
.samples
)
1026 return kCFCompareLessThan
;
1027 if (pf1
.samples
> pf2
.samples
)
1028 return kCFCompareGreaterThan
;
1030 /* Monoscopic before stereoscopic. (This is a guess.) */
1031 if (!pf1
.stereo
&& pf2
.stereo
)
1032 return kCFCompareLessThan
;
1033 if (pf1
.stereo
&& !pf2
.stereo
)
1034 return kCFCompareGreaterThan
;
1036 /* Single buffered before double buffered. */
1037 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1038 return kCFCompareLessThan
;
1039 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1040 return kCFCompareGreaterThan
;
1042 /* Possibly-optimized double buffering before backing-store-preserving
1043 double buffering. */
1044 if (!pf1
.backing_store
&& pf2
.backing_store
)
1045 return kCFCompareLessThan
;
1046 if (pf1
.backing_store
&& !pf2
.backing_store
)
1047 return kCFCompareGreaterThan
;
1049 /* Bigger depth buffer before smaller depth buffer. */
1050 if (pf1
.depth_bits
> pf2
.depth_bits
)
1051 return kCFCompareLessThan
;
1052 if (pf1
.depth_bits
< pf2
.depth_bits
)
1053 return kCFCompareGreaterThan
;
1055 /* Smaller stencil buffer before bigger stencil buffer. */
1056 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1057 return kCFCompareLessThan
;
1058 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1059 return kCFCompareGreaterThan
;
1061 /* Smaller alpha bits before larger alpha bits. */
1062 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1063 return kCFCompareLessThan
;
1064 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1065 return kCFCompareGreaterThan
;
1067 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1072 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1073 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1074 return kCFCompareLessThan
;
1075 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1076 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1077 return kCFCompareGreaterThan
;
1079 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1080 return kCFCompareLessThan
;
1081 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1082 return kCFCompareGreaterThan
;
1084 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1085 return kCFCompareLessThan
;
1086 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1087 return kCFCompareGreaterThan
;
1090 return kCFCompareGreaterThan
;
1092 else if (pf2
.accum_mode
)
1093 return kCFCompareLessThan
;
1095 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1096 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1097 return kCFCompareLessThan
;
1098 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1099 return kCFCompareGreaterThan
;
1101 /* If we get here, arbitrarily sort based on code. */
1103 return kCFCompareLessThan
;
1105 return kCFCompareGreaterThan
;
1106 return kCFCompareEqualTo
;
1110 static BOOL
init_pixel_formats(void)
1113 CGLRendererInfoObj renderer_info
;
1114 GLint rendererCount
;
1116 CFMutableSetRef pixel_format_set
;
1117 CFMutableArrayRef pixel_format_array
;
1123 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1126 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1130 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1131 if (!pixel_format_set
)
1133 WARN("CFSetCreateMutable failed\n");
1134 CGLDestroyRendererInfo(renderer_info
);
1138 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1139 if (!pixel_format_array
)
1141 WARN("CFArrayCreateMutable failed\n");
1142 CFRelease(pixel_format_set
);
1143 CGLDestroyRendererInfo(renderer_info
);
1147 for (i
= 0; i
< rendererCount
; i
++)
1149 renderer_properties renderer
;
1151 get_renderer_properties(renderer_info
, i
, &renderer
);
1154 TRACE("renderer_properties %d:\n", i
);
1155 dump_renderer(&renderer
);
1158 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1161 CFRelease(pixel_format_set
);
1162 CGLDestroyRendererInfo(renderer_info
);
1164 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1167 pixel_formats
= malloc(range
.length
* sizeof(*pixel_formats
));
1170 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1171 for (i
= 0; i
< range
.length
; i
++)
1173 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1176 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1177 pixel_formats
[i
] = pixel_format_for_code(code
);
1178 if (pixel_formats
[i
].window
)
1179 nb_displayable_formats
++;
1182 nb_formats
= range
.length
;
1183 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1187 WARN("failed to allocate pixel format list\n");
1190 WARN("got no pixel formats\n");
1192 CFRelease(pixel_format_array
);
1197 static inline BOOL
is_valid_pixel_format(int format
)
1199 return format
> 0 && format
<= nb_formats
;
1203 static inline BOOL
is_displayable_pixel_format(int format
)
1205 return format
> 0 && format
<= nb_displayable_formats
;
1209 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1211 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1212 * format in case of probing the number of pixel formats.
1214 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1216 TRACE("Returning format %d\n", format
);
1217 return &pixel_formats
[format
- 1];
1223 static BOOL
init_gl_info(void)
1225 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1226 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1228 CGDirectDisplayID display
= CGMainDisplayID();
1229 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1230 CGLPixelFormatAttribute attribs
[] = {
1231 kCGLPFADisplayMask
, displayMask
,
1234 CGLPixelFormatAttribute core_attribs
[] =
1236 kCGLPFADisplayMask
, displayMask
,
1238 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1241 CGLPixelFormatObj pix
;
1242 GLint virtualScreens
;
1244 CGLContextObj context
;
1245 CGLContextObj old_context
= CGLGetCurrentContext();
1249 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1250 if (err
!= kCGLNoError
|| !pix
)
1252 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1256 err
= CGLCreateContext(pix
, NULL
, &context
);
1257 CGLReleasePixelFormat(pix
);
1258 if (err
!= kCGLNoError
|| !context
)
1260 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1264 err
= CGLSetCurrentContext(context
);
1265 if (err
!= kCGLNoError
)
1267 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1268 CGLReleaseContext(context
);
1272 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1273 length
= strlen(str
) + sizeof(legacy_extensions
);
1275 length
+= strlen(legacy_ext_swap_control
);
1276 gl_info
.glExtensions
= malloc(length
);
1277 strcpy(gl_info
.glExtensions
, str
);
1278 strcat(gl_info
.glExtensions
, legacy_extensions
);
1280 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1282 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1284 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1285 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1286 TRACE("GL version : %s\n", str
);
1287 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1289 CGLSetCurrentContext(old_context
);
1290 CGLReleaseContext(context
);
1292 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1293 if (err
!= kCGLNoError
|| !pix
)
1295 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1296 err
, CGLErrorString(err
));
1300 err
= CGLCreateContext(pix
, NULL
, &context
);
1301 CGLReleasePixelFormat(pix
);
1302 if (err
!= kCGLNoError
|| !context
)
1304 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1305 err
, CGLErrorString(err
));
1309 err
= CGLSetCurrentContext(context
);
1310 if (err
!= kCGLNoError
)
1312 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1313 err
, CGLErrorString(err
));
1314 CGLReleaseContext(context
);
1318 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1319 TRACE("Core context GL version: %s\n", str
);
1320 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1321 CGLSetCurrentContext(old_context
);
1322 CGLReleaseContext(context
);
1328 static int get_dc_pixel_format(HDC hdc
)
1333 if ((hwnd
= NtUserWindowFromDC(hdc
)))
1335 struct macdrv_win_data
*data
;
1337 if (!(data
= get_win_data(hwnd
)))
1339 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1343 format
= data
->pixel_format
;
1344 release_win_data(data
);
1348 struct wgl_pbuffer
*pbuffer
;
1350 pthread_mutex_lock(&dc_pbuffers_mutex
);
1351 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1353 format
= pbuffer
->format
;
1356 WARN("no window or pbuffer for DC %p\n", hdc
);
1359 pthread_mutex_unlock(&dc_pbuffers_mutex
);
1366 /**********************************************************************
1369 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1371 const pixel_format
*pf
;
1372 CGLPixelFormatAttribute attribs
[64];
1374 CGLPixelFormatObj pix
;
1375 GLint virtualScreens
;
1377 BOOL core
= major
>= 3;
1379 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1382 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1383 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1387 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1388 attribs
[n
++] = kCGLPFAClosestPolicy
;
1390 if (context
->renderer_id
)
1392 attribs
[n
++] = kCGLPFARendererID
;
1393 attribs
[n
++] = context
->renderer_id
;
1394 attribs
[n
++] = kCGLPFASingleRenderer
;
1395 attribs
[n
++] = kCGLPFANoRecovery
;
1398 if (pf
->accelerated
)
1400 attribs
[n
++] = kCGLPFAAccelerated
;
1401 attribs
[n
++] = kCGLPFANoRecovery
;
1405 attribs
[n
++] = kCGLPFARendererID
;
1406 attribs
[n
++] = kCGLRendererGenericFloatID
;
1409 if (pf
->double_buffer
)
1410 attribs
[n
++] = kCGLPFADoubleBuffer
;
1414 attribs
[n
++] = kCGLPFAAuxBuffers
;
1415 attribs
[n
++] = pf
->aux_buffers
;
1418 attribs
[n
++] = kCGLPFAColorSize
;
1419 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1420 attribs
[n
++] = kCGLPFAAlphaSize
;
1421 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1422 if (color_modes
[pf
->color_mode
].is_float
)
1423 attribs
[n
++] = kCGLPFAColorFloat
;
1425 attribs
[n
++] = kCGLPFADepthSize
;
1426 attribs
[n
++] = pf
->depth_bits
;
1428 attribs
[n
++] = kCGLPFAStencilSize
;
1429 attribs
[n
++] = pf
->stencil_bits
;
1432 attribs
[n
++] = kCGLPFAStereo
;
1434 if (pf
->accum_mode
&& !core
)
1436 attribs
[n
++] = kCGLPFAAccumSize
;
1437 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1440 if (pf
->pbuffer
&& !core
)
1441 attribs
[n
++] = kCGLPFAPBuffer
;
1443 if (pf
->sample_buffers
&& pf
->samples
)
1445 attribs
[n
++] = kCGLPFASampleBuffers
;
1446 attribs
[n
++] = pf
->sample_buffers
;
1447 attribs
[n
++] = kCGLPFASamples
;
1448 attribs
[n
++] = pf
->samples
;
1451 if (pf
->backing_store
)
1452 attribs
[n
++] = kCGLPFABackingStore
;
1456 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1457 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1459 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1461 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1463 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1469 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1470 if (err
!= kCGLNoError
|| !pix
)
1472 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1473 SetLastError(ERROR_INVALID_OPERATION
);
1477 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1478 CGLReleasePixelFormat(pix
);
1479 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1481 context
->cglcontext
= NULL
;
1482 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1483 SetLastError(ERROR_INVALID_OPERATION
);
1487 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1490 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1491 if (err
!= kCGLNoError
)
1492 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1494 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1497 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1498 if (err
!= kCGLNoError
)
1499 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1502 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1503 CGLReleaseContext(context
->cglcontext
);
1504 if (!context
->context
)
1506 WARN("macdrv_create_opengl_context() failed\n");
1507 SetLastError(ERROR_INVALID_OPERATION
);
1510 context
->major
= major
;
1512 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1514 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1520 /**********************************************************************
1523 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1525 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1527 struct macdrv_win_data
*data
;
1528 const pixel_format
*pf
;
1529 HWND hwnd
= NtUserWindowFromDC(hdc
);
1532 TRACE("hdc %p format %d\n", hdc
, fmt
);
1534 if (!hwnd
|| hwnd
== NtUserGetDesktopWindow())
1536 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1540 if (!(data
= get_win_data(hwnd
)))
1542 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1546 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1548 ret
= (data
->pixel_format
== fmt
);
1552 /* Check if fmt is in our list of supported formats to see if it is supported. */
1553 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1556 ERR("Invalid pixel format: %d\n", fmt
);
1562 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1566 data
->pixel_format
= fmt
;
1568 TRACE("pixel format:\n");
1569 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1570 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1571 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1572 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1573 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1574 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1575 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1576 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1577 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1578 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1579 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1580 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1581 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1582 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1586 release_win_data(data
);
1587 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) NtUserSetWindowPixelFormat(hwnd
, fmt
);
1592 /**********************************************************************
1593 * mark_contexts_for_moved_view
1595 static void mark_contexts_for_moved_view(macdrv_view view
)
1597 struct wgl_context
*context
;
1599 pthread_mutex_lock(&context_mutex
);
1600 LIST_FOR_EACH_ENTRY(context
, &context_list
, struct wgl_context
, entry
)
1602 if (context
->draw_view
== view
)
1603 InterlockedExchange(&context
->view_moved
, TRUE
);
1605 pthread_mutex_unlock(&context_mutex
);
1609 /**********************************************************************
1612 static BOOL
sync_context_rect(struct wgl_context
*context
)
1615 if (InterlockedCompareExchange(&context
->view_moved
, FALSE
, TRUE
))
1617 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1619 if (data
&& data
->client_cocoa_view
== context
->draw_view
)
1621 RECT rect
= data
->client_rect
;
1622 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1623 if (!EqualRect(&context
->draw_rect
, &rect
))
1625 context
->draw_rect
= rect
;
1629 release_win_data(data
);
1635 /**********************************************************************
1636 * make_context_current
1638 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1642 struct wgl_pbuffer
*pbuffer
;
1646 view
= context
->read_view
;
1647 view_rect
= context
->read_rect
;
1648 pbuffer
= context
->read_pbuffer
;
1652 sync_context_rect(context
);
1654 view
= context
->draw_view
;
1655 view_rect
= context
->draw_rect
;
1656 pbuffer
= context
->draw_pbuffer
;
1659 if (view
|| !pbuffer
)
1660 macdrv_make_context_current(context
->context
, view
, cgrect_from_rect(view_rect
));
1665 if (CGLIsEnabled(context
->cglcontext
, kCGLCESurfaceBackingSize
, &enabled
) == kCGLNoError
&& enabled
)
1666 CGLDisable(context
->cglcontext
, kCGLCESurfaceBackingSize
);
1667 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1669 CGLSetCurrentContext(context
->cglcontext
);
1674 /**********************************************************************
1677 static void sync_context(struct wgl_context
*context
)
1679 if (sync_context_rect(context
))
1680 make_context_current(context
, FALSE
);
1684 /**********************************************************************
1687 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1691 /* In theory, for single-buffered contexts, there's no such thing as a swap
1692 so the swap interval shouldn't matter. But OS X will synchronize flushes
1693 of single-buffered contexts if the interval is set to non-zero. */
1694 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1697 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1698 if (err
!= kCGLNoError
)
1699 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1701 return err
== kCGLNoError
;
1705 /**********************************************************************
1706 * sync_swap_interval
1708 static void sync_swap_interval(struct wgl_context
*context
)
1710 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1716 else if (context
->draw_hwnd
)
1718 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1721 interval
= data
->swap_interval
;
1722 release_win_data(data
);
1724 else /* window was destroyed? */
1730 set_swap_interval(context
, interval
);
1735 /**********************************************************************
1736 * get_iokit_display_property
1738 static BOOL
get_iokit_display_property(CGLRendererInfoObj renderer_info
, GLint renderer
, CFStringRef property
, GLuint
* value
)
1744 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, &accelerated
) || !accelerated
)
1746 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1750 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPDisplayMask
, &display_mask
))
1752 WARN("failed to get kCGLRPDisplayMask\n");
1756 for (i
= 0; i
< sizeof(GLint
) * 8; i
++)
1758 GLint this_display_mask
= (GLint
)(1U << i
);
1759 if (this_display_mask
& display_mask
)
1761 CGDirectDisplayID display_id
= CGOpenGLDisplayMaskToDisplayID(this_display_mask
);
1762 io_service_t service
;
1764 uint32_t prop_value
;
1768 service
= CGDisplayIOServicePort(display_id
);
1771 WARN("CGDisplayIOServicePort(%u) failed\n", display_id
);
1775 data
= IORegistryEntrySearchCFProperty(service
, kIOServicePlane
, property
, NULL
,
1776 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1779 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property
), display_id
);
1782 if (CFGetTypeID(data
) != CFDataGetTypeID())
1784 WARN("property %s is not a data object: %s\n", debugstr_cf(property
), debugstr_cf(data
));
1788 if (CFDataGetLength(data
) != sizeof(prop_value
))
1790 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property
), display_id
,
1791 (unsigned long long)CFDataGetLength(data
));
1796 CFDataGetBytes(data
, CFRangeMake(0, sizeof(prop_value
)), (UInt8
*)&prop_value
);
1798 *value
= prop_value
;
1807 /**********************************************************************
1808 * create_pixel_format_for_renderer
1810 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1811 * responsible for releasing the pixel format object.
1813 static CGLPixelFormatObj
create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info
, GLint renderer
, BOOL core
)
1816 CGLPixelFormatAttribute attrs
[] = {
1817 kCGLPFARendererID
, 0,
1818 kCGLPFASingleRenderer
,
1819 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1823 CGLPixelFormatObj pixel_format
;
1824 GLint virtual_screens
;
1828 attrs
[3] = kCGLPFAOpenGLProfile
;
1829 attrs
[4] = (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
;
1832 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
1835 attrs
[1] = renderer_id
;
1836 err
= CGLChoosePixelFormat(attrs
, &pixel_format
, &virtual_screens
);
1837 if (err
!= kCGLNoError
)
1838 pixel_format
= NULL
;
1839 return pixel_format
;
1843 /**********************************************************************
1844 * map_renderer_index
1846 * We can't create pixel formats for all renderers listed. For example,
1847 * in a dual-GPU system, the integrated GPU is typically unavailable
1848 * when the discrete GPU is active.
1850 * This function conceptually creates a list of "good" renderers from the
1851 * list of all renderers. It treats the input "renderer" parameter as an
1852 * index into that list of good renderers and returns the corresponding
1853 * index into the list of all renderers.
1855 static GLint
map_renderer_index(CGLRendererInfoObj renderer_info
, GLint renderer_count
, GLint renderer
)
1857 GLint good_count
, i
;
1860 for (i
= 0; i
< renderer_count
; i
++)
1862 CGLPixelFormatObj pix
= create_pixel_format_for_renderer(renderer_info
, i
, FALSE
);
1865 CGLReleasePixelFormat(pix
);
1867 if (good_count
> renderer
)
1871 TRACE("skipping bad renderer %d\n", i
);
1874 TRACE("mapped requested renderer %d to index %d\n", renderer
, i
);
1879 /**********************************************************************
1882 static const char* get_gl_string(CGLPixelFormatObj pixel_format
, GLenum name
)
1884 const char* ret
= NULL
;
1885 CGLContextObj context
, old_context
;
1888 err
= CGLCreateContext(pixel_format
, NULL
, &context
);
1889 if (err
== kCGLNoError
&& context
)
1891 old_context
= CGLGetCurrentContext();
1892 err
= CGLSetCurrentContext(context
);
1893 if (err
== kCGLNoError
)
1895 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(name
);
1896 CGLSetCurrentContext(old_context
);
1899 WARN("CGLSetCurrentContext failed: %d %s\n", err
, CGLErrorString(err
));
1900 CGLReleaseContext(context
);
1903 WARN("CGLCreateContext failed: %d %s\n", err
, CGLErrorString(err
));
1909 /**********************************************************************
1910 * get_fallback_renderer_version
1912 static void get_fallback_renderer_version(GLuint
*value
)
1914 BOOL got_it
= FALSE
;
1915 CFURLRef url
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1916 kCFURLPOSIXPathStyle
, TRUE
);
1919 CFBundleRef bundle
= CFBundleCreate(NULL
, url
);
1923 CFStringRef version
= CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleVersionKey
);
1924 if (version
&& CFGetTypeID(version
) == CFStringGetTypeID())
1926 size_t len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(version
), kCFStringEncodingUTF8
);
1927 char* buf
= malloc(len
);
1928 if (buf
&& CFStringGetCString(version
, buf
, len
, kCFStringEncodingUTF8
))
1930 unsigned int major
, minor
, bugfix
;
1931 int count
= sscanf(buf
, "%u.%u.%u", &major
, &minor
, &bugfix
);
1951 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1952 earliest version that the Mac driver supports. */
1960 /**********************************************************************
1961 * parse_renderer_version
1963 * Get the renderer version from the OpenGL version string. Assumes
1964 * the string is of the form
1965 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
1966 * where major, minor, and bugfix are what we're interested in. This
1967 * form for the vendor specific information is not generally applicable,
1968 * but seems reliable on OS X.
1970 static BOOL
parse_renderer_version(const char* version
, GLuint
*value
)
1972 const char* p
= strchr(version
, ' ');
1974 unsigned int major
, minor
, bugfix
;
1976 if (p
) p
= strchr(p
+ 1, '-');
1977 if (!p
) return FALSE
;
1979 count
= sscanf(p
+ 1, "%u.%u.%u", &major
, &minor
, &bugfix
);
1994 /**********************************************************************
1995 * query_renderer_integer
1997 static BOOL
query_renderer_integer(CGLRendererInfoObj renderer_info
, GLint renderer
, GLenum attribute
, GLuint
*value
)
2005 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
2007 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer
, renderer_id
, attribute
, value
);
2012 case WGL_RENDERER_ACCELERATED_WINE
:
2013 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, (GLint
*)value
))
2017 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value
);
2020 case WGL_RENDERER_DEVICE_ID_WINE
:
2021 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("device-id"), value
);
2024 *value
= 0xffffffff;
2027 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value
);
2030 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE
:
2031 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
:
2033 BOOL core
= (attribute
== WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
);
2034 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, core
);
2038 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2040 CGLReleasePixelFormat(pixel_format
);
2043 unsigned int major
, minor
;
2045 if (sscanf(version
, "%u.%u", &major
, &minor
) == 2)
2056 value
[0] = value
[1] = 0;
2059 TRACE("%s -> %u.%u\n", core
? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2060 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value
[0], value
[1]);
2064 case WGL_RENDERER_PREFERRED_PROFILE_WINE
:
2066 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2070 CGLReleasePixelFormat(pixel_format
);
2071 *value
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
2072 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2076 *value
= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
2077 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2083 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE
:
2084 /* FIXME: no API to query this */
2087 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value
);
2090 case WGL_RENDERER_VENDOR_ID_WINE
:
2091 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("vendor-id"), value
);
2094 *value
= 0xffffffff;
2097 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value
);
2100 case WGL_RENDERER_VERSION_WINE
:
2102 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2105 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
2108 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2110 CGLReleasePixelFormat(pixel_format
);
2112 ret
= parse_renderer_version(version
, value
);
2117 get_fallback_renderer_version(value
);
2120 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
2124 case WGL_RENDERER_VIDEO_MEMORY_WINE
:
2125 err
= CGLDescribeRenderer(renderer_info
, renderer
, kCGLRPVideoMemoryMegabytes
, (GLint
*)value
);
2126 if (err
!= kCGLNoError
&& err
!= kCGLBadProperty
)
2127 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err
, CGLErrorString(err
));
2128 if (err
!= kCGLNoError
)
2130 if (get_renderer_property(renderer_info
, renderer
, kCGLRPVideoMemory
, (GLint
*)value
))
2131 *value
/= 1024 * 1024;
2136 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value
);
2140 FIXME("unrecognized attribute 0x%04x\n", attribute
);
2148 /**********************************************************************
2149 * macdrv_glCopyColorTable
2151 * Hook into glCopyColorTable as part of the implementation of
2152 * wglMakeContextCurrentARB. If the context has a separate readable,
2153 * temporarily make that current, do glCopyColorTable, and then set it
2154 * back to the drawable. This is modeled after what Mesa GLX's Apple
2155 * implementation does.
2157 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
2160 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2162 if (context
->read_view
|| context
->read_pbuffer
)
2163 make_context_current(context
, TRUE
);
2165 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
2167 if (context
->read_view
|| context
->read_pbuffer
)
2168 make_context_current(context
, FALSE
);
2172 /**********************************************************************
2173 * macdrv_glCopyPixels
2175 * Hook into glCopyPixels as part of the implementation of
2176 * wglMakeContextCurrentARB. If the context has a separate readable,
2177 * temporarily make that current, do glCopyPixels, and then set it back
2178 * to the drawable. This is modeled after what Mesa GLX's Apple
2179 * implementation does.
2181 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
2183 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2185 if (context
->read_view
|| context
->read_pbuffer
)
2186 make_context_current(context
, TRUE
);
2188 pglCopyPixels(x
, y
, width
, height
, type
);
2190 if (context
->read_view
|| context
->read_pbuffer
)
2191 make_context_current(context
, FALSE
);
2195 /**********************************************************************
2198 static void macdrv_glFinish(void)
2200 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2202 sync_swap_interval(context
);
2203 sync_context(context
);
2208 /**********************************************************************
2211 static void macdrv_glFlush(void)
2213 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2215 sync_swap_interval(context
);
2216 sync_context(context
);
2218 if (skip_single_buffer_flushes
)
2220 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
2221 DWORD now
= NtGetTickCount();
2223 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
2224 context
->last_flush_time
, now
);
2225 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
2227 TRACE("calling glFlushRenderAPPLE()\n");
2228 pglFlushRenderAPPLE();
2233 TRACE("calling glFlush()\n");
2234 context
->last_flush_time
= now
;
2242 /**********************************************************************
2243 * macdrv_glGetString
2245 * Hook into glGetString in order to return some legacy WGL extensions
2246 * that couldn't be advertised via the standard
2247 * WGL_ARB_extensions_string mechanism. Some programs, especially
2248 * older ones, expect to find certain older extensions, such as
2249 * WGL_EXT_extensions_string itself, in the standard GL extensions
2250 * string, and won't query any other WGL extensions unless they find
2251 * that particular extension there.
2253 static const GLubyte
*macdrv_glGetString(GLenum name
)
2255 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
2256 return (const GLubyte
*)gl_info
.glExtensions
;
2258 return pglGetString(name
);
2262 /**********************************************************************
2263 * macdrv_glReadPixels
2265 * Hook into glReadPixels as part of the implementation of
2266 * wglMakeContextCurrentARB. If the context has a separate readable,
2267 * temporarily make that current, do glReadPixels, and then set it back
2268 * to the drawable. This is modeled after what Mesa GLX's Apple
2269 * implementation does.
2271 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2272 GLenum format
, GLenum type
, void *pixels
)
2274 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2276 if (context
->read_view
|| context
->read_pbuffer
)
2277 make_context_current(context
, TRUE
);
2279 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2281 if (context
->read_view
|| context
->read_pbuffer
)
2282 make_context_current(context
, FALSE
);
2286 /**********************************************************************
2289 * Hook into glViewport as an opportunity to update the OpenGL context
2290 * if necessary. This is modeled after what Mesa GLX's Apple
2291 * implementation does.
2293 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2295 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2297 sync_context(context
);
2298 macdrv_update_opengl_context(context
->context
);
2299 pglViewport(x
, y
, width
, height
);
2303 /***********************************************************************
2304 * macdrv_wglBindTexImageARB
2306 * WGL_ARB_render_texture: wglBindTexImageARB
2308 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2310 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2314 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
2316 if (pbuffer
->no_texture
)
2318 SetLastError(ERROR_INVALID_OPERATION
);
2322 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
2323 opengl_funcs
.gl
.p_glFlush();
2327 case WGL_FRONT_LEFT_ARB
:
2328 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2329 source
= GL_FRONT_LEFT
;
2333 case WGL_FRONT_RIGHT_ARB
:
2334 source
= GL_FRONT_RIGHT
;
2336 case WGL_BACK_LEFT_ARB
:
2337 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2338 source
= GL_BACK_LEFT
;
2342 case WGL_BACK_RIGHT_ARB
:
2343 source
= GL_BACK_RIGHT
;
2345 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
2346 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
2347 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
2348 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
2356 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
2357 SetLastError(ERROR_INVALID_DATA
);
2361 WARN("unknown source buffer 0x%x\n", iBuffer
);
2362 SetLastError(ERROR_INVALID_DATA
);
2366 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
2367 if (err
!= kCGLNoError
)
2369 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2370 SetLastError(ERROR_INVALID_OPERATION
);
2378 /***********************************************************************
2379 * macdrv_wglChoosePixelFormatARB
2381 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2383 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2384 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2385 int *piFormats
, UINT
*nNumFormats
)
2387 pixel_format pf
, valid
;
2389 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2390 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2395 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2396 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2398 FIXME("unused pfAttribFList\n");
2400 memset(&pf
, 0, sizeof(pf
));
2401 memset(&valid
, 0, sizeof(valid
));
2402 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2403 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2407 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2410 int value
= iptr
[1];
2412 TRACE("%s\n", debugstr_attrib(attr
, value
));
2416 case WGL_DRAW_TO_WINDOW_ARB
:
2417 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2418 pf
.window
= (value
!= 0);
2422 case WGL_DRAW_TO_BITMAP_ARB
:
2425 case WGL_ACCELERATION_ARB
:
2426 if (value
== WGL_FULL_ACCELERATION_ARB
)
2428 else if (value
== WGL_NO_ACCELERATION_ARB
)
2432 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2433 pf
.accelerated
= value
;
2434 valid
.accelerated
= 1;
2437 case WGL_NEED_PALETTE_ARB
:
2438 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2439 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2440 if (value
) goto cant_match
;
2443 case WGL_SWAP_METHOD_ARB
:
2444 if (value
== WGL_SWAP_COPY_ARB
)
2446 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2450 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2451 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2452 pf
.backing_store
= value
;
2453 valid
.backing_store
= 1;
2456 case WGL_NUMBER_OVERLAYS_ARB
:
2457 case WGL_NUMBER_UNDERLAYS_ARB
:
2458 if (value
) goto cant_match
;
2461 case WGL_SHARE_DEPTH_ARB
:
2462 case WGL_SHARE_STENCIL_ARB
:
2463 case WGL_SHARE_ACCUM_ARB
:
2467 case WGL_SUPPORT_GDI_ARB
:
2468 if (value
) goto cant_match
;
2471 case WGL_SUPPORT_OPENGL_ARB
:
2472 if (!value
) goto cant_match
;
2475 case WGL_DOUBLE_BUFFER_ARB
:
2476 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2477 pf
.double_buffer
= (value
!= 0);
2478 valid
.double_buffer
= 1;
2479 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2482 case WGL_STEREO_ARB
:
2483 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2484 pf
.stereo
= (value
!= 0);
2488 case WGL_PIXEL_TYPE_ARB
:
2489 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2491 else if (value
== WGL_TYPE_RGBA_ARB
)
2495 /* Mac contexts don't support rendering to unsigned floating
2496 point formats, even if GL_EXT_packed_float is supported.
2497 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2500 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2501 if (srgb
&& value
) goto cant_match
;
2502 float_color
= value
;
2505 case WGL_COLOR_BITS_ARB
:
2506 if (color_bits
< value
) color_bits
= value
;
2509 case WGL_RED_BITS_ARB
:
2510 if (srgb
&& value
> 8) goto cant_match
;
2511 if (red_bits
< value
) red_bits
= value
;
2514 case WGL_GREEN_BITS_ARB
:
2515 if (srgb
&& value
> 8) goto cant_match
;
2516 if (green_bits
< value
) green_bits
= value
;
2519 case WGL_BLUE_BITS_ARB
:
2520 if (srgb
&& value
> 8) goto cant_match
;
2521 if (blue_bits
< value
) blue_bits
= value
;
2524 case WGL_ALPHA_BITS_ARB
:
2525 if (alpha_bits
< value
) alpha_bits
= value
;
2528 case WGL_ACCUM_BITS_ARB
:
2529 if (accum_bits
< value
) accum_bits
= value
;
2532 case WGL_ACCUM_RED_BITS_ARB
:
2533 if (accum_red_bits
< value
) accum_red_bits
= value
;
2536 case WGL_ACCUM_GREEN_BITS_ARB
:
2537 if (accum_green_bits
< value
) accum_green_bits
= value
;
2540 case WGL_ACCUM_BLUE_BITS_ARB
:
2541 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2544 case WGL_ACCUM_ALPHA_BITS_ARB
:
2545 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2548 case WGL_DEPTH_BITS_ARB
:
2549 if (value
> 255) goto cant_match
;
2550 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2553 case WGL_STENCIL_BITS_ARB
:
2554 if (value
> 255) goto cant_match
;
2555 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2558 case WGL_AUX_BUFFERS_ARB
:
2559 if (value
> 7) goto cant_match
;
2560 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2563 case WGL_SAMPLE_BUFFERS_ARB
:
2564 if (value
> 1) goto cant_match
;
2565 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2568 case WGL_SAMPLES_ARB
:
2569 if (value
> 31) goto cant_match
;
2570 if (pf
.samples
< value
) pf
.samples
= value
;
2573 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2574 /* sRGB is only supported for 8-bit integer color components */
2575 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2580 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2581 case WGL_RED_SHIFT_ARB
:
2582 case WGL_GREEN_SHIFT_ARB
:
2583 case WGL_BLUE_SHIFT_ARB
:
2584 case WGL_ALPHA_SHIFT_ARB
:
2585 case WGL_TRANSPARENT_ARB
:
2586 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2587 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2588 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2589 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2590 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2594 case WGL_DRAW_TO_PBUFFER_ARB
:
2595 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2596 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2597 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2598 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2599 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2600 pf
.pbuffer
= (value
!= 0);
2602 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2608 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2613 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",
2614 valid
.window
? (pf
.window
? "1" : "0") : "?",
2615 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2616 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2618 float_color
== -1 ? "?" : float_color
? "f" : "",
2632 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2633 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2634 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2638 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2640 const struct color_mode
*mode
;
2642 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2643 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2644 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2645 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2646 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2647 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2649 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2650 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2651 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2652 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2653 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2655 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2656 /* If the mode doesn't have alpha, check requested color bits against
2657 bits per pixel instead of the mode's color bits. On Windows, color
2658 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2659 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2660 expects that to match such a pixel format, we need to accommodate that. */
2661 if (mode
->alpha_bits
)
2663 if (mode
->color_bits
< color_bits
)
2668 if (mode
->bits_per_pixel
< color_bits
)
2671 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2672 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2674 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2675 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2678 if (pixel_formats
[i
].accum_mode
)
2680 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2681 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2682 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2683 mode
->alpha_bits
< accum_alpha_bits
)
2686 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2689 piFormats
[found
++] = i
+ 1;
2690 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2694 *nNumFormats
= found
;
2700 /***********************************************************************
2701 * macdrv_wglCreateContextAttribsARB
2703 * WGL_ARB_create_context: wglCreateContextAttribsARB
2705 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2706 struct wgl_context
*share_context
,
2707 const int *attrib_list
)
2710 struct wgl_context
*context
;
2712 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2714 GLint renderer_id
= 0;
2716 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2718 format
= get_dc_pixel_format(hdc
);
2720 if (!is_valid_pixel_format(format
))
2722 ERR("Invalid pixel format %d, expect problems!\n", format
);
2723 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2727 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2730 int value
= iptr
[1];
2732 TRACE("%s\n", debugstr_attrib(attr
, value
));
2736 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2740 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2744 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2745 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2748 case WGL_CONTEXT_FLAGS_ARB
:
2750 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2751 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2752 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2755 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2756 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2757 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2759 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2760 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2766 case WGL_RENDERER_ID_WINE
:
2769 CGLRendererInfoObj renderer_info
;
2770 GLint renderer_count
, temp
;
2772 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
2773 if (err
!= kCGLNoError
)
2775 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
2776 SetLastError(ERROR_GEN_FAILURE
);
2780 value
= map_renderer_index(renderer_info
, renderer_count
, value
);
2782 if (value
>= renderer_count
)
2784 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value
, renderer_count
);
2785 CGLDestroyRendererInfo(renderer_info
);
2786 SetLastError(ERROR_INVALID_PARAMETER
);
2790 if (!get_renderer_property(renderer_info
, value
, kCGLRPRendererID
, &temp
))
2792 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value
);
2793 CGLDestroyRendererInfo(renderer_info
);
2794 SetLastError(ERROR_GEN_FAILURE
);
2798 CGLDestroyRendererInfo(renderer_info
);
2800 if (renderer_id
&& temp
!= renderer_id
)
2802 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id
, temp
);
2803 SetLastError(ERROR_INVALID_PARAMETER
);
2811 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2812 SetLastError(ERROR_INVALID_PARAMETER
);
2817 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2818 (major
== 4 && (minor
== 0 || minor
== 1)))
2820 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2822 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2823 SetLastError(ERROR_INVALID_VERSION_ARB
);
2826 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2828 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2829 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2832 if (major
> gl_info
.max_major
||
2833 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2835 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2837 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2842 else if (major
>= 3)
2844 WARN("Profile version %u.%u not supported\n", major
, minor
);
2845 SetLastError(ERROR_INVALID_VERSION_ARB
);
2848 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2849 (major
== 2 && (minor
< 0 || minor
> 1)))
2851 WARN("Invalid GL version requested\n");
2852 SetLastError(ERROR_INVALID_VERSION_ARB
);
2855 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2857 WARN("Forward compatible context requested for GL version < 3\n");
2858 SetLastError(ERROR_INVALID_VERSION_ARB
);
2862 if (!(context
= calloc(1, sizeof(*context
)))) return NULL
;
2864 context
->format
= format
;
2865 context
->renderer_id
= renderer_id
;
2866 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2872 pthread_mutex_lock(&context_mutex
);
2873 list_add_tail(&context_list
, &context
->entry
);
2874 pthread_mutex_unlock(&context_mutex
);
2880 /**********************************************************************
2881 * macdrv_wglCreatePbufferARB
2883 * WGL_ARB_pbuffer: wglCreatePbufferARB
2885 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2886 const int *piAttribList
)
2888 struct wgl_pbuffer
* pbuffer
;
2890 GLenum internalFormat
= 0;
2893 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2894 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2896 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2898 WARN("invalid pixel format %d\n", iPixelFormat
);
2899 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2903 pbuffer
= calloc(1, sizeof(*pbuffer
));
2904 pbuffer
->format
= iPixelFormat
;
2906 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2908 int attr
= piAttribList
[0];
2909 int value
= piAttribList
[1];
2913 case WGL_PBUFFER_LARGEST_ARB
:
2914 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2917 case WGL_TEXTURE_FORMAT_ARB
:
2920 case WGL_TEXTURE_RGBA_ARB
:
2921 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2922 internalFormat
= GL_RGBA
;
2924 case WGL_TEXTURE_RGB_ARB
:
2925 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2926 internalFormat
= GL_RGB
;
2928 case WGL_NO_TEXTURE_ARB
:
2929 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2933 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2934 SetLastError(ERROR_INVALID_DATA
);
2939 case WGL_TEXTURE_TARGET_ARB
:
2943 case WGL_NO_TEXTURE_ARB
:
2944 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2947 case WGL_TEXTURE_CUBE_MAP_ARB
:
2948 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2949 target
= GL_TEXTURE_CUBE_MAP
;
2950 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2952 case WGL_TEXTURE_1D_ARB
:
2953 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2954 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2956 case WGL_TEXTURE_2D_ARB
:
2957 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2958 target
= GL_TEXTURE_2D
;
2960 case WGL_TEXTURE_RECTANGLE_NV
:
2961 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2962 target
= GL_TEXTURE_RECTANGLE
;
2965 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2966 SetLastError(ERROR_INVALID_DATA
);
2971 case WGL_MIPMAP_TEXTURE_ARB
:
2972 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2973 pbuffer
->max_level
= 0;
2976 int size
= min(iWidth
, iHeight
) / 2;
2979 pbuffer
->max_level
++;
2986 WARN("unknown attribute 0x%x\n", attr
);
2987 SetLastError(ERROR_INVALID_DATA
);
2992 if (!target
|| !internalFormat
)
2994 pbuffer
->no_texture
= TRUE
;
2995 /* no actual way to turn off ability to texture; use most permissive target */
2996 target
= GL_TEXTURE_RECTANGLE
;
2997 internalFormat
= GL_RGB
;
3000 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
3001 if (err
!= kCGLNoError
)
3003 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
3004 pbuffer
->pbuffer
= NULL
;
3005 if (err
== kCGLBadAlloc
)
3006 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
3008 SetLastError(ERROR_INVALID_DATA
);
3012 if (!pbuffer
->pbuffer
)
3018 TRACE(" -> %p\n", pbuffer
);
3023 /**********************************************************************
3024 * macdrv_wglDestroyPbufferARB
3026 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3028 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
3030 TRACE("pbuffer %p\n", pbuffer
);
3031 if (pbuffer
&& pbuffer
->pbuffer
)
3032 CGLReleasePBuffer(pbuffer
->pbuffer
);
3038 /**********************************************************************
3039 * macdrv_wglGetExtensionsStringARB
3041 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3043 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
3045 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3046 this can be specific to the CGL renderer like we're supposed to do. */
3047 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3048 return gl_info
.wglExtensions
;
3052 /**********************************************************************
3053 * macdrv_wglGetExtensionsStringEXT
3055 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3057 static const char *macdrv_wglGetExtensionsStringEXT(void)
3059 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3060 return gl_info
.wglExtensions
;
3064 /**********************************************************************
3065 * macdrv_wglGetPbufferDCARB
3067 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3069 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
3072 struct wgl_pbuffer
*prev
;
3074 hdc
= NtGdiOpenDCW(NULL
, NULL
, NULL
, 0, TRUE
, NULL
, NULL
, NULL
);
3077 pthread_mutex_lock(&dc_pbuffers_mutex
);
3078 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3081 CGLReleasePBuffer(prev
->pbuffer
);
3084 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
3085 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3087 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
3092 /**********************************************************************
3093 * macdrv_wglGetPixelFormatAttribivARB
3095 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3097 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3098 UINT nAttributes
, const int *piAttributes
, int *piValues
)
3100 const pixel_format
*pf
;
3103 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3104 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
3106 if (!nAttributes
) return GL_TRUE
;
3108 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
3110 piValues
[0] = nb_formats
;
3111 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
3115 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
3118 WARN("invalid pixel format %d\n", iPixelFormat
);
3119 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3123 for (i
= 0; i
< nAttributes
; ++i
)
3125 switch (piAttributes
[i
])
3127 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
3128 piValues
[i
] = nb_formats
;
3131 case WGL_DRAW_TO_WINDOW_ARB
:
3132 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
3135 case WGL_DRAW_TO_BITMAP_ARB
:
3136 piValues
[i
] = GL_FALSE
;
3139 case WGL_ACCELERATION_ARB
:
3140 if (iLayerPlane
) goto invalid_layer
;
3141 if (pf
->accelerated
)
3142 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
3144 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
3147 case WGL_NEED_PALETTE_ARB
:
3148 case WGL_NEED_SYSTEM_PALETTE_ARB
:
3149 case WGL_SWAP_LAYER_BUFFERS_ARB
:
3150 piValues
[i
] = GL_FALSE
;
3153 case WGL_SWAP_METHOD_ARB
:
3154 if (pf
->double_buffer
&& pf
->backing_store
)
3155 piValues
[i
] = WGL_SWAP_COPY_ARB
;
3157 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
3160 case WGL_NUMBER_OVERLAYS_ARB
:
3161 case WGL_NUMBER_UNDERLAYS_ARB
:
3165 case WGL_TRANSPARENT_ARB
:
3166 if (iLayerPlane
) goto invalid_layer
;
3167 piValues
[i
] = GL_FALSE
;
3170 case WGL_TRANSPARENT_RED_VALUE_ARB
:
3171 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
3172 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
3173 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
3174 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
3175 if (iLayerPlane
) goto invalid_layer
;
3179 case WGL_SHARE_DEPTH_ARB
:
3180 case WGL_SHARE_STENCIL_ARB
:
3181 case WGL_SHARE_ACCUM_ARB
:
3182 if (iLayerPlane
) goto invalid_layer
;
3183 piValues
[i
] = GL_TRUE
;
3186 case WGL_SUPPORT_GDI_ARB
:
3187 if (iLayerPlane
) goto invalid_layer
;
3188 piValues
[i
] = GL_FALSE
;
3191 case WGL_SUPPORT_OPENGL_ARB
:
3192 if (iLayerPlane
) goto invalid_layer
;
3193 piValues
[i
] = GL_TRUE
;
3196 case WGL_DOUBLE_BUFFER_ARB
:
3197 if (iLayerPlane
) goto invalid_layer
;
3198 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
3201 case WGL_STEREO_ARB
:
3202 if (iLayerPlane
) goto invalid_layer
;
3203 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
3206 case WGL_PIXEL_TYPE_ARB
:
3207 if (iLayerPlane
) goto invalid_layer
;
3208 if (color_modes
[pf
->color_mode
].is_float
)
3209 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
3211 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
3212 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3213 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3214 However, Mac contexts don't support rendering to unsigned floating-point
3215 formats, even when GL_EXT_packed_float is supported. */
3218 case WGL_COLOR_BITS_ARB
:
3219 if (iLayerPlane
) goto invalid_layer
;
3220 /* If the mode doesn't have alpha, return bits per pixel instead
3221 of color bits. On Windows, color bits sometimes exceeds r+g+b
3222 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3223 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3224 pixel format, we need to accommodate that. */
3225 if (color_modes
[pf
->color_mode
].alpha_bits
)
3226 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
3228 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
3231 case WGL_RED_BITS_ARB
:
3232 if (iLayerPlane
) goto invalid_layer
;
3233 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
3236 case WGL_RED_SHIFT_ARB
:
3237 if (iLayerPlane
) goto invalid_layer
;
3238 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
3241 case WGL_GREEN_BITS_ARB
:
3242 if (iLayerPlane
) goto invalid_layer
;
3243 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
3246 case WGL_GREEN_SHIFT_ARB
:
3247 if (iLayerPlane
) goto invalid_layer
;
3248 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
3251 case WGL_BLUE_BITS_ARB
:
3252 if (iLayerPlane
) goto invalid_layer
;
3253 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
3256 case WGL_BLUE_SHIFT_ARB
:
3257 if (iLayerPlane
) goto invalid_layer
;
3258 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
3261 case WGL_ALPHA_BITS_ARB
:
3262 if (iLayerPlane
) goto invalid_layer
;
3263 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
3266 case WGL_ALPHA_SHIFT_ARB
:
3267 if (iLayerPlane
) goto invalid_layer
;
3268 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
3271 case WGL_ACCUM_BITS_ARB
:
3272 if (iLayerPlane
) goto invalid_layer
;
3274 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3279 case WGL_ACCUM_RED_BITS_ARB
:
3280 if (iLayerPlane
) goto invalid_layer
;
3282 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
3287 case WGL_ACCUM_GREEN_BITS_ARB
:
3288 if (iLayerPlane
) goto invalid_layer
;
3290 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
3295 case WGL_ACCUM_BLUE_BITS_ARB
:
3296 if (iLayerPlane
) goto invalid_layer
;
3298 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
3303 case WGL_ACCUM_ALPHA_BITS_ARB
:
3304 if (iLayerPlane
) goto invalid_layer
;
3306 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
3311 case WGL_DEPTH_BITS_ARB
:
3312 if (iLayerPlane
) goto invalid_layer
;
3313 piValues
[i
] = pf
->depth_bits
;
3316 case WGL_STENCIL_BITS_ARB
:
3317 if (iLayerPlane
) goto invalid_layer
;
3318 piValues
[i
] = pf
->stencil_bits
;
3321 case WGL_AUX_BUFFERS_ARB
:
3322 if (iLayerPlane
) goto invalid_layer
;
3323 piValues
[i
] = pf
->aux_buffers
;
3326 case WGL_SAMPLE_BUFFERS_ARB
:
3327 if (iLayerPlane
) goto invalid_layer
;
3328 piValues
[i
] = pf
->sample_buffers
;
3331 case WGL_SAMPLES_ARB
:
3332 if (iLayerPlane
) goto invalid_layer
;
3333 piValues
[i
] = pf
->samples
;
3336 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3337 if (iLayerPlane
) goto invalid_layer
;
3338 /* sRGB is only supported for 8-bit integer color components */
3339 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
3340 color_modes
[pf
->color_mode
].green_bits
== 8 &&
3341 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
3342 !color_modes
[pf
->color_mode
].is_float
)
3343 piValues
[i
] = GL_TRUE
;
3345 piValues
[i
] = GL_FALSE
;
3348 case WGL_DRAW_TO_PBUFFER_ARB
:
3349 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
3350 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
3351 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
3354 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
3355 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
3356 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
3359 case WGL_MAX_PBUFFER_WIDTH_ARB
:
3360 piValues
[i
] = gl_info
.max_viewport_dims
[0];
3363 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
3364 piValues
[i
] = gl_info
.max_viewport_dims
[1];
3367 case WGL_MAX_PBUFFER_PIXELS_ARB
:
3368 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
3372 WARN("invalid attribute %x\n", piAttributes
[i
]);
3376 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
3382 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
3387 /**********************************************************************
3388 * macdrv_wglGetPixelFormatAttribfvARB
3390 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3392 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3393 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
3398 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3399 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
3401 /* Allocate a temporary array to store integer values */
3402 attr
= malloc(nAttributes
* sizeof(int));
3405 ERR("couldn't allocate %d array\n", nAttributes
);
3409 /* Piggy-back on wglGetPixelFormatAttribivARB */
3410 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
3415 /* Convert integer values to float. Should also check for attributes
3416 that can give decimal values here */
3417 for (i
= 0; i
< nAttributes
; i
++)
3418 pfValues
[i
] = attr
[i
];
3426 /**********************************************************************
3427 * macdrv_wglGetSwapIntervalEXT
3429 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3431 static int macdrv_wglGetSwapIntervalEXT(void)
3433 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3434 struct macdrv_win_data
*data
;
3440 if ((data
= get_win_data(context
->draw_hwnd
)))
3442 value
= data
->swap_interval
;
3443 release_win_data(data
);
3445 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3446 set_swap_interval(context
, allow_vsync
? value
: 0);
3450 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3451 if (err
!= kCGLNoError
)
3453 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3454 err
, CGLErrorString(err
));
3463 /***********************************************************************
3464 * macdrv_wglMakeContextCurrentARB
3466 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3468 * This is not supported directly by OpenGL on the Mac. We emulate it
3469 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3470 * temporarily swap the drawable. This follows the technique used in
3471 * the implementation of Mesa GLX for Apple.
3473 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3475 struct macdrv_win_data
*data
;
3478 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3479 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3483 macdrv_make_context_current(NULL
, NULL
, CGRectNull
);
3484 NtCurrentTeb()->glContext
= NULL
;
3488 if ((hwnd
= NtUserWindowFromDC(draw_hdc
)))
3490 if (!(data
= get_win_data(hwnd
)))
3492 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3496 if (!data
->pixel_format
)
3498 WARN("no pixel format set\n");
3499 release_win_data(data
);
3500 SetLastError(ERROR_INVALID_HANDLE
);
3503 if (context
->format
!= data
->pixel_format
)
3505 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3506 release_win_data(data
);
3507 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3511 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
)
3512 set_swap_interval(context
, allow_vsync
? data
->swap_interval
: 0);
3514 context
->draw_hwnd
= hwnd
;
3515 context
->draw_view
= data
->client_cocoa_view
;
3516 context
->draw_rect
= data
->client_rect
;
3517 OffsetRect(&context
->draw_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3518 context
->draw_pbuffer
= NULL
;
3519 release_win_data(data
);
3523 struct wgl_pbuffer
*pbuffer
;
3525 pthread_mutex_lock(&dc_pbuffers_mutex
);
3526 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3529 if (context
->format
!= pbuffer
->format
)
3531 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3532 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3533 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3537 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
)
3538 set_swap_interval(context
, 0);
3542 WARN("no window or pbuffer for DC\n");
3543 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3544 SetLastError(ERROR_INVALID_HANDLE
);
3548 context
->draw_hwnd
= NULL
;
3549 context
->draw_view
= NULL
;
3550 context
->draw_pbuffer
= pbuffer
;
3551 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3554 context
->read_view
= NULL
;
3555 context
->read_pbuffer
= NULL
;
3556 if (read_hdc
&& read_hdc
!= draw_hdc
)
3558 if ((hwnd
= NtUserWindowFromDC(read_hdc
)))
3560 if ((data
= get_win_data(hwnd
)))
3562 if (data
->client_cocoa_view
!= context
->draw_view
)
3564 context
->read_view
= data
->client_cocoa_view
;
3565 context
->read_rect
= data
->client_rect
;
3566 OffsetRect(&context
->read_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3568 release_win_data(data
);
3573 pthread_mutex_lock(&dc_pbuffers_mutex
);
3574 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3575 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3579 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3580 context
->draw_view
, wine_dbgstr_rect(&context
->draw_rect
), context
->draw_pbuffer
,
3581 context
->read_view
, wine_dbgstr_rect(&context
->read_rect
), context
->read_pbuffer
, context
->format
);
3583 make_context_current(context
, FALSE
);
3584 context
->has_been_current
= TRUE
;
3585 NtCurrentTeb()->glContext
= context
;
3591 /**********************************************************************
3592 * macdrv_wglQueryCurrentRendererIntegerWINE
3594 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3596 static BOOL
macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute
, GLuint
*value
)
3599 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3600 CGLPixelFormatObj pixel_format
;
3602 GLint virtual_screen
;
3604 GLint pf_renderer_id
;
3605 CGLRendererInfoObj renderer_info
;
3606 GLint renderer_count
;
3609 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context
, (context
? context
->context
: NULL
),
3610 (context
? context
->cglcontext
: NULL
), attribute
, value
);
3612 if (attribute
== WGL_RENDERER_VERSION_WINE
)
3614 if (!parse_renderer_version((const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
), value
))
3615 get_fallback_renderer_version(value
);
3616 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
3620 pixel_format
= CGLGetPixelFormat(context
->cglcontext
);
3621 err
= CGLGetVirtualScreen(context
->cglcontext
, &virtual_screen
);
3622 if (err
!= kCGLNoError
)
3624 WARN("CGLGetVirtualScreen failed: %d %s\n", err
, CGLErrorString(err
));
3628 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFADisplayMask
, &display_mask
);
3629 if (err
!= kCGLNoError
)
3631 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err
, CGLErrorString(err
));
3635 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFARendererID
, &pf_renderer_id
);
3636 if (err
!= kCGLNoError
)
3638 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err
, CGLErrorString(err
));
3642 err
= CGLQueryRendererInfo(display_mask
, &renderer_info
, &renderer_count
);
3643 if (err
!= kCGLNoError
)
3645 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3649 for (renderer
= 0; renderer
< renderer_count
; renderer
++)
3653 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
3656 if (renderer_id
== pf_renderer_id
)
3658 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3663 if (renderer
>= renderer_count
)
3664 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id
, display_mask
);
3666 CGLDestroyRendererInfo(renderer_info
);
3671 /**********************************************************************
3672 * macdrv_wglQueryCurrentRendererStringWINE
3674 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3676 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute
)
3678 const char* ret
= NULL
;
3679 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3681 TRACE("context %p/%p/%p attribute 0x%04x\n", context
, (context
? context
->context
: NULL
),
3682 (context
? context
->cglcontext
: NULL
), attribute
);
3686 case WGL_RENDERER_DEVICE_ID_WINE
:
3688 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_RENDERER
);
3689 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret
));
3693 case WGL_RENDERER_VENDOR_ID_WINE
:
3695 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VENDOR
);
3696 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret
));
3701 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3709 /**********************************************************************
3710 * macdrv_wglQueryPbufferARB
3712 * WGL_ARB_pbuffer: wglQueryPbufferARB
3714 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3720 GLenum internalFormat
;
3723 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3725 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3726 if (err
!= kCGLNoError
)
3728 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3729 SetLastError(ERROR_INVALID_HANDLE
);
3735 case WGL_PBUFFER_WIDTH_ARB
:
3738 case WGL_PBUFFER_HEIGHT_ARB
:
3741 case WGL_PBUFFER_LOST_ARB
:
3742 /* Mac PBuffers can't be lost */
3743 *piValue
= GL_FALSE
;
3745 case WGL_TEXTURE_FORMAT_ARB
:
3746 if (pbuffer
->no_texture
)
3747 *piValue
= WGL_NO_TEXTURE_ARB
;
3748 else switch (internalFormat
)
3751 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3755 *piValue
= WGL_TEXTURE_RGB_ARB
;
3759 case WGL_TEXTURE_TARGET_ARB
:
3760 if (pbuffer
->no_texture
)
3761 *piValue
= WGL_NO_TEXTURE_ARB
;
3762 else switch (target
)
3764 case GL_TEXTURE_CUBE_MAP
:
3765 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3768 *piValue
= WGL_TEXTURE_2D_ARB
;
3770 case GL_TEXTURE_RECTANGLE
:
3772 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3776 case WGL_MIPMAP_TEXTURE_ARB
:
3777 *piValue
= (pbuffer
->max_level
> 0);
3779 case WGL_MIPMAP_LEVEL_ARB
:
3780 *piValue
= pbuffer
->level
;
3782 case WGL_CUBE_MAP_FACE_ARB
:
3783 switch (pbuffer
->face
)
3785 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3787 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3789 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3790 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3792 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3793 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3795 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3796 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3799 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3801 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3802 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3807 WARN("invalid attribute 0x%x\n", iAttribute
);
3808 SetLastError(ERROR_INVALID_DATA
);
3816 /**********************************************************************
3817 * macdrv_wglQueryRendererIntegerWINE
3819 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3821 static BOOL
macdrv_wglQueryRendererIntegerWINE(HDC dc
, GLint renderer
, GLenum attribute
, GLuint
*value
)
3824 CGLRendererInfoObj renderer_info
;
3825 GLint renderer_count
;
3828 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc
, renderer
, attribute
, value
);
3830 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3831 if (err
!= kCGLNoError
)
3833 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3837 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3839 if (renderer
< renderer_count
)
3840 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3842 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3844 CGLDestroyRendererInfo(renderer_info
);
3849 /**********************************************************************
3850 * macdrv_wglQueryRendererStringWINE
3852 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3854 static const char *macdrv_wglQueryRendererStringWINE(HDC dc
, GLint renderer
, GLenum attribute
)
3856 const char* ret
= NULL
;
3857 CGLRendererInfoObj renderer_info
;
3858 GLint renderer_count
;
3861 TRACE("dc %p renderer %d attribute 0x%04x\n", dc
, renderer
, attribute
);
3863 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3864 if (err
!= kCGLNoError
)
3866 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3870 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3872 if (renderer
>= renderer_count
)
3874 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3880 case WGL_RENDERER_DEVICE_ID_WINE
:
3881 case WGL_RENDERER_VENDOR_ID_WINE
:
3883 BOOL device
= (attribute
== WGL_RENDERER_DEVICE_ID_WINE
);
3884 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
3887 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
3890 ret
= get_gl_string(pixel_format
, device
? GL_RENDERER
: GL_VENDOR
);
3891 CGLReleasePixelFormat(pixel_format
);
3894 TRACE("%s -> %s\n", device
? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret
));
3899 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3904 CGLDestroyRendererInfo(renderer_info
);
3909 /**********************************************************************
3910 * macdrv_wglReleasePbufferDCARB
3912 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3914 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3916 struct wgl_pbuffer
*prev
;
3918 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3920 pthread_mutex_lock(&dc_pbuffers_mutex
);
3922 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3925 if (prev
!= pbuffer
)
3926 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3927 CGLReleasePBuffer(prev
->pbuffer
);
3929 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3933 pthread_mutex_unlock(&dc_pbuffers_mutex
);
3935 return hdc
&& NtGdiDeleteObjectApp(hdc
);
3939 /**********************************************************************
3940 * macdrv_wglReleaseTexImageARB
3942 * WGL_ARB_render_texture: wglReleaseTexImageARB
3944 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3946 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3949 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3951 if (pbuffer
->no_texture
)
3953 SetLastError(ERROR_INVALID_OPERATION
);
3957 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3958 if (err
!= kCGLNoError
)
3960 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3961 SetLastError(ERROR_INVALID_OPERATION
);
3969 /**********************************************************************
3970 * macdrv_wglSetPbufferAttribARB
3972 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3974 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
3976 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3978 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
3980 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3982 int attr
= piAttribList
[0];
3983 int value
= piAttribList
[1];
3986 case WGL_MIPMAP_LEVEL_ARB
:
3987 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
3988 pbuffer
->level
= value
;
3990 case WGL_CUBE_MAP_FACE_ARB
:
3993 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3994 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3995 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
3997 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3998 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3999 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
4001 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4002 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4003 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
4005 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4006 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4007 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
4009 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4010 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4011 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
4013 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4014 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4015 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
4018 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
4019 SetLastError(ERROR_INVALID_DATA
);
4024 WARN("invalid attribute 0x%x\n", attr
);
4025 SetLastError(ERROR_INVALID_DATA
);
4030 if (context
&& context
->draw_pbuffer
== pbuffer
)
4031 make_context_current(context
, FALSE
);
4037 /**********************************************************************
4038 * macdrv_wglSetPixelFormatWINE
4040 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4042 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
4044 return set_pixel_format(hdc
, fmt
, TRUE
);
4048 /**********************************************************************
4049 * macdrv_wglSwapIntervalEXT
4051 * WGL_EXT_swap_control: wglSwapIntervalEXT
4053 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
4055 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4056 BOOL changed
= FALSE
;
4058 TRACE("interval %d\n", interval
);
4062 SetLastError(ERROR_INVALID_DATA
);
4068 if (context
->draw_hwnd
)
4070 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
4073 changed
= data
->swap_interval
!= interval
;
4075 data
->swap_interval
= interval
;
4076 release_win_data(data
);
4085 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
4086 if (!set_swap_interval(context
, interval
))
4088 SetLastError(ERROR_GEN_FAILURE
);
4094 struct wgl_context
*ctx
;
4096 pthread_mutex_lock(&context_mutex
);
4097 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
4099 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
4100 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
4102 pthread_mutex_unlock(&context_mutex
);
4109 static void register_extension(const char *ext
)
4111 if (gl_info
.wglExtensions
[0])
4112 strcat(gl_info
.wglExtensions
, " ");
4113 strcat(gl_info
.wglExtensions
, ext
);
4115 TRACE("'%s'\n", ext
);
4118 static void load_extensions(void)
4123 register_extension("WGL_ARB_extensions_string");
4124 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
4126 register_extension("WGL_ARB_make_current_read");
4127 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
4128 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
4130 register_extension("WGL_ARB_pixel_format");
4131 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
4132 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
4133 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
4135 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
4137 register_extension("WGL_ARB_pixel_format_float");
4138 register_extension("WGL_ATI_pixel_format_float");
4141 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
4142 register_extension("WGL_ARB_multisample");
4144 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4145 register_extension("WGL_ARB_framebuffer_sRGB");
4147 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
4149 register_extension("WGL_ARB_pbuffer");
4150 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
4151 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
4152 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
4153 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
4154 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
4156 register_extension("WGL_ARB_render_texture");
4157 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
4158 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
4159 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
4161 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
4162 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
4163 register_extension("WGL_NV_render_texture_rectangle");
4166 register_extension("WGL_ARB_create_context");
4167 register_extension("WGL_ARB_create_context_profile");
4168 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
4173 register_extension("WGL_EXT_extensions_string");
4174 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
4178 register_extension("WGL_EXT_swap_control");
4179 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
4180 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
4183 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4184 check for either, so register them separately. */
4185 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4186 register_extension("WGL_EXT_framebuffer_sRGB");
4188 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
4189 register_extension("WGL_EXT_pixel_format_packed_float");
4192 * WINE-specific WGL Extensions
4195 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4196 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4198 register_extension("WGL_WINE_pixel_format_passthrough");
4199 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
4201 register_extension("WGL_WINE_query_renderer");
4202 opengl_funcs
.ext
.p_wglQueryCurrentRendererIntegerWINE
= macdrv_wglQueryCurrentRendererIntegerWINE
;
4203 opengl_funcs
.ext
.p_wglQueryCurrentRendererStringWINE
= macdrv_wglQueryCurrentRendererStringWINE
;
4204 opengl_funcs
.ext
.p_wglQueryRendererIntegerWINE
= macdrv_wglQueryRendererIntegerWINE
;
4205 opengl_funcs
.ext
.p_wglQueryRendererStringWINE
= macdrv_wglQueryRendererStringWINE
;
4209 static void init_opengl(void)
4215 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
4218 WARN("CFDictionaryCreateMutable failed\n");
4222 opengl_handle
= dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
);
4225 ERR("Failed to load OpenGL: %s\n", dlerror());
4226 ERR("OpenGL support is disabled.\n");
4230 for (i
= 0; i
< ARRAY_SIZE(opengl_func_names
); i
++)
4232 if (!(((void **)&opengl_funcs
.gl
)[i
] = dlsym(opengl_handle
, opengl_func_names
[i
])))
4234 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
4239 if (!init_gl_info())
4242 /* redirect some standard OpenGL functions */
4243 #define REDIRECT(func) \
4244 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4245 REDIRECT(glCopyPixels
);
4246 REDIRECT(glGetString
);
4247 REDIRECT(glReadPixels
);
4248 REDIRECT(glViewport
);
4249 if (skip_single_buffer_flushes
|| allow_vsync
)
4255 /* redirect some OpenGL extension functions */
4256 #define REDIRECT(func) \
4257 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4258 REDIRECT(glCopyColorTable
);
4261 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
4262 pglFlushRenderAPPLE
= dlsym(opengl_handle
, "glFlushRenderAPPLE");
4265 if (!init_pixel_formats())
4271 dlclose(opengl_handle
);
4272 opengl_handle
= NULL
;
4276 /***********************************************************************
4279 * Synchronize the Mac GL view position with the Windows child window
4282 void sync_gl_view(struct macdrv_win_data
* data
, const RECT
* old_whole_rect
, const RECT
* old_client_rect
)
4284 if (data
->client_cocoa_view
&& data
->pixel_format
)
4286 RECT old
= *old_client_rect
, new = data
->client_rect
;
4288 OffsetRect(&old
, -old_whole_rect
->left
, -old_whole_rect
->top
);
4289 OffsetRect(&new, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
4290 if (!EqualRect(&old
, &new))
4292 TRACE("GL view %p changed position; marking contexts\n", data
->client_cocoa_view
);
4293 mark_contexts_for_moved_view(data
->client_cocoa_view
);
4299 /**********************************************************************
4300 * macdrv_wglDescribePixelFormat
4302 static int WINAPI
macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
4304 const pixel_format
*pf
;
4305 const struct color_mode
*mode
;
4307 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
4309 if (!descr
) return nb_displayable_formats
;
4310 if (size
< sizeof(*descr
)) return 0;
4312 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
4315 memset(descr
, 0, sizeof(*descr
));
4316 descr
->nSize
= sizeof(*descr
);
4317 descr
->nVersion
= 1;
4319 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
4320 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
4321 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
4322 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
4323 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
4324 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
4326 descr
->iPixelType
= PFD_TYPE_RGBA
;
4328 mode
= &color_modes
[pf
->color_mode
];
4329 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4330 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4331 R8G8B8A0 pixel format). If an app depends on that and expects that
4332 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4333 if (mode
->alpha_bits
)
4334 descr
->cColorBits
= mode
->color_bits
;
4336 descr
->cColorBits
= mode
->bits_per_pixel
;
4337 descr
->cRedBits
= mode
->red_bits
;
4338 descr
->cRedShift
= mode
->red_shift
;
4339 descr
->cGreenBits
= mode
->green_bits
;
4340 descr
->cGreenShift
= mode
->green_shift
;
4341 descr
->cBlueBits
= mode
->blue_bits
;
4342 descr
->cBlueShift
= mode
->blue_shift
;
4343 descr
->cAlphaBits
= mode
->alpha_bits
;
4344 descr
->cAlphaShift
= mode
->alpha_shift
;
4348 mode
= &color_modes
[pf
->accum_mode
- 1];
4349 descr
->cAccumBits
= mode
->color_bits
;
4350 descr
->cAccumRedBits
= mode
->red_bits
;
4351 descr
->cAccumGreenBits
= mode
->green_bits
;
4352 descr
->cAccumBlueBits
= mode
->blue_bits
;
4353 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
4356 descr
->cDepthBits
= pf
->depth_bits
;
4357 descr
->cStencilBits
= pf
->stencil_bits
;
4358 descr
->cAuxBuffers
= pf
->aux_buffers
;
4359 descr
->iLayerType
= PFD_MAIN_PLANE
;
4361 TRACE("%s\n", debugstr_pf(pf
));
4362 return nb_displayable_formats
;
4365 /***********************************************************************
4366 * macdrv_wglCopyContext
4368 static BOOL WINAPI
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
4372 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
4374 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
4375 if (err
!= kCGLNoError
)
4376 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
4377 return (err
== kCGLNoError
);
4380 /***********************************************************************
4381 * macdrv_wglCreateContext
4383 static struct wgl_context
* WINAPI
macdrv_wglCreateContext(HDC hdc
)
4385 struct wgl_context
*context
;
4387 TRACE("hdc %p\n", hdc
);
4389 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
4394 /***********************************************************************
4395 * macdrv_wglDeleteContext
4397 static BOOL WINAPI
macdrv_wglDeleteContext(struct wgl_context
*context
)
4399 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
4401 pthread_mutex_lock(&context_mutex
);
4402 list_remove(&context
->entry
);
4403 pthread_mutex_unlock(&context_mutex
);
4405 macdrv_dispose_opengl_context(context
->context
);
4410 /***********************************************************************
4411 * macdrv_wglGetPixelFormat
4413 static int WINAPI
macdrv_wglGetPixelFormat(HDC hdc
)
4417 format
= get_dc_pixel_format(hdc
);
4419 if (!is_valid_pixel_format(format
)) /* not set yet */
4421 else if (!is_displayable_pixel_format(format
))
4423 /* Non-displayable formats can't be used with traditional WGL calls.
4424 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4428 TRACE(" hdc %p -> %d\n", hdc
, format
);
4432 /***********************************************************************
4433 * macdrv_wglGetProcAddress
4435 static PROC WINAPI
macdrv_wglGetProcAddress(const char *proc
)
4439 if (!strncmp(proc
, "wgl", 3)) return NULL
;
4440 ret
= dlsym(opengl_handle
, proc
);
4446 if (dladdr(ret
, &info
))
4447 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
4449 TRACE("%s -> %p (no library info)\n", proc
, ret
);
4453 WARN("failed to find proc %s\n", debugstr_a(proc
));
4457 /***********************************************************************
4458 * macdrv_wglMakeCurrent
4460 static BOOL WINAPI
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
4462 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4463 (context
? context
->cglcontext
: NULL
));
4465 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
4468 /**********************************************************************
4469 * macdrv_wglSetPixelFormat
4471 static BOOL WINAPI
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
4473 return set_pixel_format(hdc
, fmt
, FALSE
);
4476 /***********************************************************************
4477 * macdrv_wglShareLists
4479 static BOOL WINAPI
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
4481 macdrv_opengl_context saved_context
;
4482 CGLContextObj saved_cglcontext
;
4484 TRACE("org %p dest %p\n", org
, dest
);
4486 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4487 * at context creation time but in case of WGL it is done using wglShareLists.
4489 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4490 * and when a program requests sharing we recreate the destination context if it hasn't been made
4491 * current or when it hasn't shared display lists before.
4494 if (dest
->has_been_current
)
4496 WARN("could not share display lists, the destination context has been current already\n");
4499 else if (dest
->sharing
)
4501 WARN("could not share display lists because dest has already shared lists before\n");
4505 /* Re-create the Mac context and share display lists */
4506 saved_context
= dest
->context
;
4507 saved_cglcontext
= dest
->cglcontext
;
4508 dest
->context
= NULL
;
4509 dest
->cglcontext
= NULL
;
4510 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
4512 dest
->context
= saved_context
;
4513 dest
->cglcontext
= saved_cglcontext
;
4517 /* Implicitly disposes of saved_cglcontext. */
4518 macdrv_dispose_opengl_context(saved_context
);
4520 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4521 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
4523 org
->sharing
= TRUE
;
4524 dest
->sharing
= TRUE
;
4529 /**********************************************************************
4530 * macdrv_wglSwapBuffers
4532 static BOOL WINAPI
macdrv_wglSwapBuffers(HDC hdc
)
4534 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4538 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4539 (context
? context
->cglcontext
: NULL
));
4543 sync_swap_interval(context
);
4544 sync_context(context
);
4547 if ((hwnd
= NtUserWindowFromDC(hdc
)))
4549 struct macdrv_win_data
*data
;
4551 if (!(data
= get_win_data(hwnd
)))
4553 SetLastError(ERROR_INVALID_HANDLE
);
4557 if (context
&& context
->draw_view
== data
->client_cocoa_view
)
4560 release_win_data(data
);
4564 struct wgl_pbuffer
*pbuffer
;
4566 pthread_mutex_lock(&dc_pbuffers_mutex
);
4567 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4568 pthread_mutex_unlock(&dc_pbuffers_mutex
);
4572 SetLastError(ERROR_INVALID_HANDLE
);
4576 if (context
&& context
->draw_pbuffer
== pbuffer
)
4581 macdrv_flush_opengl_context(context
->context
);
4584 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
4586 /* If there is a current context, then wglSwapBuffers should do an implicit
4587 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4588 in the other branch, but we have to do it explicitly here. */
4596 static struct opengl_funcs opengl_funcs
=
4599 macdrv_wglCopyContext
, /* p_wglCopyContext */
4600 macdrv_wglCreateContext
, /* p_wglCreateContext */
4601 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
4602 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
4603 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
4604 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
4605 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
4606 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
4607 macdrv_wglShareLists
, /* p_wglShareLists */
4608 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
4612 /**********************************************************************
4613 * macdrv_wine_get_wgl_driver
4615 struct opengl_funcs
*macdrv_wine_get_wgl_driver(UINT version
)
4617 static pthread_once_t init_once
= PTHREAD_ONCE_INIT
;
4619 if (version
!= WINE_WGL_DRIVER_VERSION
)
4621 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
4625 pthread_once(&init_once
, init_opengl
);
4626 return opengl_handle
? &opengl_funcs
: (void *)-1;