2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
49 char wglExtensions
[4096];
51 GLint max_viewport_dims
[2];
53 unsigned int max_major
, max_minor
;
56 static struct gl_info gl_info
;
64 macdrv_opengl_context context
;
65 CGLContextObj cglcontext
;
67 macdrv_view draw_view
;
69 struct wgl_pbuffer
*draw_pbuffer
;
70 macdrv_view read_view
;
72 struct wgl_pbuffer
*read_pbuffer
;
73 BOOL has_been_current
;
75 LONG update_swap_interval
;
77 DWORD last_flush_time
;
81 static struct list context_list
= LIST_INIT(context_list
);
83 static CRITICAL_SECTION context_section
;
84 static CRITICAL_SECTION_DEBUG critsect_debug
=
86 0, 0, &context_section
,
87 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
88 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
90 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
95 CGLPBufferObj pbuffer
;
103 static CFMutableDictionaryRef dc_pbuffers
;
105 static CRITICAL_SECTION dc_pbuffers_section
;
106 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
108 0, 0, &dc_pbuffers_section
,
109 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
110 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
112 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
115 static struct opengl_funcs opengl_funcs
;
117 #define USE_GL_FUNC(name) #name,
118 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
122 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
124 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
125 static void (*pglFinish
)(void);
126 static void (*pglFlush
)(void);
127 static void (*pglFlushRenderAPPLE
)(void);
128 static const GLubyte
*(*pglGetString
)(GLenum name
);
129 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
130 GLenum format
, GLenum type
, void *pixels
);
131 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
137 GLint color_bits
; /* including alpha_bits */
138 int red_bits
, red_shift
;
139 int green_bits
, green_shift
;
140 int blue_bits
, blue_shift
;
141 GLint alpha_bits
, alpha_shift
;
146 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
147 observations of the behavior of Windows systems, but also subjective judgments
148 about what color formats are more "normal" than others.
150 On at least some Windows systems, integer color formats are listed before
151 floating-point formats. Within the integer formats, higher color bits were
152 usually listed before lower color bits, while for floating-point formats it
153 was the reverse. However, that leads D3D to select 64-bit integer formats in
154 preference to 32-bit formats when the latter would be sufficient. It seems
155 that a 32-bit format is much more likely to be normally used in that case.
157 Also, there are certain odd color formats supported on the Mac which seem like
158 they would be less appropriate than more common ones. For instance, the color
159 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
160 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
163 For two color formats which differ only in whether or not they have alpha bits,
164 we use the same ordering. pixel_format_comparator() gives alpha bits a
165 different weight than color formats.
167 static const struct color_mode color_modes
[] = {
168 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
169 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
170 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
171 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
172 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
173 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
174 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
175 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
176 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
177 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
178 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
179 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
180 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
181 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
182 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
183 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
184 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
185 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
186 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
187 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
188 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
189 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
190 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
191 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
195 static const struct {
198 } depth_stencil_modes
[] = {
226 GLint max_aux_buffers
;
227 GLint max_sample_buffers
;
234 } renderer_properties
;
238 unsigned int window
:1;
239 unsigned int pbuffer
:1;
240 unsigned int accelerated
:1;
241 unsigned int color_mode
:5; /* index into color_modes table */
242 unsigned int aux_buffers
:3;
243 unsigned int depth_bits
:8;
244 unsigned int stencil_bits
:8;
245 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
246 unsigned int double_buffer
:1;
247 unsigned int stereo
:1;
248 unsigned int sample_buffers
:1;
249 unsigned int samples
:5;
250 unsigned int backing_store
:1;
258 } pixel_format_or_code
;
259 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
262 static pixel_format
*pixel_formats
;
263 static int nb_formats
, nb_displayable_formats
;
266 static void *opengl_handle
;
269 static const char* debugstr_attrib(int attrib
, int value
)
271 static const struct {
275 #define ATTRIB(a) { a, #a }
276 ATTRIB(WGL_ACCELERATION_ARB
),
277 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
278 ATTRIB(WGL_ACCUM_BITS_ARB
),
279 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
280 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
281 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
282 ATTRIB(WGL_ALPHA_BITS_ARB
),
283 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
284 ATTRIB(WGL_AUX_BUFFERS_ARB
),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
286 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
287 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
288 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
289 ATTRIB(WGL_BLUE_BITS_ARB
),
290 ATTRIB(WGL_BLUE_SHIFT_ARB
),
291 ATTRIB(WGL_COLOR_BITS_ARB
),
292 ATTRIB(WGL_DEPTH_BITS_ARB
),
293 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
294 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
295 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
296 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
297 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
298 ATTRIB(WGL_GREEN_BITS_ARB
),
299 ATTRIB(WGL_GREEN_SHIFT_ARB
),
300 ATTRIB(WGL_NEED_PALETTE_ARB
),
301 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
302 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
303 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
304 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
305 ATTRIB(WGL_PIXEL_TYPE_ARB
),
306 ATTRIB(WGL_RED_BITS_ARB
),
307 ATTRIB(WGL_RED_SHIFT_ARB
),
308 ATTRIB(WGL_RENDERER_ID_WINE
),
309 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
310 ATTRIB(WGL_SAMPLES_ARB
),
311 ATTRIB(WGL_SHARE_ACCUM_ARB
),
312 ATTRIB(WGL_SHARE_DEPTH_ARB
),
313 ATTRIB(WGL_SHARE_STENCIL_ARB
),
314 ATTRIB(WGL_STENCIL_BITS_ARB
),
315 ATTRIB(WGL_STEREO_ARB
),
316 ATTRIB(WGL_SUPPORT_GDI_ARB
),
317 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
318 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
319 ATTRIB(WGL_SWAP_METHOD_ARB
),
320 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
321 ATTRIB(WGL_TRANSPARENT_ARB
),
322 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
323 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
324 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
325 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
329 const char *attrib_name
= NULL
;
330 const char *value_name
= NULL
;
332 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
334 if (attrib_names
[i
].attrib
== attrib
)
336 attrib_name
= attrib_names
[i
].name
;
342 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
346 case WGL_ACCELERATION_ARB
:
349 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
350 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
351 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
354 case WGL_PIXEL_TYPE_ARB
:
357 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
358 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
359 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
360 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
363 case WGL_SWAP_METHOD_ARB
:
366 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
367 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
368 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
374 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
376 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
380 /**********************************************************************
381 * active_displays_mask
383 static CGOpenGLDisplayMask
active_displays_mask(void)
386 CGDirectDisplayID displays
[32];
388 CGOpenGLDisplayMask mask
;
390 err
= CGGetActiveDisplayList(sizeof(displays
) / sizeof(displays
[0]), displays
, &count
);
391 if (err
!= kCGErrorSuccess
)
393 displays
[0] = CGMainDisplayID();
398 for (i
= 0; i
< count
; i
++)
399 mask
|= CGDisplayIDToOpenGLDisplayMask(displays
[i
]);
405 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
406 CGLRendererProperty property
, GLint
*value
)
408 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
409 if (err
!= kCGLNoError
)
410 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
411 return (err
== kCGLNoError
);
415 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
419 memset(properties
, 0, sizeof(*properties
));
421 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
422 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
424 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
425 properties
->buffer_modes
= value
;
427 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
428 properties
->color_modes
= value
;
430 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
431 properties
->accum_modes
= value
;
433 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
434 properties
->depth_modes
= value
;
436 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
437 properties
->stencil_modes
= value
;
439 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
440 properties
->max_aux_buffers
= value
;
442 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
443 properties
->max_sample_buffers
= value
;
445 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
446 properties
->max_samples
= value
;
448 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
449 properties
->offscreen
= (value
!= 0);
451 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
452 properties
->accelerated
= (value
!= 0);
454 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
455 properties
->backing_store
= (value
!= 0);
457 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
458 properties
->window
= (value
!= 0);
460 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
461 properties
->online
= (value
!= 0);
465 static void dump_renderer(const renderer_properties
* renderer
)
469 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
470 TRACE("Buffer modes:\n");
471 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
472 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
473 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
474 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
476 TRACE("Color buffer modes:\n");
477 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
479 if (renderer
->color_modes
& color_modes
[i
].mode
)
481 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
482 if (color_modes
[i
].is_float
)
488 TRACE("Accumulation buffer sizes: { ");
489 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
491 if (renderer
->accum_modes
& color_modes
[i
].mode
)
492 TRACE("%d, ", color_modes
[i
].color_bits
);
496 TRACE("Depth buffer sizes: { ");
497 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
499 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
500 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
504 TRACE("Stencil buffer sizes: { ");
505 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
507 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
508 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
512 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
513 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
514 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
515 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
516 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
517 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
518 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
519 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
523 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
525 pixel_format_or_code pfc
;
528 pfc
.format
= *format
;
533 static inline pixel_format
pixel_format_for_code(UInt64 code
)
535 pixel_format_or_code pfc
;
542 static const char *debugstr_pf(const pixel_format
*pf
)
544 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",
548 color_modes
[pf
->color_mode
].color_bits
,
549 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
550 color_modes
[pf
->color_mode
].alpha_bits
,
553 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
560 code_for_pixel_format(pf
));
564 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
569 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
571 if ((modes
& color_modes
[i
].mode
) &&
572 color_modes
[i
].color_bits
>= color_size
&&
573 color_modes
[i
].alpha_bits
>= alpha_size
&&
574 !color_modes
[i
].is_float
== !color_float
)
576 if (best
< 0) /* no existing best choice */
578 else if (color_modes
[i
].color_bits
== color_size
&&
579 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
581 /* prefer it over a best which isn't exact or which has a higher bpp */
582 if (color_modes
[best
].color_bits
!= color_size
||
583 color_modes
[best
].alpha_bits
!= alpha_size
||
584 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
587 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
588 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
589 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
596 /* Couldn't find a match. Return first one that renderer supports. */
597 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
599 if (modes
& color_modes
[i
].mode
)
608 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
613 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
615 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
617 /* Prefer the fewest color bits, then prefer more alpha bits, then
618 prefer more bits per pixel. */
621 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
623 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
625 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
627 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
628 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
636 /* Couldn't find a match. Return last one that renderer supports. */
637 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
639 if (modes
& color_modes
[i
].mode
)
648 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
649 CFMutableSetRef pixel_format_set
)
651 CGLPixelFormatAttribute attribs
[64] = {
652 kCGLPFAMinimumPolicy
,
653 kCGLPFAClosestPolicy
,
654 kCGLPFARendererID
, renderer
.renderer_id
,
655 kCGLPFASingleRenderer
,
657 int n
= 5, n_stack
[16], n_stack_idx
= -1;
658 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
659 new_pixel_formats
= 0;
660 pixel_format request
;
661 unsigned int double_buffer
;
662 unsigned int accelerated
= renderer
.accelerated
;
666 attribs
[n
++] = kCGLPFAAccelerated
;
667 attribs
[n
++] = kCGLPFANoRecovery
;
669 else if (!allow_software_rendering
)
671 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
675 n_stack
[++n_stack_idx
] = n
;
676 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
680 n
= n_stack
[n_stack_idx
];
682 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
683 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
687 attribs
[n
++] = kCGLPFADoubleBuffer
;
688 memset(&request
, 0, sizeof(request
));
689 request
.accelerated
= accelerated
;
690 request
.double_buffer
= double_buffer
;
692 /* Don't bother with in-between aux buffers values: either 0 or max. */
693 n_stack
[++n_stack_idx
] = n
;
694 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
696 unsigned int color_mode
;
698 n
= n_stack
[n_stack_idx
];
700 attribs
[n
++] = kCGLPFAAuxBuffers
;
702 request
.aux_buffers
= aux
;
704 n_stack
[++n_stack_idx
] = n
;
705 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
707 unsigned int depth_mode
;
709 n
= n_stack
[n_stack_idx
];
711 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
714 attribs
[n
++] = kCGLPFAColorSize
;
715 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
716 attribs
[n
++] = kCGLPFAAlphaSize
;
717 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
718 if (color_modes
[color_mode
].is_float
)
719 attribs
[n
++] = kCGLPFAColorFloat
;
720 request
.color_mode
= color_mode
;
722 n_stack
[++n_stack_idx
] = n
;
723 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
725 unsigned int stencil_mode
;
727 n
= n_stack
[n_stack_idx
];
729 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
732 attribs
[n
++] = kCGLPFADepthSize
;
733 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
734 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
736 n_stack
[++n_stack_idx
] = n
;
737 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
741 n
= n_stack
[n_stack_idx
];
743 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
745 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
748 attribs
[n
++] = kCGLPFAStencilSize
;
749 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
750 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
752 /* FIXME: Could trim search space a bit here depending on GPU.
753 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
754 n_stack
[++n_stack_idx
] = n
;
755 for (stereo
= 0; stereo
<= 1; stereo
++)
759 n
= n_stack
[n_stack_idx
];
761 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
762 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
766 attribs
[n
++] = kCGLPFAStereo
;
767 request
.stereo
= stereo
;
769 /* Starts at -1 for a 0 accum size */
770 n_stack
[++n_stack_idx
] = n
;
771 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
773 unsigned int target_pass
;
775 n
= n_stack
[n_stack_idx
];
779 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
782 attribs
[n
++] = kCGLPFAAccumSize
;
783 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
784 request
.accum_mode
= accum_mode
+ 1;
787 request
.accum_mode
= 0;
789 /* Targets to request are:
790 accelerated: window OR window + pbuffer
791 software: window + pbuffer */
792 n_stack
[++n_stack_idx
] = n
;
793 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
795 unsigned int samples
, max_samples
;
797 n
= n_stack
[n_stack_idx
];
799 attribs
[n
++] = kCGLPFAWindow
;
802 if (!accelerated
|| target_pass
> 0)
804 attribs
[n
++] = kCGLPFAPBuffer
;
810 /* FIXME: Could trim search space a bit here depending on GPU.
811 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
812 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
813 n_stack
[++n_stack_idx
] = n
;
814 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
815 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
817 unsigned int backing_store
, min_backing_store
, max_backing_store
;
819 n
= n_stack
[n_stack_idx
];
823 attribs
[n
++] = kCGLPFASampleBuffers
;
824 attribs
[n
++] = renderer
.max_sample_buffers
;
825 attribs
[n
++] = kCGLPFASamples
;
826 attribs
[n
++] = samples
;
827 request
.sample_buffers
= renderer
.max_sample_buffers
;
828 request
.samples
= samples
;
831 request
.sample_buffers
= request
.samples
= 0;
833 if (renderer
.backing_store
&& double_buffer
)
835 /* The software renderer seems to always preserve the backing store, whether
836 we ask for it or not. So don't bother not asking for it. */
837 min_backing_store
= accelerated
? 0 : 1;
838 max_backing_store
= 1;
841 min_backing_store
= max_backing_store
= 0;
842 n_stack
[++n_stack_idx
] = n
;
843 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
845 CGLPixelFormatObj pix
;
846 GLint virtualScreens
;
849 n
= n_stack
[n_stack_idx
];
852 attribs
[n
++] = kCGLPFABackingStore
;
853 request
.backing_store
= backing_store
;
857 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
858 if (err
== kCGLNoError
&& pix
)
861 GLint value
, color_size
, alpha_size
, color_float
;
863 CFNumberRef code_object
;
866 memset(&pf
, 0, sizeof(pf
));
868 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
869 pf
.accelerated
= value
;
870 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
871 pf
.aux_buffers
= value
;
872 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
873 pf
.depth_bits
= value
;
874 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
875 pf
.double_buffer
= value
;
876 if (pf
.double_buffer
&&
877 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
878 pf
.backing_store
= value
;
879 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
881 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
882 pf
.sample_buffers
= value
;
883 if (pf
.sample_buffers
&&
884 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
886 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
887 pf
.stencil_bits
= value
;
888 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
890 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
893 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
895 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
897 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
899 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
901 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
902 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
904 CGLReleasePixelFormat(pix
);
906 pf_code
= code_for_pixel_format(&pf
);
908 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
909 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
910 dupe_pixel_formats
++;
913 CFSetAddValue(pixel_format_set
, code_object
);
914 CFArrayAppendValue(pixel_format_array
, code_object
);
917 CFRelease(code_object
);
919 if (pf_code
== code_for_pixel_format(&request
))
920 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
923 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
924 dupe
? " (duplicate)" : "");
929 failed_pixel_formats
++;
930 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
933 tried_pixel_formats
++;
965 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
966 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
967 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
968 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
972 /* The docs for WGL_ARB_pixel_format say:
973 Indices are assigned to pixel formats in the following order:
974 1. Accelerated pixel formats that are displayable
975 2. Accelerated pixel formats that are displayable and which have
977 3. Generic pixel formats
978 4. Accelerated pixel formats that are non displayable
980 static int pixel_format_category(pixel_format pf
)
982 /* non-displayable */
986 /* non-accelerated a.k.a. software a.k.a. generic */
990 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
991 if (color_modes
[pf
.color_mode
].is_float
)
994 /* accelerated, displayable, no extended attributes */
999 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
1001 CFNumberRef number1
= val1
;
1002 CFNumberRef number2
= val2
;
1003 UInt64 code1
, code2
;
1004 pixel_format pf1
, pf2
;
1005 int category1
, category2
;
1007 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
1008 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
1009 pf1
= pixel_format_for_code(code1
);
1010 pf2
= pixel_format_for_code(code2
);
1011 category1
= pixel_format_category(pf1
);
1012 category2
= pixel_format_category(pf2
);
1014 if (category1
< category2
)
1015 return kCFCompareLessThan
;
1016 if (category1
> category2
)
1017 return kCFCompareGreaterThan
;
1019 /* Within a category, sort the "best" formats toward the front since that's
1020 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1021 matches at least one Windows 7 machine's behavior.
1023 /* Accelerated before unaccelerated. */
1024 if (pf1
.accelerated
&& !pf2
.accelerated
)
1025 return kCFCompareLessThan
;
1026 if (!pf1
.accelerated
&& pf2
.accelerated
)
1027 return kCFCompareGreaterThan
;
1029 /* Explicit color mode ordering. */
1030 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1031 return kCFCompareLessThan
;
1032 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1033 return kCFCompareGreaterThan
;
1035 /* Non-pbuffer-capable before pbuffer-capable. */
1036 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1037 return kCFCompareLessThan
;
1038 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1039 return kCFCompareGreaterThan
;
1041 /* Fewer samples before more samples. */
1042 if (pf1
.samples
< pf2
.samples
)
1043 return kCFCompareLessThan
;
1044 if (pf1
.samples
> pf2
.samples
)
1045 return kCFCompareGreaterThan
;
1047 /* Monoscopic before stereoscopic. (This is a guess.) */
1048 if (!pf1
.stereo
&& pf2
.stereo
)
1049 return kCFCompareLessThan
;
1050 if (pf1
.stereo
&& !pf2
.stereo
)
1051 return kCFCompareGreaterThan
;
1053 /* Single buffered before double buffered. */
1054 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1055 return kCFCompareLessThan
;
1056 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1057 return kCFCompareGreaterThan
;
1059 /* Possibly-optimized double buffering before backing-store-preserving
1060 double buffering. */
1061 if (!pf1
.backing_store
&& pf2
.backing_store
)
1062 return kCFCompareLessThan
;
1063 if (pf1
.backing_store
&& !pf2
.backing_store
)
1064 return kCFCompareGreaterThan
;
1066 /* Bigger depth buffer before smaller depth buffer. */
1067 if (pf1
.depth_bits
> pf2
.depth_bits
)
1068 return kCFCompareLessThan
;
1069 if (pf1
.depth_bits
< pf2
.depth_bits
)
1070 return kCFCompareGreaterThan
;
1072 /* Smaller stencil buffer before bigger stencil buffer. */
1073 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1074 return kCFCompareLessThan
;
1075 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1076 return kCFCompareGreaterThan
;
1078 /* Smaller alpha bits before larger alpha bits. */
1079 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1080 return kCFCompareLessThan
;
1081 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1082 return kCFCompareGreaterThan
;
1084 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1089 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1090 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1091 return kCFCompareLessThan
;
1092 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1093 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1094 return kCFCompareGreaterThan
;
1096 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1097 return kCFCompareLessThan
;
1098 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1099 return kCFCompareGreaterThan
;
1101 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1102 return kCFCompareLessThan
;
1103 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1104 return kCFCompareGreaterThan
;
1107 return kCFCompareGreaterThan
;
1109 else if (pf2
.accum_mode
)
1110 return kCFCompareLessThan
;
1112 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1113 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1114 return kCFCompareLessThan
;
1115 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1116 return kCFCompareGreaterThan
;
1118 /* If we get here, arbitrarily sort based on code. */
1120 return kCFCompareLessThan
;
1122 return kCFCompareGreaterThan
;
1123 return kCFCompareEqualTo
;
1127 static BOOL
init_pixel_formats(void)
1130 CGLRendererInfoObj renderer_info
;
1131 GLint rendererCount
;
1133 CFMutableSetRef pixel_format_set
;
1134 CFMutableArrayRef pixel_format_array
;
1140 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1143 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1147 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1148 if (!pixel_format_set
)
1150 WARN("CFSetCreateMutable failed\n");
1151 CGLDestroyRendererInfo(renderer_info
);
1155 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1156 if (!pixel_format_array
)
1158 WARN("CFArrayCreateMutable failed\n");
1159 CFRelease(pixel_format_set
);
1160 CGLDestroyRendererInfo(renderer_info
);
1164 for (i
= 0; i
< rendererCount
; i
++)
1166 renderer_properties renderer
;
1168 get_renderer_properties(renderer_info
, i
, &renderer
);
1171 TRACE("renderer_properties %d:\n", i
);
1172 dump_renderer(&renderer
);
1175 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1178 CFRelease(pixel_format_set
);
1179 CGLDestroyRendererInfo(renderer_info
);
1181 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1184 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1187 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1188 for (i
= 0; i
< range
.length
; i
++)
1190 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1193 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1194 pixel_formats
[i
] = pixel_format_for_code(code
);
1195 if (pixel_formats
[i
].window
)
1196 nb_displayable_formats
++;
1199 nb_formats
= range
.length
;
1200 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1204 WARN("failed to allocate pixel format list\n");
1207 WARN("got no pixel formats\n");
1209 CFRelease(pixel_format_array
);
1214 static inline BOOL
is_valid_pixel_format(int format
)
1216 return format
> 0 && format
<= nb_formats
;
1220 static inline BOOL
is_displayable_pixel_format(int format
)
1222 return format
> 0 && format
<= nb_displayable_formats
;
1226 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1228 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1229 * format in case of probing the number of pixel formats.
1231 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1233 TRACE("Returning format %d\n", format
);
1234 return &pixel_formats
[format
- 1];
1240 static BOOL
init_gl_info(void)
1242 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1243 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1245 CGDirectDisplayID display
= CGMainDisplayID();
1246 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1247 CGLPixelFormatAttribute attribs
[] = {
1248 kCGLPFADisplayMask
, displayMask
,
1251 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1252 CGLPixelFormatAttribute core_attribs
[] =
1254 kCGLPFADisplayMask
, displayMask
,
1256 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1260 CGLPixelFormatObj pix
;
1261 GLint virtualScreens
;
1263 CGLContextObj context
;
1264 CGLContextObj old_context
= CGLGetCurrentContext();
1268 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1269 if (err
!= kCGLNoError
|| !pix
)
1271 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1275 err
= CGLCreateContext(pix
, NULL
, &context
);
1276 CGLReleasePixelFormat(pix
);
1277 if (err
!= kCGLNoError
|| !context
)
1279 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1283 err
= CGLSetCurrentContext(context
);
1284 if (err
!= kCGLNoError
)
1286 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1287 CGLReleaseContext(context
);
1291 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1292 length
= strlen(str
) + sizeof(legacy_extensions
);
1294 length
+= strlen(legacy_ext_swap_control
);
1295 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1296 strcpy(gl_info
.glExtensions
, str
);
1297 strcat(gl_info
.glExtensions
, legacy_extensions
);
1299 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1301 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1303 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1304 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1305 TRACE("GL version : %s\n", str
);
1306 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1308 CGLSetCurrentContext(old_context
);
1309 CGLReleaseContext(context
);
1311 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1312 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1313 if (err
!= kCGLNoError
|| !pix
)
1315 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1316 err
, CGLErrorString(err
));
1320 err
= CGLCreateContext(pix
, NULL
, &context
);
1321 CGLReleasePixelFormat(pix
);
1322 if (err
!= kCGLNoError
|| !context
)
1324 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1325 err
, CGLErrorString(err
));
1329 err
= CGLSetCurrentContext(context
);
1330 if (err
!= kCGLNoError
)
1332 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1333 err
, CGLErrorString(err
));
1334 CGLReleaseContext(context
);
1338 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1339 TRACE("Core context GL version: %s\n", str
);
1340 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1341 CGLSetCurrentContext(old_context
);
1342 CGLReleaseContext(context
);
1349 static int get_dc_pixel_format(HDC hdc
)
1354 if ((hwnd
= WindowFromDC(hdc
)))
1356 struct macdrv_win_data
*data
;
1358 if (!(data
= get_win_data(hwnd
)))
1360 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1364 format
= data
->pixel_format
;
1365 release_win_data(data
);
1369 struct wgl_pbuffer
*pbuffer
;
1371 EnterCriticalSection(&dc_pbuffers_section
);
1372 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1374 format
= pbuffer
->format
;
1377 WARN("no window or pbuffer for DC %p\n", hdc
);
1380 LeaveCriticalSection(&dc_pbuffers_section
);
1387 /**********************************************************************
1390 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1392 const pixel_format
*pf
;
1393 CGLPixelFormatAttribute attribs
[64];
1395 CGLPixelFormatObj pix
;
1396 GLint virtualScreens
;
1398 BOOL core
= major
>= 3;
1400 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1403 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1408 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1411 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1412 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1416 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1417 attribs
[n
++] = kCGLPFAClosestPolicy
;
1419 if (context
->renderer_id
)
1421 attribs
[n
++] = kCGLPFARendererID
;
1422 attribs
[n
++] = context
->renderer_id
;
1423 attribs
[n
++] = kCGLPFASingleRenderer
;
1424 attribs
[n
++] = kCGLPFANoRecovery
;
1427 if (pf
->accelerated
)
1429 attribs
[n
++] = kCGLPFAAccelerated
;
1430 attribs
[n
++] = kCGLPFANoRecovery
;
1434 attribs
[n
++] = kCGLPFARendererID
;
1435 attribs
[n
++] = kCGLRendererGenericFloatID
;
1438 if (pf
->double_buffer
)
1439 attribs
[n
++] = kCGLPFADoubleBuffer
;
1443 attribs
[n
++] = kCGLPFAAuxBuffers
;
1444 attribs
[n
++] = pf
->aux_buffers
;
1447 attribs
[n
++] = kCGLPFAColorSize
;
1448 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1449 attribs
[n
++] = kCGLPFAAlphaSize
;
1450 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1451 if (color_modes
[pf
->color_mode
].is_float
)
1452 attribs
[n
++] = kCGLPFAColorFloat
;
1454 attribs
[n
++] = kCGLPFADepthSize
;
1455 attribs
[n
++] = pf
->depth_bits
;
1457 attribs
[n
++] = kCGLPFAStencilSize
;
1458 attribs
[n
++] = pf
->stencil_bits
;
1461 attribs
[n
++] = kCGLPFAStereo
;
1463 if (pf
->accum_mode
&& !core
)
1465 attribs
[n
++] = kCGLPFAAccumSize
;
1466 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1469 if (pf
->pbuffer
&& !core
)
1470 attribs
[n
++] = kCGLPFAPBuffer
;
1472 if (pf
->sample_buffers
&& pf
->samples
)
1474 attribs
[n
++] = kCGLPFASampleBuffers
;
1475 attribs
[n
++] = pf
->sample_buffers
;
1476 attribs
[n
++] = kCGLPFASamples
;
1477 attribs
[n
++] = pf
->samples
;
1480 if (pf
->backing_store
)
1481 attribs
[n
++] = kCGLPFABackingStore
;
1483 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1486 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1487 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1489 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1491 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1493 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1500 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1501 if (err
!= kCGLNoError
|| !pix
)
1503 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1504 SetLastError(ERROR_INVALID_OPERATION
);
1508 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1509 CGLReleasePixelFormat(pix
);
1510 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1512 context
->cglcontext
= NULL
;
1513 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1514 SetLastError(ERROR_INVALID_OPERATION
);
1518 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1521 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1522 if (err
!= kCGLNoError
)
1523 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1525 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1528 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1529 if (err
!= kCGLNoError
)
1530 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1533 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1534 CGLReleaseContext(context
->cglcontext
);
1535 if (!context
->context
)
1537 WARN("macdrv_create_opengl_context() failed\n");
1538 SetLastError(ERROR_INVALID_OPERATION
);
1541 context
->major
= major
;
1544 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1546 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1552 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1555 *rect
= data
->client_rect
;
1557 if (data
->cocoa_window
)
1560 *window
= data
->cocoa_window
;
1561 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1565 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1566 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1567 struct macdrv_win_data
*top_data
= get_win_data(top
);
1569 if (top_data
&& top_data
->cocoa_window
)
1572 *window
= top_data
->cocoa_window
;
1573 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1574 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1579 release_win_data(top_data
);
1586 /***********************************************************************
1589 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1591 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1595 macdrv_window cocoa_window
;
1597 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1599 ERR("no top-level parent with Cocoa window in this process\n");
1603 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1606 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1610 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1611 wine_dbgstr_rect(&data
->gl_rect
));
1614 data
->pixel_format
= format
;
1620 /**********************************************************************
1623 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1625 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1627 struct macdrv_win_data
*data
;
1628 const pixel_format
*pf
;
1629 HWND hwnd
= WindowFromDC(hdc
);
1632 TRACE("hdc %p format %d\n", hdc
, fmt
);
1634 if (!hwnd
|| hwnd
== GetDesktopWindow())
1636 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1640 if (!(data
= get_win_data(hwnd
)))
1642 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1646 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1648 ret
= (data
->pixel_format
== fmt
);
1652 /* Check if fmt is in our list of supported formats to see if it is supported. */
1653 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1656 ERR("Invalid pixel format: %d\n", fmt
);
1662 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1666 if (!set_win_format(data
, fmt
))
1668 WARN("Couldn't set format of the window, returning failure\n");
1672 TRACE("pixel format:\n");
1673 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1674 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1675 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1676 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1677 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1678 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1679 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1680 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1681 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1682 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1683 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1684 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1685 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1686 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1690 release_win_data(data
);
1691 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) __wine_set_pixel_format(hwnd
, fmt
);
1696 /**********************************************************************
1697 * mark_contexts_for_moved_view
1699 static void mark_contexts_for_moved_view(macdrv_view view
)
1701 struct wgl_context
*context
;
1703 EnterCriticalSection(&context_section
);
1704 LIST_FOR_EACH_ENTRY(context
, &context_list
, struct wgl_context
, entry
)
1706 if (context
->draw_view
== view
)
1707 InterlockedExchange(&context
->view_moved
, TRUE
);
1709 LeaveCriticalSection(&context_section
);
1713 /**********************************************************************
1714 * set_gl_view_parent
1716 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1718 struct macdrv_win_data
*data
;
1720 if (!(data
= get_win_data(hwnd
))) return;
1724 macdrv_window cocoa_window
;
1726 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1728 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1730 ERR("no top-level parent with Cocoa window in this process\n");
1731 macdrv_dispose_view(data
->gl_view
);
1732 data
->gl_view
= NULL
;
1733 release_win_data(data
);
1734 __wine_set_pixel_format( hwnd
, 0 );
1738 macdrv_set_view_superview(data
->gl_view
, NULL
, cocoa_window
, NULL
, NULL
);
1739 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(data
->gl_rect
));
1740 mark_contexts_for_moved_view(data
->gl_view
);
1743 release_win_data(data
);
1747 /**********************************************************************
1750 static BOOL
sync_context_rect(struct wgl_context
*context
)
1753 if (InterlockedCompareExchange(&context
->view_moved
, FALSE
, TRUE
))
1755 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1757 if (data
&& data
->gl_view
&& data
->gl_view
== context
->draw_view
&&
1758 memcmp(&context
->draw_rect
, &data
->gl_rect
, sizeof(context
->draw_rect
)))
1760 context
->draw_rect
= data
->gl_rect
;
1763 release_win_data(data
);
1769 /**********************************************************************
1770 * make_context_current
1772 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1776 struct wgl_pbuffer
*pbuffer
;
1780 view
= context
->read_view
;
1781 view_rect
= context
->read_rect
;
1782 pbuffer
= context
->read_pbuffer
;
1786 sync_context_rect(context
);
1788 view
= context
->draw_view
;
1789 view_rect
= context
->draw_rect
;
1790 pbuffer
= context
->draw_pbuffer
;
1793 if (view
|| !pbuffer
)
1794 macdrv_make_context_current(context
->context
, view
, cgrect_from_rect(view_rect
));
1799 if (CGLIsEnabled(context
->cglcontext
, kCGLCESurfaceBackingSize
, &enabled
) == kCGLNoError
&& enabled
)
1800 CGLDisable(context
->cglcontext
, kCGLCESurfaceBackingSize
);
1801 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1803 CGLSetCurrentContext(context
->cglcontext
);
1808 /**********************************************************************
1811 static void sync_context(struct wgl_context
*context
)
1813 if (sync_context_rect(context
))
1814 make_context_current(context
, FALSE
);
1818 /**********************************************************************
1821 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1825 /* In theory, for single-buffered contexts, there's no such thing as a swap
1826 so the swap interval shouldn't matter. But OS X will synchronize flushes
1827 of single-buffered contexts if the interval is set to non-zero. */
1828 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1831 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1832 if (err
!= kCGLNoError
)
1833 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1835 return err
== kCGLNoError
;
1839 /**********************************************************************
1840 * sync_swap_interval
1842 static void sync_swap_interval(struct wgl_context
*context
)
1844 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1848 if (context
->draw_hwnd
)
1850 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1853 interval
= data
->swap_interval
;
1854 release_win_data(data
);
1856 else /* window was destroyed? */
1862 set_swap_interval(context
, interval
);
1867 /**********************************************************************
1868 * get_iokit_display_property
1870 static BOOL
get_iokit_display_property(CGLRendererInfoObj renderer_info
, GLint renderer
, CFStringRef property
, GLuint
* value
)
1876 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, &accelerated
) || !accelerated
)
1878 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1882 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPDisplayMask
, &display_mask
))
1884 WARN("failed to get kCGLRPDisplayMask\n");
1888 for (i
= 0; i
< sizeof(GLint
) * 8; i
++)
1890 GLint this_display_mask
= (GLint
)(1U << i
);
1891 if (this_display_mask
& display_mask
)
1893 CGDirectDisplayID display_id
= CGOpenGLDisplayMaskToDisplayID(this_display_mask
);
1894 io_service_t service
;
1896 uint32_t prop_value
;
1900 service
= CGDisplayIOServicePort(display_id
);
1903 WARN("CGDisplayIOServicePort(%u) failed\n", display_id
);
1907 data
= IORegistryEntrySearchCFProperty(service
, kIOServicePlane
, property
, NULL
,
1908 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1911 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property
), display_id
);
1914 if (CFGetTypeID(data
) != CFDataGetTypeID())
1916 WARN("property %s is not a data object: %s\n", debugstr_cf(property
), debugstr_cf(data
));
1920 if (CFDataGetLength(data
) != sizeof(prop_value
))
1922 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property
), display_id
,
1923 (unsigned long long)CFDataGetLength(data
));
1928 CFDataGetBytes(data
, CFRangeMake(0, sizeof(prop_value
)), (UInt8
*)&prop_value
);
1930 *value
= prop_value
;
1939 /**********************************************************************
1940 * create_pixel_format_for_renderer
1942 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1943 * responsible for releasing the pixel format object.
1945 static CGLPixelFormatObj
create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info
, GLint renderer
, BOOL core
)
1948 CGLPixelFormatAttribute attrs
[] = {
1949 kCGLPFARendererID
, 0,
1950 kCGLPFASingleRenderer
,
1951 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1955 CGLPixelFormatObj pixel_format
;
1956 GLint virtual_screens
;
1960 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1961 attrs
[3] = kCGLPFAOpenGLProfile
;
1962 attrs
[4] = (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
;
1968 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
1971 attrs
[1] = renderer_id
;
1972 err
= CGLChoosePixelFormat(attrs
, &pixel_format
, &virtual_screens
);
1973 if (err
!= kCGLNoError
)
1974 pixel_format
= NULL
;
1975 return pixel_format
;
1979 /**********************************************************************
1980 * map_renderer_index
1982 * We can't create pixel formats for all renderers listed. For example,
1983 * in a dual-GPU system, the integrated GPU is typically unavailable
1984 * when the discrete GPU is active.
1986 * This function conceptually creates a list of "good" renderers from the
1987 * list of all renderers. It treats the input "renderer" parameter as an
1988 * index into that list of good renderers and returns the corresponding
1989 * index into the list of all renderers.
1991 static GLint
map_renderer_index(CGLRendererInfoObj renderer_info
, GLint renderer_count
, GLint renderer
)
1993 GLint good_count
, i
;
1996 for (i
= 0; i
< renderer_count
; i
++)
1998 CGLPixelFormatObj pix
= create_pixel_format_for_renderer(renderer_info
, i
, FALSE
);
2001 CGLReleasePixelFormat(pix
);
2003 if (good_count
> renderer
)
2007 TRACE("skipping bad renderer %d\n", i
);
2010 TRACE("mapped requested renderer %d to index %d\n", renderer
, i
);
2015 /**********************************************************************
2018 static const char* get_gl_string(CGLPixelFormatObj pixel_format
, GLenum name
)
2020 const char* ret
= NULL
;
2021 CGLContextObj context
, old_context
;
2024 err
= CGLCreateContext(pixel_format
, NULL
, &context
);
2025 if (err
== kCGLNoError
&& context
)
2027 old_context
= CGLGetCurrentContext();
2028 err
= CGLSetCurrentContext(context
);
2029 if (err
== kCGLNoError
)
2031 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(name
);
2032 CGLSetCurrentContext(old_context
);
2035 WARN("CGLSetCurrentContext failed: %d %s\n", err
, CGLErrorString(err
));
2036 CGLReleaseContext(context
);
2039 WARN("CGLCreateContext failed: %d %s\n", err
, CGLErrorString(err
));
2045 /**********************************************************************
2046 * get_fallback_renderer_version
2048 static void get_fallback_renderer_version(GLuint
*value
)
2050 BOOL got_it
= FALSE
;
2051 CFURLRef url
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
2052 kCFURLPOSIXPathStyle
, TRUE
);
2055 CFBundleRef bundle
= CFBundleCreate(NULL
, url
);
2059 CFStringRef version
= CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleVersionKey
);
2060 if (version
&& CFGetTypeID(version
) == CFStringGetTypeID())
2062 size_t len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(version
), kCFStringEncodingUTF8
);
2063 char* buf
= HeapAlloc(GetProcessHeap(), 0, len
);
2064 if (buf
&& CFStringGetCString(version
, buf
, len
, kCFStringEncodingUTF8
))
2066 unsigned int major
, minor
, bugfix
;
2067 int count
= sscanf(buf
, "%u.%u.%u", &major
, &minor
, &bugfix
);
2079 HeapFree(GetProcessHeap(), 0, buf
);
2087 /* Use the version of the OpenGL framework from OS X 10.6, which is the
2088 earliest version that the Mac driver supports. */
2096 /**********************************************************************
2097 * parse_renderer_version
2099 * Get the renderer version from the OpenGL version string. Assumes
2100 * the string is of the form
2101 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2102 * where major, minor, and bugfix are what we're interested in. This
2103 * form for the vendor specific information is not generally applicable,
2104 * but seems reliable on OS X.
2106 static BOOL
parse_renderer_version(const char* version
, GLuint
*value
)
2108 const char* p
= strchr(version
, ' ');
2110 unsigned int major
, minor
, bugfix
;
2112 if (p
) p
= strchr(p
+ 1, '-');
2113 if (!p
) return FALSE
;
2115 count
= sscanf(p
+ 1, "%u.%u.%u", &major
, &minor
, &bugfix
);
2130 /**********************************************************************
2131 * query_renderer_integer
2133 static BOOL
query_renderer_integer(CGLRendererInfoObj renderer_info
, GLint renderer
, GLenum attribute
, GLuint
*value
)
2141 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
2143 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer
, renderer_id
, attribute
, value
);
2148 case WGL_RENDERER_ACCELERATED_WINE
:
2149 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, (GLint
*)value
))
2153 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value
);
2156 case WGL_RENDERER_DEVICE_ID_WINE
:
2157 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("device-id"), value
);
2160 *value
= 0xffffffff;
2163 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value
);
2166 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE
:
2167 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
:
2169 BOOL core
= (attribute
== WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
);
2170 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, core
);
2174 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2176 CGLReleasePixelFormat(pixel_format
);
2179 unsigned int major
, minor
;
2181 if (sscanf(version
, "%u.%u", &major
, &minor
) == 2)
2192 value
[0] = value
[1] = 0;
2195 TRACE("%s -> %u.%u\n", core
? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2196 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value
[0], value
[1]);
2200 case WGL_RENDERER_PREFERRED_PROFILE_WINE
:
2202 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2206 CGLReleasePixelFormat(pixel_format
);
2207 *value
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
2208 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2212 *value
= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
2213 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2219 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE
:
2220 /* FIXME: no API to query this */
2223 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value
);
2226 case WGL_RENDERER_VENDOR_ID_WINE
:
2227 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("vendor-id"), value
);
2230 *value
= 0xffffffff;
2233 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value
);
2236 case WGL_RENDERER_VERSION_WINE
:
2238 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2241 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
2244 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2246 CGLReleasePixelFormat(pixel_format
);
2248 ret
= parse_renderer_version(version
, value
);
2253 get_fallback_renderer_version(value
);
2256 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
2260 case WGL_RENDERER_VIDEO_MEMORY_WINE
:
2261 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2262 err
= CGLDescribeRenderer(renderer_info
, renderer
, kCGLRPVideoMemoryMegabytes
, (GLint
*)value
);
2263 if (err
!= kCGLNoError
&& err
!= kCGLBadProperty
)
2264 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err
, CGLErrorString(err
));
2265 if (err
!= kCGLNoError
)
2268 if (get_renderer_property(renderer_info
, renderer
, kCGLRPVideoMemory
, (GLint
*)value
))
2269 *value
/= 1024 * 1024;
2274 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value
);
2278 FIXME("unrecognized attribute 0x%04x\n", attribute
);
2286 /**********************************************************************
2287 * macdrv_glCopyColorTable
2289 * Hook into glCopyColorTable as part of the implementation of
2290 * wglMakeContextCurrentARB. If the context has a separate readable,
2291 * temporarily make that current, do glCopyColorTable, and then set it
2292 * back to the drawable. This is modeled after what Mesa GLX's Apple
2293 * implementation does.
2295 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
2298 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2300 if (context
->read_view
|| context
->read_pbuffer
)
2301 make_context_current(context
, TRUE
);
2303 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
2305 if (context
->read_view
|| context
->read_pbuffer
)
2306 make_context_current(context
, FALSE
);
2310 /**********************************************************************
2311 * macdrv_glCopyPixels
2313 * Hook into glCopyPixels as part of the implementation of
2314 * wglMakeContextCurrentARB. If the context has a separate readable,
2315 * temporarily make that current, do glCopyPixels, and then set it back
2316 * to the drawable. This is modeled after what Mesa GLX's Apple
2317 * implementation does.
2319 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
2321 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2323 if (context
->read_view
|| context
->read_pbuffer
)
2324 make_context_current(context
, TRUE
);
2326 pglCopyPixels(x
, y
, width
, height
, type
);
2328 if (context
->read_view
|| context
->read_pbuffer
)
2329 make_context_current(context
, FALSE
);
2333 /**********************************************************************
2336 static void macdrv_glFinish(void)
2338 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2340 sync_swap_interval(context
);
2341 sync_context(context
);
2346 /**********************************************************************
2349 static void macdrv_glFlush(void)
2351 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2353 sync_swap_interval(context
);
2354 sync_context(context
);
2356 if (skip_single_buffer_flushes
)
2358 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
2359 DWORD now
= GetTickCount();
2361 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
2362 context
->last_flush_time
, now
);
2363 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
2365 TRACE("calling glFlushRenderAPPLE()\n");
2366 pglFlushRenderAPPLE();
2371 TRACE("calling glFlush()\n");
2372 context
->last_flush_time
= now
;
2380 /**********************************************************************
2381 * macdrv_glGetString
2383 * Hook into glGetString in order to return some legacy WGL extensions
2384 * that couldn't be advertised via the standard
2385 * WGL_ARB_extensions_string mechanism. Some programs, especially
2386 * older ones, expect to find certain older extensions, such as
2387 * WGL_EXT_extensions_string itself, in the standard GL extensions
2388 * string, and won't query any other WGL extensions unless they find
2389 * that particular extension there.
2391 static const GLubyte
*macdrv_glGetString(GLenum name
)
2393 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
2394 return (const GLubyte
*)gl_info
.glExtensions
;
2396 return pglGetString(name
);
2400 /**********************************************************************
2401 * macdrv_glReadPixels
2403 * Hook into glReadPixels as part of the implementation of
2404 * wglMakeContextCurrentARB. If the context has a separate readable,
2405 * temporarily make that current, do glReadPixels, and then set it back
2406 * to the drawable. This is modeled after what Mesa GLX's Apple
2407 * implementation does.
2409 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2410 GLenum format
, GLenum type
, void *pixels
)
2412 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2414 if (context
->read_view
|| context
->read_pbuffer
)
2415 make_context_current(context
, TRUE
);
2417 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2419 if (context
->read_view
|| context
->read_pbuffer
)
2420 make_context_current(context
, FALSE
);
2424 /**********************************************************************
2427 * Hook into glViewport as an opportunity to update the OpenGL context
2428 * if necessary. This is modeled after what Mesa GLX's Apple
2429 * implementation does.
2431 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2433 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2435 sync_context(context
);
2436 macdrv_update_opengl_context(context
->context
);
2437 pglViewport(x
, y
, width
, height
);
2441 /***********************************************************************
2442 * macdrv_wglBindTexImageARB
2444 * WGL_ARB_render_texture: wglBindTexImageARB
2446 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2448 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2452 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
2454 if (pbuffer
->no_texture
)
2456 SetLastError(ERROR_INVALID_OPERATION
);
2460 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
2461 opengl_funcs
.gl
.p_glFlush();
2465 case WGL_FRONT_LEFT_ARB
:
2466 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2467 source
= GL_FRONT_LEFT
;
2471 case WGL_FRONT_RIGHT_ARB
:
2472 source
= GL_FRONT_RIGHT
;
2474 case WGL_BACK_LEFT_ARB
:
2475 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2476 source
= GL_BACK_LEFT
;
2480 case WGL_BACK_RIGHT_ARB
:
2481 source
= GL_BACK_RIGHT
;
2483 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
2484 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
2485 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
2486 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
2494 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
2495 SetLastError(ERROR_INVALID_DATA
);
2499 WARN("unknown source buffer 0x%x\n", iBuffer
);
2500 SetLastError(ERROR_INVALID_DATA
);
2504 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
2505 if (err
!= kCGLNoError
)
2507 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2508 SetLastError(ERROR_INVALID_OPERATION
);
2516 /***********************************************************************
2517 * macdrv_wglChoosePixelFormatARB
2519 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2521 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2522 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2523 int *piFormats
, UINT
*nNumFormats
)
2525 pixel_format pf
, valid
;
2527 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2528 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2533 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2534 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2536 FIXME("unused pfAttribFList\n");
2538 memset(&pf
, 0, sizeof(pf
));
2539 memset(&valid
, 0, sizeof(valid
));
2540 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2541 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2545 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2548 int value
= iptr
[1];
2550 TRACE("%s\n", debugstr_attrib(attr
, value
));
2554 case WGL_DRAW_TO_WINDOW_ARB
:
2555 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2556 pf
.window
= (value
!= 0);
2560 case WGL_DRAW_TO_BITMAP_ARB
:
2563 case WGL_ACCELERATION_ARB
:
2564 if (value
== WGL_FULL_ACCELERATION_ARB
)
2566 else if (value
== WGL_NO_ACCELERATION_ARB
)
2570 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2571 pf
.accelerated
= value
;
2572 valid
.accelerated
= 1;
2575 case WGL_NEED_PALETTE_ARB
:
2576 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2577 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2578 if (value
) goto cant_match
;
2581 case WGL_SWAP_METHOD_ARB
:
2582 if (value
== WGL_SWAP_COPY_ARB
)
2584 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2588 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2589 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2590 pf
.backing_store
= value
;
2591 valid
.backing_store
= 1;
2594 case WGL_NUMBER_OVERLAYS_ARB
:
2595 case WGL_NUMBER_UNDERLAYS_ARB
:
2596 if (value
) goto cant_match
;
2599 case WGL_SHARE_DEPTH_ARB
:
2600 case WGL_SHARE_STENCIL_ARB
:
2601 case WGL_SHARE_ACCUM_ARB
:
2605 case WGL_SUPPORT_GDI_ARB
:
2606 if (value
) goto cant_match
;
2609 case WGL_SUPPORT_OPENGL_ARB
:
2610 if (!value
) goto cant_match
;
2613 case WGL_DOUBLE_BUFFER_ARB
:
2614 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2615 pf
.double_buffer
= (value
!= 0);
2616 valid
.double_buffer
= 1;
2617 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2620 case WGL_STEREO_ARB
:
2621 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2622 pf
.stereo
= (value
!= 0);
2626 case WGL_PIXEL_TYPE_ARB
:
2627 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2629 else if (value
== WGL_TYPE_RGBA_ARB
)
2633 /* Mac contexts don't support rendering to unsigned floating
2634 point formats, even if GL_EXT_packed_float is supported.
2635 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2638 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2639 if (srgb
&& value
) goto cant_match
;
2640 float_color
= value
;
2643 case WGL_COLOR_BITS_ARB
:
2644 if (color_bits
< value
) color_bits
= value
;
2647 case WGL_RED_BITS_ARB
:
2648 if (srgb
&& value
> 8) goto cant_match
;
2649 if (red_bits
< value
) red_bits
= value
;
2652 case WGL_GREEN_BITS_ARB
:
2653 if (srgb
&& value
> 8) goto cant_match
;
2654 if (green_bits
< value
) green_bits
= value
;
2657 case WGL_BLUE_BITS_ARB
:
2658 if (srgb
&& value
> 8) goto cant_match
;
2659 if (blue_bits
< value
) blue_bits
= value
;
2662 case WGL_ALPHA_BITS_ARB
:
2663 if (alpha_bits
< value
) alpha_bits
= value
;
2666 case WGL_ACCUM_BITS_ARB
:
2667 if (accum_bits
< value
) accum_bits
= value
;
2670 case WGL_ACCUM_RED_BITS_ARB
:
2671 if (accum_red_bits
< value
) accum_red_bits
= value
;
2674 case WGL_ACCUM_GREEN_BITS_ARB
:
2675 if (accum_green_bits
< value
) accum_green_bits
= value
;
2678 case WGL_ACCUM_BLUE_BITS_ARB
:
2679 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2682 case WGL_ACCUM_ALPHA_BITS_ARB
:
2683 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2686 case WGL_DEPTH_BITS_ARB
:
2687 if (value
> 255) goto cant_match
;
2688 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2691 case WGL_STENCIL_BITS_ARB
:
2692 if (value
> 255) goto cant_match
;
2693 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2696 case WGL_AUX_BUFFERS_ARB
:
2697 if (value
> 7) goto cant_match
;
2698 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2701 case WGL_SAMPLE_BUFFERS_ARB
:
2702 if (value
> 1) goto cant_match
;
2703 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2706 case WGL_SAMPLES_ARB
:
2707 if (value
> 31) goto cant_match
;
2708 if (pf
.samples
< value
) pf
.samples
= value
;
2711 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2712 /* sRGB is only supported for 8-bit integer color components */
2713 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2718 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2719 case WGL_RED_SHIFT_ARB
:
2720 case WGL_GREEN_SHIFT_ARB
:
2721 case WGL_BLUE_SHIFT_ARB
:
2722 case WGL_ALPHA_SHIFT_ARB
:
2723 case WGL_TRANSPARENT_ARB
:
2724 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2725 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2726 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2727 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2728 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2732 case WGL_DRAW_TO_PBUFFER_ARB
:
2733 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2734 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2735 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2736 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2737 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2738 pf
.pbuffer
= (value
!= 0);
2740 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2746 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2751 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",
2752 valid
.window
? (pf
.window
? "1" : "0") : "?",
2753 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2754 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2756 float_color
== -1 ? "?" : float_color
? "f" : "",
2770 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2771 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2772 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2776 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2778 const struct color_mode
*mode
;
2780 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2781 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2782 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2783 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2784 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2785 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2787 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2788 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2789 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2790 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2791 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2793 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2794 /* If the mode doesn't have alpha, check requested color bits against
2795 bits per pixel instead of the mode's color bits. On Windows, color
2796 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2797 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2798 expects that to match such a pixel format, we need to accommodate that. */
2799 if (mode
->alpha_bits
)
2801 if (mode
->color_bits
< color_bits
)
2806 if (mode
->bits_per_pixel
< color_bits
)
2809 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2810 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2812 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2813 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2816 if (pixel_formats
[i
].accum_mode
)
2818 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2819 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2820 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2821 mode
->alpha_bits
< accum_alpha_bits
)
2824 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2827 piFormats
[found
++] = i
+ 1;
2828 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2832 *nNumFormats
= found
;
2838 /***********************************************************************
2839 * macdrv_wglCreateContextAttribsARB
2841 * WGL_ARB_create_context: wglCreateContextAttribsARB
2843 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2844 struct wgl_context
*share_context
,
2845 const int *attrib_list
)
2848 struct wgl_context
*context
;
2850 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2852 GLint renderer_id
= 0;
2854 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2856 format
= get_dc_pixel_format(hdc
);
2858 if (!is_valid_pixel_format(format
))
2860 ERR("Invalid pixel format %d, expect problems!\n", format
);
2861 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2865 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2868 int value
= iptr
[1];
2870 TRACE("%s\n", debugstr_attrib(attr
, value
));
2874 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2878 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2882 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2883 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2886 case WGL_CONTEXT_FLAGS_ARB
:
2888 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2889 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2890 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2893 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2894 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2895 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2897 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2898 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2904 case WGL_RENDERER_ID_WINE
:
2907 CGLRendererInfoObj renderer_info
;
2908 GLint renderer_count
, temp
;
2910 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
2911 if (err
!= kCGLNoError
)
2913 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
2914 SetLastError(ERROR_GEN_FAILURE
);
2918 value
= map_renderer_index(renderer_info
, renderer_count
, value
);
2920 if (value
>= renderer_count
)
2922 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value
, renderer_count
);
2923 CGLDestroyRendererInfo(renderer_info
);
2924 SetLastError(ERROR_INVALID_PARAMETER
);
2928 if (!get_renderer_property(renderer_info
, value
, kCGLRPRendererID
, &temp
))
2930 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value
);
2931 CGLDestroyRendererInfo(renderer_info
);
2932 SetLastError(ERROR_GEN_FAILURE
);
2936 CGLDestroyRendererInfo(renderer_info
);
2938 if (renderer_id
&& temp
!= renderer_id
)
2940 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id
, temp
);
2941 SetLastError(ERROR_INVALID_PARAMETER
);
2949 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2950 SetLastError(ERROR_INVALID_PARAMETER
);
2955 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2956 (major
== 4 && (minor
== 0 || minor
== 1)))
2958 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2960 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2961 SetLastError(ERROR_INVALID_VERSION_ARB
);
2964 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2966 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2967 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2970 if (major
> gl_info
.max_major
||
2971 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2973 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2975 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2980 else if (major
>= 3)
2982 WARN("Profile version %u.%u not supported\n", major
, minor
);
2983 SetLastError(ERROR_INVALID_VERSION_ARB
);
2986 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2987 (major
== 2 && (minor
< 0 || minor
> 1)))
2989 WARN("Invalid GL version requested\n");
2990 SetLastError(ERROR_INVALID_VERSION_ARB
);
2993 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2995 WARN("Forward compatible context requested for GL version < 3\n");
2996 SetLastError(ERROR_INVALID_VERSION_ARB
);
3000 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3002 context
->format
= format
;
3003 context
->renderer_id
= renderer_id
;
3004 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
3006 HeapFree(GetProcessHeap(), 0, context
);
3010 EnterCriticalSection(&context_section
);
3011 list_add_tail(&context_list
, &context
->entry
);
3012 LeaveCriticalSection(&context_section
);
3018 /**********************************************************************
3019 * macdrv_wglCreatePbufferARB
3021 * WGL_ARB_pbuffer: wglCreatePbufferARB
3023 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
3024 const int *piAttribList
)
3026 struct wgl_pbuffer
* pbuffer
;
3028 GLenum internalFormat
= 0;
3031 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
3032 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
3034 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
3036 WARN("invalid pixel format %d\n", iPixelFormat
);
3037 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3041 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
3042 pbuffer
->format
= iPixelFormat
;
3044 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3046 int attr
= piAttribList
[0];
3047 int value
= piAttribList
[1];
3051 case WGL_PBUFFER_LARGEST_ARB
:
3052 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
3055 case WGL_TEXTURE_FORMAT_ARB
:
3058 case WGL_TEXTURE_RGBA_ARB
:
3059 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
3060 internalFormat
= GL_RGBA
;
3062 case WGL_TEXTURE_RGB_ARB
:
3063 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
3064 internalFormat
= GL_RGB
;
3066 case WGL_NO_TEXTURE_ARB
:
3067 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
3071 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
3072 SetLastError(ERROR_INVALID_DATA
);
3077 case WGL_TEXTURE_TARGET_ARB
:
3081 case WGL_NO_TEXTURE_ARB
:
3082 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
3085 case WGL_TEXTURE_CUBE_MAP_ARB
:
3086 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
3087 target
= GL_TEXTURE_CUBE_MAP
;
3088 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
3090 case WGL_TEXTURE_1D_ARB
:
3091 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
3092 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
3094 case WGL_TEXTURE_2D_ARB
:
3095 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
3096 target
= GL_TEXTURE_2D
;
3098 case WGL_TEXTURE_RECTANGLE_NV
:
3099 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
3100 target
= GL_TEXTURE_RECTANGLE
;
3103 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
3104 SetLastError(ERROR_INVALID_DATA
);
3109 case WGL_MIPMAP_TEXTURE_ARB
:
3110 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
3111 pbuffer
->max_level
= 0;
3114 int size
= min(iWidth
, iHeight
) / 2;
3117 pbuffer
->max_level
++;
3124 WARN("unknown attribute 0x%x\n", attr
);
3125 SetLastError(ERROR_INVALID_DATA
);
3130 if (!target
|| !internalFormat
)
3132 pbuffer
->no_texture
= TRUE
;
3133 /* no actual way to turn off ability to texture; use most permissive target */
3134 target
= GL_TEXTURE_RECTANGLE
;
3135 internalFormat
= GL_RGB
;
3138 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
3139 if (err
!= kCGLNoError
)
3141 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
3142 pbuffer
->pbuffer
= NULL
;
3143 if (err
== kCGLBadAlloc
)
3144 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
3146 SetLastError(ERROR_INVALID_DATA
);
3150 if (!pbuffer
->pbuffer
)
3152 HeapFree(GetProcessHeap(), 0, pbuffer
);
3156 TRACE(" -> %p\n", pbuffer
);
3161 /**********************************************************************
3162 * macdrv_wglDestroyPbufferARB
3164 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3166 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
3168 TRACE("pbuffer %p\n", pbuffer
);
3169 if (pbuffer
&& pbuffer
->pbuffer
)
3170 CGLReleasePBuffer(pbuffer
->pbuffer
);
3171 HeapFree(GetProcessHeap(), 0, pbuffer
);
3176 /**********************************************************************
3177 * macdrv_wglGetExtensionsStringARB
3179 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3181 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
3183 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3184 this can be specific to the CGL renderer like we're supposed to do. */
3185 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3186 return gl_info
.wglExtensions
;
3190 /**********************************************************************
3191 * macdrv_wglGetExtensionsStringEXT
3193 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3195 static const char *macdrv_wglGetExtensionsStringEXT(void)
3197 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3198 return gl_info
.wglExtensions
;
3202 /**********************************************************************
3203 * macdrv_wglGetPbufferDCARB
3205 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3207 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
3210 struct wgl_pbuffer
*prev
;
3212 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
3215 EnterCriticalSection(&dc_pbuffers_section
);
3216 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3219 CGLReleasePBuffer(prev
->pbuffer
);
3220 HeapFree(GetProcessHeap(), 0, prev
);
3222 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
3223 LeaveCriticalSection(&dc_pbuffers_section
);
3225 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
3230 /**********************************************************************
3231 * macdrv_wglGetPixelFormatAttribivARB
3233 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3235 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3236 UINT nAttributes
, const int *piAttributes
, int *piValues
)
3238 const pixel_format
*pf
;
3241 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3242 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
3244 if (!nAttributes
) return GL_TRUE
;
3246 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
3248 piValues
[0] = nb_formats
;
3249 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
3253 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
3256 WARN("invalid pixel format %d\n", iPixelFormat
);
3257 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3261 for (i
= 0; i
< nAttributes
; ++i
)
3263 switch (piAttributes
[i
])
3265 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
3266 piValues
[i
] = nb_formats
;
3269 case WGL_DRAW_TO_WINDOW_ARB
:
3270 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
3273 case WGL_DRAW_TO_BITMAP_ARB
:
3274 piValues
[i
] = GL_FALSE
;
3277 case WGL_ACCELERATION_ARB
:
3278 if (iLayerPlane
) goto invalid_layer
;
3279 if (pf
->accelerated
)
3280 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
3282 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
3285 case WGL_NEED_PALETTE_ARB
:
3286 case WGL_NEED_SYSTEM_PALETTE_ARB
:
3287 case WGL_SWAP_LAYER_BUFFERS_ARB
:
3288 piValues
[i
] = GL_FALSE
;
3291 case WGL_SWAP_METHOD_ARB
:
3292 if (pf
->double_buffer
&& pf
->backing_store
)
3293 piValues
[i
] = WGL_SWAP_COPY_ARB
;
3295 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
3298 case WGL_NUMBER_OVERLAYS_ARB
:
3299 case WGL_NUMBER_UNDERLAYS_ARB
:
3303 case WGL_TRANSPARENT_ARB
:
3304 if (iLayerPlane
) goto invalid_layer
;
3305 piValues
[i
] = GL_FALSE
;
3308 case WGL_TRANSPARENT_RED_VALUE_ARB
:
3309 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
3310 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
3311 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
3312 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
3313 if (iLayerPlane
) goto invalid_layer
;
3317 case WGL_SHARE_DEPTH_ARB
:
3318 case WGL_SHARE_STENCIL_ARB
:
3319 case WGL_SHARE_ACCUM_ARB
:
3320 if (iLayerPlane
) goto invalid_layer
;
3321 piValues
[i
] = GL_TRUE
;
3324 case WGL_SUPPORT_GDI_ARB
:
3325 if (iLayerPlane
) goto invalid_layer
;
3326 piValues
[i
] = GL_FALSE
;
3329 case WGL_SUPPORT_OPENGL_ARB
:
3330 if (iLayerPlane
) goto invalid_layer
;
3331 piValues
[i
] = GL_TRUE
;
3334 case WGL_DOUBLE_BUFFER_ARB
:
3335 if (iLayerPlane
) goto invalid_layer
;
3336 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
3339 case WGL_STEREO_ARB
:
3340 if (iLayerPlane
) goto invalid_layer
;
3341 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
3344 case WGL_PIXEL_TYPE_ARB
:
3345 if (iLayerPlane
) goto invalid_layer
;
3346 if (color_modes
[pf
->color_mode
].is_float
)
3347 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
3349 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
3350 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3351 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3352 However, Mac contexts don't support rendering to unsigned floating-point
3353 formats, even when GL_EXT_packed_float is supported. */
3356 case WGL_COLOR_BITS_ARB
:
3357 if (iLayerPlane
) goto invalid_layer
;
3358 /* If the mode doesn't have alpha, return bits per pixel instead
3359 of color bits. On Windows, color bits sometimes exceeds r+g+b
3360 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3361 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3362 pixel format, we need to accommodate that. */
3363 if (color_modes
[pf
->color_mode
].alpha_bits
)
3364 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
3366 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
3369 case WGL_RED_BITS_ARB
:
3370 if (iLayerPlane
) goto invalid_layer
;
3371 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
3374 case WGL_RED_SHIFT_ARB
:
3375 if (iLayerPlane
) goto invalid_layer
;
3376 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
3379 case WGL_GREEN_BITS_ARB
:
3380 if (iLayerPlane
) goto invalid_layer
;
3381 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
3384 case WGL_GREEN_SHIFT_ARB
:
3385 if (iLayerPlane
) goto invalid_layer
;
3386 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
3389 case WGL_BLUE_BITS_ARB
:
3390 if (iLayerPlane
) goto invalid_layer
;
3391 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
3394 case WGL_BLUE_SHIFT_ARB
:
3395 if (iLayerPlane
) goto invalid_layer
;
3396 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
3399 case WGL_ALPHA_BITS_ARB
:
3400 if (iLayerPlane
) goto invalid_layer
;
3401 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
3404 case WGL_ALPHA_SHIFT_ARB
:
3405 if (iLayerPlane
) goto invalid_layer
;
3406 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
3409 case WGL_ACCUM_BITS_ARB
:
3410 if (iLayerPlane
) goto invalid_layer
;
3412 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3417 case WGL_ACCUM_RED_BITS_ARB
:
3418 if (iLayerPlane
) goto invalid_layer
;
3420 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
3425 case WGL_ACCUM_GREEN_BITS_ARB
:
3426 if (iLayerPlane
) goto invalid_layer
;
3428 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
3433 case WGL_ACCUM_BLUE_BITS_ARB
:
3434 if (iLayerPlane
) goto invalid_layer
;
3436 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
3441 case WGL_ACCUM_ALPHA_BITS_ARB
:
3442 if (iLayerPlane
) goto invalid_layer
;
3444 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
3449 case WGL_DEPTH_BITS_ARB
:
3450 if (iLayerPlane
) goto invalid_layer
;
3451 piValues
[i
] = pf
->depth_bits
;
3454 case WGL_STENCIL_BITS_ARB
:
3455 if (iLayerPlane
) goto invalid_layer
;
3456 piValues
[i
] = pf
->stencil_bits
;
3459 case WGL_AUX_BUFFERS_ARB
:
3460 if (iLayerPlane
) goto invalid_layer
;
3461 piValues
[i
] = pf
->aux_buffers
;
3464 case WGL_SAMPLE_BUFFERS_ARB
:
3465 if (iLayerPlane
) goto invalid_layer
;
3466 piValues
[i
] = pf
->sample_buffers
;
3469 case WGL_SAMPLES_ARB
:
3470 if (iLayerPlane
) goto invalid_layer
;
3471 piValues
[i
] = pf
->samples
;
3474 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3475 if (iLayerPlane
) goto invalid_layer
;
3476 /* sRGB is only supported for 8-bit integer color components */
3477 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
3478 color_modes
[pf
->color_mode
].green_bits
== 8 &&
3479 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
3480 !color_modes
[pf
->color_mode
].is_float
)
3481 piValues
[i
] = GL_TRUE
;
3483 piValues
[i
] = GL_FALSE
;
3486 case WGL_DRAW_TO_PBUFFER_ARB
:
3487 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
3488 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
3489 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
3492 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
3493 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
3494 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
3497 case WGL_MAX_PBUFFER_WIDTH_ARB
:
3498 piValues
[i
] = gl_info
.max_viewport_dims
[0];
3501 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
3502 piValues
[i
] = gl_info
.max_viewport_dims
[1];
3505 case WGL_MAX_PBUFFER_PIXELS_ARB
:
3506 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
3510 WARN("invalid attribute %x\n", piAttributes
[i
]);
3514 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
3520 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
3525 /**********************************************************************
3526 * macdrv_wglGetPixelFormatAttribfvARB
3528 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3530 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3531 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
3536 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3537 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
3539 /* Allocate a temporary array to store integer values */
3540 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
3543 ERR("couldn't allocate %d array\n", nAttributes
);
3547 /* Piggy-back on wglGetPixelFormatAttribivARB */
3548 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
3553 /* Convert integer values to float. Should also check for attributes
3554 that can give decimal values here */
3555 for (i
= 0; i
< nAttributes
; i
++)
3556 pfValues
[i
] = attr
[i
];
3559 HeapFree(GetProcessHeap(), 0, attr
);
3564 /**********************************************************************
3565 * macdrv_wglGetSwapIntervalEXT
3567 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3569 static int macdrv_wglGetSwapIntervalEXT(void)
3571 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3572 struct macdrv_win_data
*data
;
3578 if ((data
= get_win_data(context
->draw_hwnd
)))
3580 value
= data
->swap_interval
;
3581 release_win_data(data
);
3583 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3584 set_swap_interval(context
, value
);
3588 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3589 if (err
!= kCGLNoError
)
3591 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3592 err
, CGLErrorString(err
));
3601 /***********************************************************************
3602 * macdrv_wglMakeContextCurrentARB
3604 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3606 * This is not supported directly by OpenGL on the Mac. We emulate it
3607 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3608 * temporarily swap the drawable. This follows the technique used in
3609 * the implementation of Mesa GLX for Apple.
3611 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3613 struct macdrv_win_data
*data
;
3616 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3617 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3621 macdrv_make_context_current(NULL
, NULL
, CGRectNull
);
3622 NtCurrentTeb()->glContext
= NULL
;
3626 if ((hwnd
= WindowFromDC(draw_hdc
)))
3628 if (!(data
= get_win_data(hwnd
)))
3630 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3634 if (!data
->pixel_format
)
3636 WARN("no pixel format set\n");
3637 release_win_data(data
);
3638 SetLastError(ERROR_INVALID_HANDLE
);
3641 if (context
->format
!= data
->pixel_format
)
3643 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3644 release_win_data(data
);
3645 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3649 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
3650 set_swap_interval(context
, data
->swap_interval
);
3652 context
->draw_hwnd
= hwnd
;
3653 context
->draw_view
= data
->gl_view
;
3654 context
->draw_rect
= data
->gl_rect
;
3655 context
->draw_pbuffer
= NULL
;
3656 release_win_data(data
);
3660 struct wgl_pbuffer
*pbuffer
;
3662 EnterCriticalSection(&dc_pbuffers_section
);
3663 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3666 if (context
->format
!= pbuffer
->format
)
3668 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3669 LeaveCriticalSection(&dc_pbuffers_section
);
3670 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3675 (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
))
3676 set_swap_interval(context
, 0);
3680 WARN("no window or pbuffer for DC\n");
3681 LeaveCriticalSection(&dc_pbuffers_section
);
3682 SetLastError(ERROR_INVALID_HANDLE
);
3686 context
->draw_hwnd
= NULL
;
3687 context
->draw_view
= NULL
;
3688 context
->draw_pbuffer
= pbuffer
;
3689 LeaveCriticalSection(&dc_pbuffers_section
);
3692 context
->read_view
= NULL
;
3693 context
->read_pbuffer
= NULL
;
3694 if (read_hdc
&& read_hdc
!= draw_hdc
)
3696 if ((hwnd
= WindowFromDC(read_hdc
)))
3698 if ((data
= get_win_data(hwnd
)))
3700 if (data
->gl_view
!= context
->draw_view
)
3702 context
->read_view
= data
->gl_view
;
3703 context
->read_rect
= data
->gl_rect
;
3705 release_win_data(data
);
3710 EnterCriticalSection(&dc_pbuffers_section
);
3711 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3712 LeaveCriticalSection(&dc_pbuffers_section
);
3716 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3717 context
->draw_view
, wine_dbgstr_rect(&context
->draw_rect
), context
->draw_pbuffer
,
3718 context
->read_view
, wine_dbgstr_rect(&context
->read_rect
), context
->read_pbuffer
, context
->format
);
3720 make_context_current(context
, FALSE
);
3721 context
->has_been_current
= TRUE
;
3722 NtCurrentTeb()->glContext
= context
;
3728 /**********************************************************************
3729 * macdrv_wglQueryCurrentRendererIntegerWINE
3731 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3733 static BOOL
macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute
, GLuint
*value
)
3736 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3737 CGLPixelFormatObj pixel_format
;
3739 GLint virtual_screen
;
3741 GLint pf_renderer_id
;
3742 CGLRendererInfoObj renderer_info
;
3743 GLint renderer_count
;
3746 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context
, (context
? context
->context
: NULL
),
3747 (context
? context
->cglcontext
: NULL
), attribute
, value
);
3749 if (attribute
== WGL_RENDERER_VERSION_WINE
)
3751 if (!parse_renderer_version((const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
), value
))
3752 get_fallback_renderer_version(value
);
3753 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
3757 pixel_format
= CGLGetPixelFormat(context
->cglcontext
);
3758 err
= CGLGetVirtualScreen(context
->cglcontext
, &virtual_screen
);
3759 if (err
!= kCGLNoError
)
3761 WARN("CGLGetVirtualScreen failed: %d %s\n", err
, CGLErrorString(err
));
3765 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFADisplayMask
, &display_mask
);
3766 if (err
!= kCGLNoError
)
3768 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err
, CGLErrorString(err
));
3772 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFARendererID
, &pf_renderer_id
);
3773 if (err
!= kCGLNoError
)
3775 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err
, CGLErrorString(err
));
3779 err
= CGLQueryRendererInfo(display_mask
, &renderer_info
, &renderer_count
);
3780 if (err
!= kCGLNoError
)
3782 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3786 for (renderer
= 0; renderer
< renderer_count
; renderer
++)
3790 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
3793 if (renderer_id
== pf_renderer_id
)
3795 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3800 if (renderer
>= renderer_count
)
3801 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id
, display_mask
);
3803 CGLDestroyRendererInfo(renderer_info
);
3808 /**********************************************************************
3809 * macdrv_wglQueryCurrentRendererStringWINE
3811 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3813 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute
)
3815 const char* ret
= NULL
;
3816 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3818 TRACE("context %p/%p/%p attribute 0x%04x\n", context
, (context
? context
->context
: NULL
),
3819 (context
? context
->cglcontext
: NULL
), attribute
);
3823 case WGL_RENDERER_DEVICE_ID_WINE
:
3825 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_RENDERER
);
3826 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret
));
3830 case WGL_RENDERER_VENDOR_ID_WINE
:
3832 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VENDOR
);
3833 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret
));
3838 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3846 /**********************************************************************
3847 * macdrv_wglQueryPbufferARB
3849 * WGL_ARB_pbuffer: wglQueryPbufferARB
3851 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3857 GLenum internalFormat
;
3860 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3862 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3863 if (err
!= kCGLNoError
)
3865 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3866 SetLastError(ERROR_INVALID_HANDLE
);
3872 case WGL_PBUFFER_WIDTH_ARB
:
3875 case WGL_PBUFFER_HEIGHT_ARB
:
3878 case WGL_PBUFFER_LOST_ARB
:
3879 /* Mac PBuffers can't be lost */
3880 *piValue
= GL_FALSE
;
3882 case WGL_TEXTURE_FORMAT_ARB
:
3883 if (pbuffer
->no_texture
)
3884 *piValue
= WGL_NO_TEXTURE_ARB
;
3885 else switch (internalFormat
)
3888 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3892 *piValue
= WGL_TEXTURE_RGB_ARB
;
3896 case WGL_TEXTURE_TARGET_ARB
:
3897 if (pbuffer
->no_texture
)
3898 *piValue
= WGL_NO_TEXTURE_ARB
;
3899 else switch (target
)
3901 case GL_TEXTURE_CUBE_MAP
:
3902 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3905 *piValue
= WGL_TEXTURE_2D_ARB
;
3907 case GL_TEXTURE_RECTANGLE
:
3909 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3913 case WGL_MIPMAP_TEXTURE_ARB
:
3914 *piValue
= (pbuffer
->max_level
> 0);
3916 case WGL_MIPMAP_LEVEL_ARB
:
3917 *piValue
= pbuffer
->level
;
3919 case WGL_CUBE_MAP_FACE_ARB
:
3920 switch (pbuffer
->face
)
3922 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3924 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3926 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3927 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3929 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3930 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3932 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3933 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3935 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3936 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3938 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3939 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3944 WARN("invalid attribute 0x%x\n", iAttribute
);
3945 SetLastError(ERROR_INVALID_DATA
);
3953 /**********************************************************************
3954 * macdrv_wglQueryRendererIntegerWINE
3956 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3958 static BOOL
macdrv_wglQueryRendererIntegerWINE(HDC dc
, GLint renderer
, GLenum attribute
, GLuint
*value
)
3961 CGLRendererInfoObj renderer_info
;
3962 GLint renderer_count
;
3965 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc
, renderer
, attribute
, value
);
3967 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3968 if (err
!= kCGLNoError
)
3970 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3974 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3976 if (renderer
< renderer_count
)
3977 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3979 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3981 CGLDestroyRendererInfo(renderer_info
);
3986 /**********************************************************************
3987 * macdrv_wglQueryRendererStringWINE
3989 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3991 static const char *macdrv_wglQueryRendererStringWINE(HDC dc
, GLint renderer
, GLenum attribute
)
3993 const char* ret
= NULL
;
3994 CGLRendererInfoObj renderer_info
;
3995 GLint renderer_count
;
3998 TRACE("dc %p renderer %d attribute 0x%04x\n", dc
, renderer
, attribute
);
4000 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
4001 if (err
!= kCGLNoError
)
4003 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
4007 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
4009 if (renderer
>= renderer_count
)
4011 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
4017 case WGL_RENDERER_DEVICE_ID_WINE
:
4018 case WGL_RENDERER_VENDOR_ID_WINE
:
4020 BOOL device
= (attribute
== WGL_RENDERER_DEVICE_ID_WINE
);
4021 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
4024 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
4027 ret
= get_gl_string(pixel_format
, device
? GL_RENDERER
: GL_VENDOR
);
4028 CGLReleasePixelFormat(pixel_format
);
4031 TRACE("%s -> %s\n", device
? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret
));
4036 FIXME("unrecognized attribute 0x%04x\n", attribute
);
4041 CGLDestroyRendererInfo(renderer_info
);
4046 /**********************************************************************
4047 * macdrv_wglReleasePbufferDCARB
4049 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
4051 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
4053 struct wgl_pbuffer
*prev
;
4055 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
4057 EnterCriticalSection(&dc_pbuffers_section
);
4059 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4062 if (prev
!= pbuffer
)
4063 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
4064 CGLReleasePBuffer(prev
->pbuffer
);
4065 HeapFree(GetProcessHeap(), 0, prev
);
4066 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
4070 LeaveCriticalSection(&dc_pbuffers_section
);
4072 return hdc
&& DeleteDC(hdc
);
4076 /**********************************************************************
4077 * macdrv_wglReleaseTexImageARB
4079 * WGL_ARB_render_texture: wglReleaseTexImageARB
4081 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
4083 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4086 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
4088 if (pbuffer
->no_texture
)
4090 SetLastError(ERROR_INVALID_OPERATION
);
4094 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
4095 if (err
!= kCGLNoError
)
4097 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
4098 SetLastError(ERROR_INVALID_OPERATION
);
4106 /**********************************************************************
4107 * macdrv_wglSetPbufferAttribARB
4109 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4111 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
4113 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4115 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
4117 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
4119 int attr
= piAttribList
[0];
4120 int value
= piAttribList
[1];
4123 case WGL_MIPMAP_LEVEL_ARB
:
4124 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
4125 pbuffer
->level
= value
;
4127 case WGL_CUBE_MAP_FACE_ARB
:
4130 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
4131 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4132 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
4134 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4135 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4136 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
4138 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4139 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4140 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
4142 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4143 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4144 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
4146 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4147 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4148 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
4150 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4151 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4152 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
4155 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
4156 SetLastError(ERROR_INVALID_DATA
);
4161 WARN("invalide attribute 0x%x\n", attr
);
4162 SetLastError(ERROR_INVALID_DATA
);
4167 if (context
&& context
->draw_pbuffer
== pbuffer
)
4168 make_context_current(context
, FALSE
);
4174 /**********************************************************************
4175 * macdrv_wglSetPixelFormatWINE
4177 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4179 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
4181 return set_pixel_format(hdc
, fmt
, TRUE
);
4185 /**********************************************************************
4186 * macdrv_wglSwapIntervalEXT
4188 * WGL_EXT_swap_control: wglSwapIntervalEXT
4190 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
4192 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4193 BOOL changed
= FALSE
;
4195 TRACE("interval %d\n", interval
);
4199 SetLastError(ERROR_INVALID_DATA
);
4205 if (context
->draw_hwnd
)
4207 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
4210 changed
= data
->swap_interval
!= interval
;
4212 data
->swap_interval
= interval
;
4213 release_win_data(data
);
4219 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
4220 if (!set_swap_interval(context
, interval
))
4222 SetLastError(ERROR_GEN_FAILURE
);
4228 struct wgl_context
*ctx
;
4230 EnterCriticalSection(&context_section
);
4231 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
4233 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
4234 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
4236 LeaveCriticalSection(&context_section
);
4243 static void register_extension(const char *ext
)
4245 if (gl_info
.wglExtensions
[0])
4246 strcat(gl_info
.wglExtensions
, " ");
4247 strcat(gl_info
.wglExtensions
, ext
);
4249 TRACE("'%s'\n", ext
);
4252 static void load_extensions(void)
4257 register_extension("WGL_ARB_extensions_string");
4258 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
4260 register_extension("WGL_ARB_make_current_read");
4261 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
4262 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
4264 register_extension("WGL_ARB_pixel_format");
4265 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
4266 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
4267 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
4269 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
4271 register_extension("WGL_ARB_pixel_format_float");
4272 register_extension("WGL_ATI_pixel_format_float");
4275 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
4276 register_extension("WGL_ARB_multisample");
4278 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4279 register_extension("WGL_ARB_framebuffer_sRGB");
4281 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
4283 register_extension("WGL_ARB_pbuffer");
4284 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
4285 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
4286 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
4287 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
4288 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
4290 register_extension("WGL_ARB_render_texture");
4291 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
4292 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
4293 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
4295 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
4296 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
4297 register_extension("WGL_NV_render_texture_rectangle");
4300 register_extension("WGL_ARB_create_context");
4301 register_extension("WGL_ARB_create_context_profile");
4302 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
4307 register_extension("WGL_EXT_extensions_string");
4308 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
4312 register_extension("WGL_EXT_swap_control");
4313 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
4314 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
4317 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4318 check for either, so register them separately. */
4319 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4320 register_extension("WGL_EXT_framebuffer_sRGB");
4322 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
4323 register_extension("WGL_EXT_pixel_format_packed_float");
4326 * WINE-specific WGL Extensions
4329 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4330 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4332 register_extension("WGL_WINE_pixel_format_passthrough");
4333 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
4335 register_extension("WGL_WINE_query_renderer");
4336 opengl_funcs
.ext
.p_wglQueryCurrentRendererIntegerWINE
= macdrv_wglQueryCurrentRendererIntegerWINE
;
4337 opengl_funcs
.ext
.p_wglQueryCurrentRendererStringWINE
= macdrv_wglQueryCurrentRendererStringWINE
;
4338 opengl_funcs
.ext
.p_wglQueryRendererIntegerWINE
= macdrv_wglQueryRendererIntegerWINE
;
4339 opengl_funcs
.ext
.p_wglQueryRendererStringWINE
= macdrv_wglQueryRendererStringWINE
;
4343 static BOOL
init_opengl(void)
4345 static BOOL init_done
= FALSE
;
4349 if (init_done
) return (opengl_handle
!= NULL
);
4354 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
4357 WARN("CFDictionaryCreateMutable failed\n");
4361 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
4364 ERR("Failed to load OpenGL: %s\n", buffer
);
4365 ERR("OpenGL support is disabled.\n");
4369 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
4371 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
4373 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
4378 /* redirect some standard OpenGL functions */
4379 #define REDIRECT(func) \
4380 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4381 REDIRECT(glCopyPixels
);
4382 REDIRECT(glGetString
);
4383 REDIRECT(glReadPixels
);
4384 REDIRECT(glViewport
);
4385 if (skip_single_buffer_flushes
|| allow_vsync
)
4391 /* redirect some OpenGL extension functions */
4392 #define REDIRECT(func) \
4393 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4394 REDIRECT(glCopyColorTable
);
4397 if (!init_gl_info())
4400 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
4401 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
4404 if (!init_pixel_formats())
4410 wine_dlclose(opengl_handle
, NULL
, 0);
4411 opengl_handle
= NULL
;
4416 /***********************************************************************
4419 * Synchronize the Mac GL view position with the Windows child window
4422 void sync_gl_view(struct macdrv_win_data
*data
)
4426 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
4428 if (!data
->gl_view
) return;
4430 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
4432 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
4433 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
4434 data
->gl_rect
= rect
;
4435 mark_contexts_for_moved_view(data
->gl_view
);
4440 /**********************************************************************
4441 * macdrv_wglDescribePixelFormat
4443 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
4445 const pixel_format
*pf
;
4446 const struct color_mode
*mode
;
4448 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
4450 if (!descr
) return nb_displayable_formats
;
4451 if (size
< sizeof(*descr
)) return 0;
4453 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
4456 memset(descr
, 0, sizeof(*descr
));
4457 descr
->nSize
= sizeof(*descr
);
4458 descr
->nVersion
= 1;
4460 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
4461 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
4462 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
4463 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
4464 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
4465 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
4467 descr
->iPixelType
= PFD_TYPE_RGBA
;
4469 mode
= &color_modes
[pf
->color_mode
];
4470 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4471 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4472 R8G8B8A0 pixel format). If an app depends on that and expects that
4473 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4474 if (mode
->alpha_bits
)
4475 descr
->cColorBits
= mode
->color_bits
;
4477 descr
->cColorBits
= mode
->bits_per_pixel
;
4478 descr
->cRedBits
= mode
->red_bits
;
4479 descr
->cRedShift
= mode
->red_shift
;
4480 descr
->cGreenBits
= mode
->green_bits
;
4481 descr
->cGreenShift
= mode
->green_shift
;
4482 descr
->cBlueBits
= mode
->blue_bits
;
4483 descr
->cBlueShift
= mode
->blue_shift
;
4484 descr
->cAlphaBits
= mode
->alpha_bits
;
4485 descr
->cAlphaShift
= mode
->alpha_shift
;
4489 mode
= &color_modes
[pf
->accum_mode
- 1];
4490 descr
->cAccumBits
= mode
->color_bits
;
4491 descr
->cAccumRedBits
= mode
->red_bits
;
4492 descr
->cAccumGreenBits
= mode
->green_bits
;
4493 descr
->cAccumBlueBits
= mode
->blue_bits
;
4494 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
4497 descr
->cDepthBits
= pf
->depth_bits
;
4498 descr
->cStencilBits
= pf
->stencil_bits
;
4499 descr
->cAuxBuffers
= pf
->aux_buffers
;
4500 descr
->iLayerType
= PFD_MAIN_PLANE
;
4502 TRACE("%s\n", debugstr_pf(pf
));
4503 return nb_displayable_formats
;
4506 /***********************************************************************
4507 * macdrv_wglCopyContext
4509 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
4513 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
4515 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
4516 if (err
!= kCGLNoError
)
4517 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
4518 return (err
== kCGLNoError
);
4521 /***********************************************************************
4522 * macdrv_wglCreateContext
4524 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
4526 struct wgl_context
*context
;
4528 TRACE("hdc %p\n", hdc
);
4530 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
4535 /***********************************************************************
4536 * macdrv_wglDeleteContext
4538 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
4540 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
4542 EnterCriticalSection(&context_section
);
4543 list_remove(&context
->entry
);
4544 LeaveCriticalSection(&context_section
);
4546 macdrv_dispose_opengl_context(context
->context
);
4547 HeapFree(GetProcessHeap(), 0, context
);
4550 /***********************************************************************
4551 * macdrv_wglGetPixelFormat
4553 static int macdrv_wglGetPixelFormat(HDC hdc
)
4557 format
= get_dc_pixel_format(hdc
);
4559 if (!is_valid_pixel_format(format
)) /* not set yet */
4561 else if (!is_displayable_pixel_format(format
))
4563 /* Non-displayable formats can't be used with traditional WGL calls.
4564 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4568 TRACE(" hdc %p -> %d\n", hdc
, format
);
4572 /***********************************************************************
4573 * macdrv_wglGetProcAddress
4575 static PROC
macdrv_wglGetProcAddress(const char *proc
)
4579 if (!strncmp(proc
, "wgl", 3)) return NULL
;
4580 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
4586 if (dladdr(ret
, &info
))
4587 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
4589 TRACE("%s -> %p (no library info)\n", proc
, ret
);
4593 WARN("failed to find proc %s\n", debugstr_a(proc
));
4597 /***********************************************************************
4598 * macdrv_wglMakeCurrent
4600 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
4602 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4603 (context
? context
->cglcontext
: NULL
));
4605 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
4608 /**********************************************************************
4609 * macdrv_wglSetPixelFormat
4611 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
4613 return set_pixel_format(hdc
, fmt
, FALSE
);
4616 /***********************************************************************
4617 * macdrv_wglShareLists
4619 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
4621 macdrv_opengl_context saved_context
;
4622 CGLContextObj saved_cglcontext
;
4624 TRACE("org %p dest %p\n", org
, dest
);
4626 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4627 * at context creation time but in case of WGL it is done using wglShareLists.
4629 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4630 * and when a program requests sharing we recreate the destination context if it hasn't been made
4631 * current or when it hasn't shared display lists before.
4634 if (dest
->has_been_current
)
4636 WARN("could not share display lists, the destination context has been current already\n");
4639 else if (dest
->sharing
)
4641 WARN("could not share display lists because dest has already shared lists before\n");
4645 /* Re-create the Mac context and share display lists */
4646 saved_context
= dest
->context
;
4647 saved_cglcontext
= dest
->cglcontext
;
4648 dest
->context
= NULL
;
4649 dest
->cglcontext
= NULL
;
4650 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
4652 dest
->context
= saved_context
;
4653 dest
->cglcontext
= saved_cglcontext
;
4657 /* Implicitly disposes of saved_cglcontext. */
4658 macdrv_dispose_opengl_context(saved_context
);
4660 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4661 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
4663 org
->sharing
= TRUE
;
4664 dest
->sharing
= TRUE
;
4669 /**********************************************************************
4670 * macdrv_wglSwapBuffers
4672 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
4674 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4678 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4679 (context
? context
->cglcontext
: NULL
));
4683 sync_swap_interval(context
);
4684 sync_context(context
);
4687 if ((hwnd
= WindowFromDC(hdc
)))
4689 struct macdrv_win_data
*data
;
4691 if (!(data
= get_win_data(hwnd
)))
4693 SetLastError(ERROR_INVALID_HANDLE
);
4697 if (context
&& context
->draw_view
== data
->gl_view
)
4700 release_win_data(data
);
4704 struct wgl_pbuffer
*pbuffer
;
4706 EnterCriticalSection(&dc_pbuffers_section
);
4707 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4708 LeaveCriticalSection(&dc_pbuffers_section
);
4712 SetLastError(ERROR_INVALID_HANDLE
);
4716 if (context
&& context
->draw_pbuffer
== pbuffer
)
4721 macdrv_flush_opengl_context(context
->context
);
4724 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
4726 /* If there is a current context, then wglSwapBuffers should do an implicit
4727 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4728 in the other branch, but we have to do it explicitly here. */
4736 static struct opengl_funcs opengl_funcs
=
4739 macdrv_wglCopyContext
, /* p_wglCopyContext */
4740 macdrv_wglCreateContext
, /* p_wglCreateContext */
4741 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
4742 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
4743 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
4744 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
4745 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
4746 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
4747 macdrv_wglShareLists
, /* p_wglShareLists */
4748 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
4752 /**********************************************************************
4753 * macdrv_wine_get_wgl_driver
4755 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
4757 if (version
!= WINE_WGL_DRIVER_VERSION
)
4759 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
4763 if (!init_opengl()) return (void *)-1;
4765 return &opengl_funcs
;