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/debug.h"
32 #include "wine/wgl_driver.h"
34 #define GL_SILENCE_DEPRECATION
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
48 char wglExtensions
[4096];
50 GLint max_viewport_dims
[2];
52 unsigned int max_major
, max_minor
;
55 static struct gl_info gl_info
;
63 macdrv_opengl_context context
;
64 CGLContextObj cglcontext
;
66 macdrv_view draw_view
;
68 struct wgl_pbuffer
*draw_pbuffer
;
69 macdrv_view read_view
;
71 struct wgl_pbuffer
*read_pbuffer
;
72 BOOL has_been_current
;
74 LONG update_swap_interval
;
76 DWORD last_flush_time
;
80 static struct list context_list
= LIST_INIT(context_list
);
82 static CRITICAL_SECTION context_section
;
83 static CRITICAL_SECTION_DEBUG critsect_debug
=
85 0, 0, &context_section
,
86 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
87 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
89 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
94 CGLPBufferObj pbuffer
;
102 static CFMutableDictionaryRef dc_pbuffers
;
104 static CRITICAL_SECTION dc_pbuffers_section
;
105 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
107 0, 0, &dc_pbuffers_section
,
108 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
109 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
111 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
114 static struct opengl_funcs opengl_funcs
;
116 #define USE_GL_FUNC(name) #name,
117 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
121 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
123 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
124 static void (*pglFinish
)(void);
125 static void (*pglFlush
)(void);
126 static void (*pglFlushRenderAPPLE
)(void);
127 static const GLubyte
*(*pglGetString
)(GLenum name
);
128 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
129 GLenum format
, GLenum type
, void *pixels
);
130 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
136 GLint color_bits
; /* including alpha_bits */
137 int red_bits
, red_shift
;
138 int green_bits
, green_shift
;
139 int blue_bits
, blue_shift
;
140 GLint alpha_bits
, alpha_shift
;
145 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
146 observations of the behavior of Windows systems, but also subjective judgments
147 about what color formats are more "normal" than others.
149 On at least some Windows systems, integer color formats are listed before
150 floating-point formats. Within the integer formats, higher color bits were
151 usually listed before lower color bits, while for floating-point formats it
152 was the reverse. However, that leads D3D to select 64-bit integer formats in
153 preference to 32-bit formats when the latter would be sufficient. It seems
154 that a 32-bit format is much more likely to be normally used in that case.
156 Also, there are certain odd color formats supported on the Mac which seem like
157 they would be less appropriate than more common ones. For instance, the color
158 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
159 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
162 For two color formats which differ only in whether or not they have alpha bits,
163 we use the same ordering. pixel_format_comparator() gives alpha bits a
164 different weight than color formats.
166 static const struct color_mode color_modes
[] = {
167 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
168 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
169 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
170 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
171 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
172 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
173 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
174 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
175 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
176 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
177 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
178 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
179 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
180 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
181 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
182 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
183 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
184 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
185 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
186 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
187 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
188 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
189 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
190 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
194 static const struct {
197 } depth_stencil_modes
[] = {
225 GLint max_aux_buffers
;
226 GLint max_sample_buffers
;
233 } renderer_properties
;
237 unsigned int window
:1;
238 unsigned int pbuffer
:1;
239 unsigned int accelerated
:1;
240 unsigned int color_mode
:5; /* index into color_modes table */
241 unsigned int aux_buffers
:3;
242 unsigned int depth_bits
:8;
243 unsigned int stencil_bits
:8;
244 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
245 unsigned int double_buffer
:1;
246 unsigned int stereo
:1;
247 unsigned int sample_buffers
:1;
248 unsigned int samples
:5;
249 unsigned int backing_store
:1;
257 } pixel_format_or_code
;
258 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
261 static pixel_format
*pixel_formats
;
262 static int nb_formats
, nb_displayable_formats
;
265 static void *opengl_handle
;
268 static const char* debugstr_attrib(int attrib
, int value
)
270 static const struct {
274 #define ATTRIB(a) { a, #a }
275 ATTRIB(WGL_ACCELERATION_ARB
),
276 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
277 ATTRIB(WGL_ACCUM_BITS_ARB
),
278 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
279 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
280 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
281 ATTRIB(WGL_ALPHA_BITS_ARB
),
282 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
283 ATTRIB(WGL_AUX_BUFFERS_ARB
),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
286 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
287 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
288 ATTRIB(WGL_BLUE_BITS_ARB
),
289 ATTRIB(WGL_BLUE_SHIFT_ARB
),
290 ATTRIB(WGL_COLOR_BITS_ARB
),
291 ATTRIB(WGL_DEPTH_BITS_ARB
),
292 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
293 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
294 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
295 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
296 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
297 ATTRIB(WGL_GREEN_BITS_ARB
),
298 ATTRIB(WGL_GREEN_SHIFT_ARB
),
299 ATTRIB(WGL_NEED_PALETTE_ARB
),
300 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
301 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
302 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
303 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
304 ATTRIB(WGL_PIXEL_TYPE_ARB
),
305 ATTRIB(WGL_RED_BITS_ARB
),
306 ATTRIB(WGL_RED_SHIFT_ARB
),
307 ATTRIB(WGL_RENDERER_ID_WINE
),
308 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
309 ATTRIB(WGL_SAMPLES_ARB
),
310 ATTRIB(WGL_SHARE_ACCUM_ARB
),
311 ATTRIB(WGL_SHARE_DEPTH_ARB
),
312 ATTRIB(WGL_SHARE_STENCIL_ARB
),
313 ATTRIB(WGL_STENCIL_BITS_ARB
),
314 ATTRIB(WGL_STEREO_ARB
),
315 ATTRIB(WGL_SUPPORT_GDI_ARB
),
316 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
317 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
318 ATTRIB(WGL_SWAP_METHOD_ARB
),
319 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
320 ATTRIB(WGL_TRANSPARENT_ARB
),
321 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
322 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
323 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
324 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
328 const char *attrib_name
= NULL
;
329 const char *value_name
= NULL
;
331 for (i
= 0; i
< ARRAY_SIZE(attrib_names
); i
++)
333 if (attrib_names
[i
].attrib
== attrib
)
335 attrib_name
= attrib_names
[i
].name
;
341 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
345 case WGL_ACCELERATION_ARB
:
348 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
349 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
350 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
353 case WGL_PIXEL_TYPE_ARB
:
356 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
357 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
358 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
359 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
362 case WGL_SWAP_METHOD_ARB
:
365 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
366 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
367 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
373 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
375 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
379 /**********************************************************************
380 * active_displays_mask
382 static CGOpenGLDisplayMask
active_displays_mask(void)
385 CGDirectDisplayID displays
[32];
387 CGOpenGLDisplayMask mask
;
389 err
= CGGetActiveDisplayList(ARRAY_SIZE(displays
), displays
, &count
);
390 if (err
!= kCGErrorSuccess
)
392 displays
[0] = CGMainDisplayID();
397 for (i
= 0; i
< count
; i
++)
398 mask
|= CGDisplayIDToOpenGLDisplayMask(displays
[i
]);
404 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
405 CGLRendererProperty property
, GLint
*value
)
407 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
408 if (err
!= kCGLNoError
)
409 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
410 return (err
== kCGLNoError
);
414 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
418 memset(properties
, 0, sizeof(*properties
));
420 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
421 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
423 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
424 properties
->buffer_modes
= value
;
426 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
427 properties
->color_modes
= value
;
429 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
430 properties
->accum_modes
= value
;
432 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
433 properties
->depth_modes
= value
;
435 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
436 properties
->stencil_modes
= value
;
438 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
439 properties
->max_aux_buffers
= value
;
441 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
442 properties
->max_sample_buffers
= value
;
444 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
445 properties
->max_samples
= value
;
447 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
448 properties
->offscreen
= (value
!= 0);
450 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
451 properties
->accelerated
= (value
!= 0);
453 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
454 properties
->backing_store
= (value
!= 0);
456 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
457 properties
->window
= (value
!= 0);
459 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
460 properties
->online
= (value
!= 0);
464 static void dump_renderer(const renderer_properties
* renderer
)
468 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
469 TRACE("Buffer modes:\n");
470 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
471 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
472 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
473 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
475 TRACE("Color buffer modes:\n");
476 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
478 if (renderer
->color_modes
& color_modes
[i
].mode
)
480 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
481 if (color_modes
[i
].is_float
)
487 TRACE("Accumulation buffer sizes: { ");
488 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
490 if (renderer
->accum_modes
& color_modes
[i
].mode
)
491 TRACE("%d, ", color_modes
[i
].color_bits
);
495 TRACE("Depth buffer sizes: { ");
496 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
498 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
499 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
503 TRACE("Stencil buffer sizes: { ");
504 for (i
= 0; i
< ARRAY_SIZE(depth_stencil_modes
); i
++)
506 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
507 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
511 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
512 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
513 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
514 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
515 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
516 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
517 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
518 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
522 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
524 pixel_format_or_code pfc
;
527 pfc
.format
= *format
;
532 static inline pixel_format
pixel_format_for_code(UInt64 code
)
534 pixel_format_or_code pfc
;
541 static const char *debugstr_pf(const pixel_format
*pf
)
543 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",
547 color_modes
[pf
->color_mode
].color_bits
,
548 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
549 color_modes
[pf
->color_mode
].alpha_bits
,
552 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
559 code_for_pixel_format(pf
));
563 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
568 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
570 if ((modes
& color_modes
[i
].mode
) &&
571 color_modes
[i
].color_bits
>= color_size
&&
572 color_modes
[i
].alpha_bits
>= alpha_size
&&
573 !color_modes
[i
].is_float
== !color_float
)
575 if (best
< 0) /* no existing best choice */
577 else if (color_modes
[i
].color_bits
== color_size
&&
578 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
580 /* prefer it over a best which isn't exact or which has a higher bpp */
581 if (color_modes
[best
].color_bits
!= color_size
||
582 color_modes
[best
].alpha_bits
!= alpha_size
||
583 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
586 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
587 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
588 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
595 /* Couldn't find a match. Return first one that renderer supports. */
596 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
598 if (modes
& color_modes
[i
].mode
)
607 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
612 for (i
= 0; i
< ARRAY_SIZE(color_modes
); i
++)
614 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
616 /* Prefer the fewest color bits, then prefer more alpha bits, then
617 prefer more bits per pixel. */
620 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
622 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
624 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
626 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
627 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
635 /* Couldn't find a match. Return last one that renderer supports. */
636 for (i
= ARRAY_SIZE(color_modes
) - 1; i
>= 0; i
--)
638 if (modes
& color_modes
[i
].mode
)
647 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
648 CFMutableSetRef pixel_format_set
)
650 CGLPixelFormatAttribute attribs
[64] = {
651 kCGLPFAMinimumPolicy
,
652 kCGLPFAClosestPolicy
,
653 kCGLPFARendererID
, renderer
.renderer_id
,
654 kCGLPFASingleRenderer
,
656 int n
= 5, n_stack
[16], n_stack_idx
= -1;
657 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
658 new_pixel_formats
= 0;
659 pixel_format request
;
660 unsigned int double_buffer
;
661 unsigned int accelerated
= renderer
.accelerated
;
665 attribs
[n
++] = kCGLPFAAccelerated
;
666 attribs
[n
++] = kCGLPFANoRecovery
;
668 else if (!allow_software_rendering
)
670 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
674 n_stack
[++n_stack_idx
] = n
;
675 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
679 n
= n_stack
[n_stack_idx
];
681 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
682 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
686 attribs
[n
++] = kCGLPFADoubleBuffer
;
687 memset(&request
, 0, sizeof(request
));
688 request
.accelerated
= accelerated
;
689 request
.double_buffer
= double_buffer
;
691 /* Don't bother with in-between aux buffers values: either 0 or max. */
692 n_stack
[++n_stack_idx
] = n
;
693 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
695 unsigned int color_mode
;
697 n
= n_stack
[n_stack_idx
];
699 attribs
[n
++] = kCGLPFAAuxBuffers
;
701 request
.aux_buffers
= aux
;
703 n_stack
[++n_stack_idx
] = n
;
704 for (color_mode
= 0; color_mode
< ARRAY_SIZE(color_modes
); color_mode
++)
706 unsigned int depth_mode
;
708 n
= n_stack
[n_stack_idx
];
710 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
713 attribs
[n
++] = kCGLPFAColorSize
;
714 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
715 attribs
[n
++] = kCGLPFAAlphaSize
;
716 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
717 if (color_modes
[color_mode
].is_float
)
718 attribs
[n
++] = kCGLPFAColorFloat
;
719 request
.color_mode
= color_mode
;
721 n_stack
[++n_stack_idx
] = n
;
722 for (depth_mode
= 0; depth_mode
< ARRAY_SIZE(depth_stencil_modes
); depth_mode
++)
724 unsigned int stencil_mode
;
726 n
= n_stack
[n_stack_idx
];
728 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
731 attribs
[n
++] = kCGLPFADepthSize
;
732 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
733 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
735 n_stack
[++n_stack_idx
] = n
;
736 for (stencil_mode
= 0; stencil_mode
< ARRAY_SIZE(depth_stencil_modes
); stencil_mode
++)
740 n
= n_stack
[n_stack_idx
];
742 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
744 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
747 attribs
[n
++] = kCGLPFAStencilSize
;
748 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
749 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
751 /* FIXME: Could trim search space a bit here depending on GPU.
752 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
753 n_stack
[++n_stack_idx
] = n
;
754 for (stereo
= 0; stereo
<= 1; stereo
++)
758 n
= n_stack
[n_stack_idx
];
760 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
761 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
765 attribs
[n
++] = kCGLPFAStereo
;
766 request
.stereo
= stereo
;
768 /* Starts at -1 for a 0 accum size */
769 n_stack
[++n_stack_idx
] = n
;
770 for (accum_mode
= -1; accum_mode
< (int) ARRAY_SIZE(color_modes
); accum_mode
++)
772 unsigned int target_pass
;
774 n
= n_stack
[n_stack_idx
];
778 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
781 attribs
[n
++] = kCGLPFAAccumSize
;
782 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
783 request
.accum_mode
= accum_mode
+ 1;
786 request
.accum_mode
= 0;
788 /* Targets to request are:
789 accelerated: window OR window + pbuffer
790 software: window + pbuffer */
791 n_stack
[++n_stack_idx
] = n
;
792 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
794 unsigned int samples
, max_samples
;
796 n
= n_stack
[n_stack_idx
];
798 attribs
[n
++] = kCGLPFAWindow
;
801 if (!accelerated
|| target_pass
> 0)
803 attribs
[n
++] = kCGLPFAPBuffer
;
809 /* FIXME: Could trim search space a bit here depending on GPU.
810 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
811 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
812 n_stack
[++n_stack_idx
] = n
;
813 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
814 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
816 unsigned int backing_store
, min_backing_store
, max_backing_store
;
818 n
= n_stack
[n_stack_idx
];
822 attribs
[n
++] = kCGLPFASampleBuffers
;
823 attribs
[n
++] = renderer
.max_sample_buffers
;
824 attribs
[n
++] = kCGLPFASamples
;
825 attribs
[n
++] = samples
;
826 request
.sample_buffers
= renderer
.max_sample_buffers
;
827 request
.samples
= samples
;
830 request
.sample_buffers
= request
.samples
= 0;
832 if (renderer
.backing_store
&& double_buffer
)
834 /* The software renderer seems to always preserve the backing store, whether
835 we ask for it or not. So don't bother not asking for it. */
836 min_backing_store
= accelerated
? 0 : 1;
837 max_backing_store
= 1;
840 min_backing_store
= max_backing_store
= 0;
841 n_stack
[++n_stack_idx
] = n
;
842 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
844 CGLPixelFormatObj pix
;
845 GLint virtualScreens
;
848 n
= n_stack
[n_stack_idx
];
851 attribs
[n
++] = kCGLPFABackingStore
;
852 request
.backing_store
= backing_store
;
856 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
857 if (err
== kCGLNoError
&& pix
)
860 GLint value
, color_size
, alpha_size
, color_float
;
862 CFNumberRef code_object
;
865 memset(&pf
, 0, sizeof(pf
));
867 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
868 pf
.accelerated
= value
;
869 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
870 pf
.aux_buffers
= value
;
871 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
872 pf
.depth_bits
= value
;
873 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
874 pf
.double_buffer
= value
;
875 if (pf
.double_buffer
&&
876 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
877 pf
.backing_store
= value
;
878 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
880 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
881 pf
.sample_buffers
= value
;
882 if (pf
.sample_buffers
&&
883 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
885 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
886 pf
.stencil_bits
= value
;
887 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
889 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
892 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
894 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
896 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
898 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
900 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
901 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
903 CGLReleasePixelFormat(pix
);
905 pf_code
= code_for_pixel_format(&pf
);
907 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
908 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
909 dupe_pixel_formats
++;
912 CFSetAddValue(pixel_format_set
, code_object
);
913 CFArrayAppendValue(pixel_format_array
, code_object
);
916 CFRelease(code_object
);
918 if (pf_code
== code_for_pixel_format(&request
))
919 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
922 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
923 dupe
? " (duplicate)" : "");
928 failed_pixel_formats
++;
929 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
932 tried_pixel_formats
++;
964 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
965 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
966 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
967 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
971 /* The docs for WGL_ARB_pixel_format say:
972 Indices are assigned to pixel formats in the following order:
973 1. Accelerated pixel formats that are displayable
974 2. Accelerated pixel formats that are displayable and which have
976 3. Generic pixel formats
977 4. Accelerated pixel formats that are non displayable
979 static int pixel_format_category(pixel_format pf
)
981 /* non-displayable */
985 /* non-accelerated a.k.a. software a.k.a. generic */
989 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
990 if (color_modes
[pf
.color_mode
].is_float
)
993 /* accelerated, displayable, no extended attributes */
998 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
1000 CFNumberRef number1
= val1
;
1001 CFNumberRef number2
= val2
;
1002 UInt64 code1
, code2
;
1003 pixel_format pf1
, pf2
;
1004 int category1
, category2
;
1006 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
1007 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
1008 pf1
= pixel_format_for_code(code1
);
1009 pf2
= pixel_format_for_code(code2
);
1010 category1
= pixel_format_category(pf1
);
1011 category2
= pixel_format_category(pf2
);
1013 if (category1
< category2
)
1014 return kCFCompareLessThan
;
1015 if (category1
> category2
)
1016 return kCFCompareGreaterThan
;
1018 /* Within a category, sort the "best" formats toward the front since that's
1019 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1020 matches at least one Windows 7 machine's behavior.
1022 /* Accelerated before unaccelerated. */
1023 if (pf1
.accelerated
&& !pf2
.accelerated
)
1024 return kCFCompareLessThan
;
1025 if (!pf1
.accelerated
&& pf2
.accelerated
)
1026 return kCFCompareGreaterThan
;
1028 /* Explicit color mode ordering. */
1029 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1030 return kCFCompareLessThan
;
1031 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1032 return kCFCompareGreaterThan
;
1034 /* Non-pbuffer-capable before pbuffer-capable. */
1035 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1036 return kCFCompareLessThan
;
1037 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1038 return kCFCompareGreaterThan
;
1040 /* Fewer samples before more samples. */
1041 if (pf1
.samples
< pf2
.samples
)
1042 return kCFCompareLessThan
;
1043 if (pf1
.samples
> pf2
.samples
)
1044 return kCFCompareGreaterThan
;
1046 /* Monoscopic before stereoscopic. (This is a guess.) */
1047 if (!pf1
.stereo
&& pf2
.stereo
)
1048 return kCFCompareLessThan
;
1049 if (pf1
.stereo
&& !pf2
.stereo
)
1050 return kCFCompareGreaterThan
;
1052 /* Single buffered before double buffered. */
1053 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1054 return kCFCompareLessThan
;
1055 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1056 return kCFCompareGreaterThan
;
1058 /* Possibly-optimized double buffering before backing-store-preserving
1059 double buffering. */
1060 if (!pf1
.backing_store
&& pf2
.backing_store
)
1061 return kCFCompareLessThan
;
1062 if (pf1
.backing_store
&& !pf2
.backing_store
)
1063 return kCFCompareGreaterThan
;
1065 /* Bigger depth buffer before smaller depth buffer. */
1066 if (pf1
.depth_bits
> pf2
.depth_bits
)
1067 return kCFCompareLessThan
;
1068 if (pf1
.depth_bits
< pf2
.depth_bits
)
1069 return kCFCompareGreaterThan
;
1071 /* Smaller stencil buffer before bigger stencil buffer. */
1072 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1073 return kCFCompareLessThan
;
1074 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1075 return kCFCompareGreaterThan
;
1077 /* Smaller alpha bits before larger alpha bits. */
1078 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1079 return kCFCompareLessThan
;
1080 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1081 return kCFCompareGreaterThan
;
1083 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1088 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1089 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1090 return kCFCompareLessThan
;
1091 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1092 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1093 return kCFCompareGreaterThan
;
1095 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1096 return kCFCompareLessThan
;
1097 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1098 return kCFCompareGreaterThan
;
1100 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1101 return kCFCompareLessThan
;
1102 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1103 return kCFCompareGreaterThan
;
1106 return kCFCompareGreaterThan
;
1108 else if (pf2
.accum_mode
)
1109 return kCFCompareLessThan
;
1111 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1112 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1113 return kCFCompareLessThan
;
1114 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1115 return kCFCompareGreaterThan
;
1117 /* If we get here, arbitrarily sort based on code. */
1119 return kCFCompareLessThan
;
1121 return kCFCompareGreaterThan
;
1122 return kCFCompareEqualTo
;
1126 static BOOL
init_pixel_formats(void)
1129 CGLRendererInfoObj renderer_info
;
1130 GLint rendererCount
;
1132 CFMutableSetRef pixel_format_set
;
1133 CFMutableArrayRef pixel_format_array
;
1139 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1142 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1146 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1147 if (!pixel_format_set
)
1149 WARN("CFSetCreateMutable failed\n");
1150 CGLDestroyRendererInfo(renderer_info
);
1154 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1155 if (!pixel_format_array
)
1157 WARN("CFArrayCreateMutable failed\n");
1158 CFRelease(pixel_format_set
);
1159 CGLDestroyRendererInfo(renderer_info
);
1163 for (i
= 0; i
< rendererCount
; i
++)
1165 renderer_properties renderer
;
1167 get_renderer_properties(renderer_info
, i
, &renderer
);
1170 TRACE("renderer_properties %d:\n", i
);
1171 dump_renderer(&renderer
);
1174 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1177 CFRelease(pixel_format_set
);
1178 CGLDestroyRendererInfo(renderer_info
);
1180 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1183 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1186 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1187 for (i
= 0; i
< range
.length
; i
++)
1189 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1192 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1193 pixel_formats
[i
] = pixel_format_for_code(code
);
1194 if (pixel_formats
[i
].window
)
1195 nb_displayable_formats
++;
1198 nb_formats
= range
.length
;
1199 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1203 WARN("failed to allocate pixel format list\n");
1206 WARN("got no pixel formats\n");
1208 CFRelease(pixel_format_array
);
1213 static inline BOOL
is_valid_pixel_format(int format
)
1215 return format
> 0 && format
<= nb_formats
;
1219 static inline BOOL
is_displayable_pixel_format(int format
)
1221 return format
> 0 && format
<= nb_displayable_formats
;
1225 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1227 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1228 * format in case of probing the number of pixel formats.
1230 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1232 TRACE("Returning format %d\n", format
);
1233 return &pixel_formats
[format
- 1];
1239 static BOOL
init_gl_info(void)
1241 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1242 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1244 CGDirectDisplayID display
= CGMainDisplayID();
1245 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1246 CGLPixelFormatAttribute attribs
[] = {
1247 kCGLPFADisplayMask
, displayMask
,
1250 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1251 CGLPixelFormatAttribute core_attribs
[] =
1253 kCGLPFADisplayMask
, displayMask
,
1255 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1259 CGLPixelFormatObj pix
;
1260 GLint virtualScreens
;
1262 CGLContextObj context
;
1263 CGLContextObj old_context
= CGLGetCurrentContext();
1267 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1268 if (err
!= kCGLNoError
|| !pix
)
1270 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1274 err
= CGLCreateContext(pix
, NULL
, &context
);
1275 CGLReleasePixelFormat(pix
);
1276 if (err
!= kCGLNoError
|| !context
)
1278 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1282 err
= CGLSetCurrentContext(context
);
1283 if (err
!= kCGLNoError
)
1285 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1286 CGLReleaseContext(context
);
1290 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1291 length
= strlen(str
) + sizeof(legacy_extensions
);
1293 length
+= strlen(legacy_ext_swap_control
);
1294 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1295 strcpy(gl_info
.glExtensions
, str
);
1296 strcat(gl_info
.glExtensions
, legacy_extensions
);
1298 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1300 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1302 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1303 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1304 TRACE("GL version : %s\n", str
);
1305 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1307 CGLSetCurrentContext(old_context
);
1308 CGLReleaseContext(context
);
1310 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1311 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1312 if (err
!= kCGLNoError
|| !pix
)
1314 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1315 err
, CGLErrorString(err
));
1319 err
= CGLCreateContext(pix
, NULL
, &context
);
1320 CGLReleasePixelFormat(pix
);
1321 if (err
!= kCGLNoError
|| !context
)
1323 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1324 err
, CGLErrorString(err
));
1328 err
= CGLSetCurrentContext(context
);
1329 if (err
!= kCGLNoError
)
1331 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1332 err
, CGLErrorString(err
));
1333 CGLReleaseContext(context
);
1337 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1338 TRACE("Core context GL version: %s\n", str
);
1339 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1340 CGLSetCurrentContext(old_context
);
1341 CGLReleaseContext(context
);
1348 static int get_dc_pixel_format(HDC hdc
)
1353 if ((hwnd
= WindowFromDC(hdc
)))
1355 struct macdrv_win_data
*data
;
1357 if (!(data
= get_win_data(hwnd
)))
1359 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1363 format
= data
->pixel_format
;
1364 release_win_data(data
);
1368 struct wgl_pbuffer
*pbuffer
;
1370 EnterCriticalSection(&dc_pbuffers_section
);
1371 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1373 format
= pbuffer
->format
;
1376 WARN("no window or pbuffer for DC %p\n", hdc
);
1379 LeaveCriticalSection(&dc_pbuffers_section
);
1386 /**********************************************************************
1389 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1391 const pixel_format
*pf
;
1392 CGLPixelFormatAttribute attribs
[64];
1394 CGLPixelFormatObj pix
;
1395 GLint virtualScreens
;
1397 BOOL core
= major
>= 3;
1399 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1402 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1407 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1410 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1411 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1415 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1416 attribs
[n
++] = kCGLPFAClosestPolicy
;
1418 if (context
->renderer_id
)
1420 attribs
[n
++] = kCGLPFARendererID
;
1421 attribs
[n
++] = context
->renderer_id
;
1422 attribs
[n
++] = kCGLPFASingleRenderer
;
1423 attribs
[n
++] = kCGLPFANoRecovery
;
1426 if (pf
->accelerated
)
1428 attribs
[n
++] = kCGLPFAAccelerated
;
1429 attribs
[n
++] = kCGLPFANoRecovery
;
1433 attribs
[n
++] = kCGLPFARendererID
;
1434 attribs
[n
++] = kCGLRendererGenericFloatID
;
1437 if (pf
->double_buffer
)
1438 attribs
[n
++] = kCGLPFADoubleBuffer
;
1442 attribs
[n
++] = kCGLPFAAuxBuffers
;
1443 attribs
[n
++] = pf
->aux_buffers
;
1446 attribs
[n
++] = kCGLPFAColorSize
;
1447 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1448 attribs
[n
++] = kCGLPFAAlphaSize
;
1449 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1450 if (color_modes
[pf
->color_mode
].is_float
)
1451 attribs
[n
++] = kCGLPFAColorFloat
;
1453 attribs
[n
++] = kCGLPFADepthSize
;
1454 attribs
[n
++] = pf
->depth_bits
;
1456 attribs
[n
++] = kCGLPFAStencilSize
;
1457 attribs
[n
++] = pf
->stencil_bits
;
1460 attribs
[n
++] = kCGLPFAStereo
;
1462 if (pf
->accum_mode
&& !core
)
1464 attribs
[n
++] = kCGLPFAAccumSize
;
1465 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1468 if (pf
->pbuffer
&& !core
)
1469 attribs
[n
++] = kCGLPFAPBuffer
;
1471 if (pf
->sample_buffers
&& pf
->samples
)
1473 attribs
[n
++] = kCGLPFASampleBuffers
;
1474 attribs
[n
++] = pf
->sample_buffers
;
1475 attribs
[n
++] = kCGLPFASamples
;
1476 attribs
[n
++] = pf
->samples
;
1479 if (pf
->backing_store
)
1480 attribs
[n
++] = kCGLPFABackingStore
;
1482 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1485 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1486 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1488 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1490 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1492 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1499 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1500 if (err
!= kCGLNoError
|| !pix
)
1502 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1503 SetLastError(ERROR_INVALID_OPERATION
);
1507 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1508 CGLReleasePixelFormat(pix
);
1509 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1511 context
->cglcontext
= NULL
;
1512 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1513 SetLastError(ERROR_INVALID_OPERATION
);
1517 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1520 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1521 if (err
!= kCGLNoError
)
1522 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1524 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1527 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1528 if (err
!= kCGLNoError
)
1529 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1532 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1533 CGLReleaseContext(context
->cglcontext
);
1534 if (!context
->context
)
1536 WARN("macdrv_create_opengl_context() failed\n");
1537 SetLastError(ERROR_INVALID_OPERATION
);
1540 context
->major
= major
;
1542 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1544 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1550 /**********************************************************************
1553 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1555 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1557 struct macdrv_win_data
*data
;
1558 const pixel_format
*pf
;
1559 HWND hwnd
= WindowFromDC(hdc
);
1562 TRACE("hdc %p format %d\n", hdc
, fmt
);
1564 if (!hwnd
|| hwnd
== GetDesktopWindow())
1566 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1570 if (!(data
= get_win_data(hwnd
)))
1572 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1576 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1578 ret
= (data
->pixel_format
== fmt
);
1582 /* Check if fmt is in our list of supported formats to see if it is supported. */
1583 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1586 ERR("Invalid pixel format: %d\n", fmt
);
1592 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1596 data
->pixel_format
= fmt
;
1598 TRACE("pixel format:\n");
1599 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1600 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1601 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1602 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1603 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1604 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1605 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1606 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1607 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1608 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1609 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1610 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1611 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1612 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1616 release_win_data(data
);
1617 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) __wine_set_pixel_format(hwnd
, fmt
);
1622 /**********************************************************************
1623 * mark_contexts_for_moved_view
1625 static void mark_contexts_for_moved_view(macdrv_view view
)
1627 struct wgl_context
*context
;
1629 EnterCriticalSection(&context_section
);
1630 LIST_FOR_EACH_ENTRY(context
, &context_list
, struct wgl_context
, entry
)
1632 if (context
->draw_view
== view
)
1633 InterlockedExchange(&context
->view_moved
, TRUE
);
1635 LeaveCriticalSection(&context_section
);
1639 /**********************************************************************
1642 static BOOL
sync_context_rect(struct wgl_context
*context
)
1645 if (InterlockedCompareExchange(&context
->view_moved
, FALSE
, TRUE
))
1647 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1649 if (data
&& data
->client_cocoa_view
== context
->draw_view
)
1651 RECT rect
= data
->client_rect
;
1652 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1653 if (!EqualRect(&context
->draw_rect
, &rect
))
1655 context
->draw_rect
= rect
;
1659 release_win_data(data
);
1665 /**********************************************************************
1666 * make_context_current
1668 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1672 struct wgl_pbuffer
*pbuffer
;
1676 view
= context
->read_view
;
1677 view_rect
= context
->read_rect
;
1678 pbuffer
= context
->read_pbuffer
;
1682 sync_context_rect(context
);
1684 view
= context
->draw_view
;
1685 view_rect
= context
->draw_rect
;
1686 pbuffer
= context
->draw_pbuffer
;
1689 if (view
|| !pbuffer
)
1690 macdrv_make_context_current(context
->context
, view
, cgrect_from_rect(view_rect
));
1695 if (CGLIsEnabled(context
->cglcontext
, kCGLCESurfaceBackingSize
, &enabled
) == kCGLNoError
&& enabled
)
1696 CGLDisable(context
->cglcontext
, kCGLCESurfaceBackingSize
);
1697 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1699 CGLSetCurrentContext(context
->cglcontext
);
1704 /**********************************************************************
1707 static void sync_context(struct wgl_context
*context
)
1709 if (sync_context_rect(context
))
1710 make_context_current(context
, FALSE
);
1714 /**********************************************************************
1717 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1721 /* In theory, for single-buffered contexts, there's no such thing as a swap
1722 so the swap interval shouldn't matter. But OS X will synchronize flushes
1723 of single-buffered contexts if the interval is set to non-zero. */
1724 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1727 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1728 if (err
!= kCGLNoError
)
1729 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1731 return err
== kCGLNoError
;
1735 /**********************************************************************
1736 * sync_swap_interval
1738 static void sync_swap_interval(struct wgl_context
*context
)
1740 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1746 else if (context
->draw_hwnd
)
1748 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1751 interval
= data
->swap_interval
;
1752 release_win_data(data
);
1754 else /* window was destroyed? */
1760 set_swap_interval(context
, interval
);
1765 /**********************************************************************
1766 * get_iokit_display_property
1768 static BOOL
get_iokit_display_property(CGLRendererInfoObj renderer_info
, GLint renderer
, CFStringRef property
, GLuint
* value
)
1774 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, &accelerated
) || !accelerated
)
1776 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1780 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPDisplayMask
, &display_mask
))
1782 WARN("failed to get kCGLRPDisplayMask\n");
1786 for (i
= 0; i
< sizeof(GLint
) * 8; i
++)
1788 GLint this_display_mask
= (GLint
)(1U << i
);
1789 if (this_display_mask
& display_mask
)
1791 CGDirectDisplayID display_id
= CGOpenGLDisplayMaskToDisplayID(this_display_mask
);
1792 io_service_t service
;
1794 uint32_t prop_value
;
1798 service
= CGDisplayIOServicePort(display_id
);
1801 WARN("CGDisplayIOServicePort(%u) failed\n", display_id
);
1805 data
= IORegistryEntrySearchCFProperty(service
, kIOServicePlane
, property
, NULL
,
1806 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1809 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property
), display_id
);
1812 if (CFGetTypeID(data
) != CFDataGetTypeID())
1814 WARN("property %s is not a data object: %s\n", debugstr_cf(property
), debugstr_cf(data
));
1818 if (CFDataGetLength(data
) != sizeof(prop_value
))
1820 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property
), display_id
,
1821 (unsigned long long)CFDataGetLength(data
));
1826 CFDataGetBytes(data
, CFRangeMake(0, sizeof(prop_value
)), (UInt8
*)&prop_value
);
1828 *value
= prop_value
;
1837 /**********************************************************************
1838 * create_pixel_format_for_renderer
1840 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1841 * responsible for releasing the pixel format object.
1843 static CGLPixelFormatObj
create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info
, GLint renderer
, BOOL core
)
1846 CGLPixelFormatAttribute attrs
[] = {
1847 kCGLPFARendererID
, 0,
1848 kCGLPFASingleRenderer
,
1849 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1853 CGLPixelFormatObj pixel_format
;
1854 GLint virtual_screens
;
1858 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1859 attrs
[3] = kCGLPFAOpenGLProfile
;
1860 attrs
[4] = (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
;
1866 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
1869 attrs
[1] = renderer_id
;
1870 err
= CGLChoosePixelFormat(attrs
, &pixel_format
, &virtual_screens
);
1871 if (err
!= kCGLNoError
)
1872 pixel_format
= NULL
;
1873 return pixel_format
;
1877 /**********************************************************************
1878 * map_renderer_index
1880 * We can't create pixel formats for all renderers listed. For example,
1881 * in a dual-GPU system, the integrated GPU is typically unavailable
1882 * when the discrete GPU is active.
1884 * This function conceptually creates a list of "good" renderers from the
1885 * list of all renderers. It treats the input "renderer" parameter as an
1886 * index into that list of good renderers and returns the corresponding
1887 * index into the list of all renderers.
1889 static GLint
map_renderer_index(CGLRendererInfoObj renderer_info
, GLint renderer_count
, GLint renderer
)
1891 GLint good_count
, i
;
1894 for (i
= 0; i
< renderer_count
; i
++)
1896 CGLPixelFormatObj pix
= create_pixel_format_for_renderer(renderer_info
, i
, FALSE
);
1899 CGLReleasePixelFormat(pix
);
1901 if (good_count
> renderer
)
1905 TRACE("skipping bad renderer %d\n", i
);
1908 TRACE("mapped requested renderer %d to index %d\n", renderer
, i
);
1913 /**********************************************************************
1916 static const char* get_gl_string(CGLPixelFormatObj pixel_format
, GLenum name
)
1918 const char* ret
= NULL
;
1919 CGLContextObj context
, old_context
;
1922 err
= CGLCreateContext(pixel_format
, NULL
, &context
);
1923 if (err
== kCGLNoError
&& context
)
1925 old_context
= CGLGetCurrentContext();
1926 err
= CGLSetCurrentContext(context
);
1927 if (err
== kCGLNoError
)
1929 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(name
);
1930 CGLSetCurrentContext(old_context
);
1933 WARN("CGLSetCurrentContext failed: %d %s\n", err
, CGLErrorString(err
));
1934 CGLReleaseContext(context
);
1937 WARN("CGLCreateContext failed: %d %s\n", err
, CGLErrorString(err
));
1943 /**********************************************************************
1944 * get_fallback_renderer_version
1946 static void get_fallback_renderer_version(GLuint
*value
)
1948 BOOL got_it
= FALSE
;
1949 CFURLRef url
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1950 kCFURLPOSIXPathStyle
, TRUE
);
1953 CFBundleRef bundle
= CFBundleCreate(NULL
, url
);
1957 CFStringRef version
= CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleVersionKey
);
1958 if (version
&& CFGetTypeID(version
) == CFStringGetTypeID())
1960 size_t len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(version
), kCFStringEncodingUTF8
);
1961 char* buf
= HeapAlloc(GetProcessHeap(), 0, len
);
1962 if (buf
&& CFStringGetCString(version
, buf
, len
, kCFStringEncodingUTF8
))
1964 unsigned int major
, minor
, bugfix
;
1965 int count
= sscanf(buf
, "%u.%u.%u", &major
, &minor
, &bugfix
);
1977 HeapFree(GetProcessHeap(), 0, buf
);
1985 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1986 earliest version that the Mac driver supports. */
1994 /**********************************************************************
1995 * parse_renderer_version
1997 * Get the renderer version from the OpenGL version string. Assumes
1998 * the string is of the form
1999 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2000 * where major, minor, and bugfix are what we're interested in. This
2001 * form for the vendor specific information is not generally applicable,
2002 * but seems reliable on OS X.
2004 static BOOL
parse_renderer_version(const char* version
, GLuint
*value
)
2006 const char* p
= strchr(version
, ' ');
2008 unsigned int major
, minor
, bugfix
;
2010 if (p
) p
= strchr(p
+ 1, '-');
2011 if (!p
) return FALSE
;
2013 count
= sscanf(p
+ 1, "%u.%u.%u", &major
, &minor
, &bugfix
);
2028 /**********************************************************************
2029 * query_renderer_integer
2031 static BOOL
query_renderer_integer(CGLRendererInfoObj renderer_info
, GLint renderer
, GLenum attribute
, GLuint
*value
)
2039 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
2041 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer
, renderer_id
, attribute
, value
);
2046 case WGL_RENDERER_ACCELERATED_WINE
:
2047 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, (GLint
*)value
))
2051 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value
);
2054 case WGL_RENDERER_DEVICE_ID_WINE
:
2055 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("device-id"), value
);
2058 *value
= 0xffffffff;
2061 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value
);
2064 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE
:
2065 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
:
2067 BOOL core
= (attribute
== WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
);
2068 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, core
);
2072 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2074 CGLReleasePixelFormat(pixel_format
);
2077 unsigned int major
, minor
;
2079 if (sscanf(version
, "%u.%u", &major
, &minor
) == 2)
2090 value
[0] = value
[1] = 0;
2093 TRACE("%s -> %u.%u\n", core
? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2094 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value
[0], value
[1]);
2098 case WGL_RENDERER_PREFERRED_PROFILE_WINE
:
2100 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2104 CGLReleasePixelFormat(pixel_format
);
2105 *value
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
2106 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2110 *value
= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
2111 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2117 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE
:
2118 /* FIXME: no API to query this */
2121 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value
);
2124 case WGL_RENDERER_VENDOR_ID_WINE
:
2125 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("vendor-id"), value
);
2128 *value
= 0xffffffff;
2131 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value
);
2134 case WGL_RENDERER_VERSION_WINE
:
2136 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2139 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
2142 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2144 CGLReleasePixelFormat(pixel_format
);
2146 ret
= parse_renderer_version(version
, value
);
2151 get_fallback_renderer_version(value
);
2154 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
2158 case WGL_RENDERER_VIDEO_MEMORY_WINE
:
2159 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2160 err
= CGLDescribeRenderer(renderer_info
, renderer
, kCGLRPVideoMemoryMegabytes
, (GLint
*)value
);
2161 if (err
!= kCGLNoError
&& err
!= kCGLBadProperty
)
2162 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err
, CGLErrorString(err
));
2163 if (err
!= kCGLNoError
)
2166 if (get_renderer_property(renderer_info
, renderer
, kCGLRPVideoMemory
, (GLint
*)value
))
2167 *value
/= 1024 * 1024;
2172 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value
);
2176 FIXME("unrecognized attribute 0x%04x\n", attribute
);
2184 /**********************************************************************
2185 * macdrv_glCopyColorTable
2187 * Hook into glCopyColorTable as part of the implementation of
2188 * wglMakeContextCurrentARB. If the context has a separate readable,
2189 * temporarily make that current, do glCopyColorTable, and then set it
2190 * back to the drawable. This is modeled after what Mesa GLX's Apple
2191 * implementation does.
2193 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
2196 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2198 if (context
->read_view
|| context
->read_pbuffer
)
2199 make_context_current(context
, TRUE
);
2201 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
2203 if (context
->read_view
|| context
->read_pbuffer
)
2204 make_context_current(context
, FALSE
);
2208 /**********************************************************************
2209 * macdrv_glCopyPixels
2211 * Hook into glCopyPixels as part of the implementation of
2212 * wglMakeContextCurrentARB. If the context has a separate readable,
2213 * temporarily make that current, do glCopyPixels, and then set it back
2214 * to the drawable. This is modeled after what Mesa GLX's Apple
2215 * implementation does.
2217 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
2219 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2221 if (context
->read_view
|| context
->read_pbuffer
)
2222 make_context_current(context
, TRUE
);
2224 pglCopyPixels(x
, y
, width
, height
, type
);
2226 if (context
->read_view
|| context
->read_pbuffer
)
2227 make_context_current(context
, FALSE
);
2231 /**********************************************************************
2234 static void macdrv_glFinish(void)
2236 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2238 sync_swap_interval(context
);
2239 sync_context(context
);
2244 /**********************************************************************
2247 static void macdrv_glFlush(void)
2249 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2251 sync_swap_interval(context
);
2252 sync_context(context
);
2254 if (skip_single_buffer_flushes
)
2256 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
2257 DWORD now
= GetTickCount();
2259 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
2260 context
->last_flush_time
, now
);
2261 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
2263 TRACE("calling glFlushRenderAPPLE()\n");
2264 pglFlushRenderAPPLE();
2269 TRACE("calling glFlush()\n");
2270 context
->last_flush_time
= now
;
2278 /**********************************************************************
2279 * macdrv_glGetString
2281 * Hook into glGetString in order to return some legacy WGL extensions
2282 * that couldn't be advertised via the standard
2283 * WGL_ARB_extensions_string mechanism. Some programs, especially
2284 * older ones, expect to find certain older extensions, such as
2285 * WGL_EXT_extensions_string itself, in the standard GL extensions
2286 * string, and won't query any other WGL extensions unless they find
2287 * that particular extension there.
2289 static const GLubyte
*macdrv_glGetString(GLenum name
)
2291 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
2292 return (const GLubyte
*)gl_info
.glExtensions
;
2294 return pglGetString(name
);
2298 /**********************************************************************
2299 * macdrv_glReadPixels
2301 * Hook into glReadPixels as part of the implementation of
2302 * wglMakeContextCurrentARB. If the context has a separate readable,
2303 * temporarily make that current, do glReadPixels, and then set it back
2304 * to the drawable. This is modeled after what Mesa GLX's Apple
2305 * implementation does.
2307 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2308 GLenum format
, GLenum type
, void *pixels
)
2310 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2312 if (context
->read_view
|| context
->read_pbuffer
)
2313 make_context_current(context
, TRUE
);
2315 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2317 if (context
->read_view
|| context
->read_pbuffer
)
2318 make_context_current(context
, FALSE
);
2322 /**********************************************************************
2325 * Hook into glViewport as an opportunity to update the OpenGL context
2326 * if necessary. This is modeled after what Mesa GLX's Apple
2327 * implementation does.
2329 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2331 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2333 sync_context(context
);
2334 macdrv_update_opengl_context(context
->context
);
2335 pglViewport(x
, y
, width
, height
);
2339 /***********************************************************************
2340 * macdrv_wglBindTexImageARB
2342 * WGL_ARB_render_texture: wglBindTexImageARB
2344 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2346 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2350 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
2352 if (pbuffer
->no_texture
)
2354 SetLastError(ERROR_INVALID_OPERATION
);
2358 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
2359 opengl_funcs
.gl
.p_glFlush();
2363 case WGL_FRONT_LEFT_ARB
:
2364 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2365 source
= GL_FRONT_LEFT
;
2369 case WGL_FRONT_RIGHT_ARB
:
2370 source
= GL_FRONT_RIGHT
;
2372 case WGL_BACK_LEFT_ARB
:
2373 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2374 source
= GL_BACK_LEFT
;
2378 case WGL_BACK_RIGHT_ARB
:
2379 source
= GL_BACK_RIGHT
;
2381 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
2382 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
2383 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
2384 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
2392 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
2393 SetLastError(ERROR_INVALID_DATA
);
2397 WARN("unknown source buffer 0x%x\n", iBuffer
);
2398 SetLastError(ERROR_INVALID_DATA
);
2402 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
2403 if (err
!= kCGLNoError
)
2405 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2406 SetLastError(ERROR_INVALID_OPERATION
);
2414 /***********************************************************************
2415 * macdrv_wglChoosePixelFormatARB
2417 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2419 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2420 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2421 int *piFormats
, UINT
*nNumFormats
)
2423 pixel_format pf
, valid
;
2425 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2426 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2431 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2432 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2434 FIXME("unused pfAttribFList\n");
2436 memset(&pf
, 0, sizeof(pf
));
2437 memset(&valid
, 0, sizeof(valid
));
2438 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2439 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2443 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2446 int value
= iptr
[1];
2448 TRACE("%s\n", debugstr_attrib(attr
, value
));
2452 case WGL_DRAW_TO_WINDOW_ARB
:
2453 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2454 pf
.window
= (value
!= 0);
2458 case WGL_DRAW_TO_BITMAP_ARB
:
2461 case WGL_ACCELERATION_ARB
:
2462 if (value
== WGL_FULL_ACCELERATION_ARB
)
2464 else if (value
== WGL_NO_ACCELERATION_ARB
)
2468 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2469 pf
.accelerated
= value
;
2470 valid
.accelerated
= 1;
2473 case WGL_NEED_PALETTE_ARB
:
2474 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2475 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2476 if (value
) goto cant_match
;
2479 case WGL_SWAP_METHOD_ARB
:
2480 if (value
== WGL_SWAP_COPY_ARB
)
2482 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2486 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2487 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2488 pf
.backing_store
= value
;
2489 valid
.backing_store
= 1;
2492 case WGL_NUMBER_OVERLAYS_ARB
:
2493 case WGL_NUMBER_UNDERLAYS_ARB
:
2494 if (value
) goto cant_match
;
2497 case WGL_SHARE_DEPTH_ARB
:
2498 case WGL_SHARE_STENCIL_ARB
:
2499 case WGL_SHARE_ACCUM_ARB
:
2503 case WGL_SUPPORT_GDI_ARB
:
2504 if (value
) goto cant_match
;
2507 case WGL_SUPPORT_OPENGL_ARB
:
2508 if (!value
) goto cant_match
;
2511 case WGL_DOUBLE_BUFFER_ARB
:
2512 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2513 pf
.double_buffer
= (value
!= 0);
2514 valid
.double_buffer
= 1;
2515 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2518 case WGL_STEREO_ARB
:
2519 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2520 pf
.stereo
= (value
!= 0);
2524 case WGL_PIXEL_TYPE_ARB
:
2525 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2527 else if (value
== WGL_TYPE_RGBA_ARB
)
2531 /* Mac contexts don't support rendering to unsigned floating
2532 point formats, even if GL_EXT_packed_float is supported.
2533 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2536 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2537 if (srgb
&& value
) goto cant_match
;
2538 float_color
= value
;
2541 case WGL_COLOR_BITS_ARB
:
2542 if (color_bits
< value
) color_bits
= value
;
2545 case WGL_RED_BITS_ARB
:
2546 if (srgb
&& value
> 8) goto cant_match
;
2547 if (red_bits
< value
) red_bits
= value
;
2550 case WGL_GREEN_BITS_ARB
:
2551 if (srgb
&& value
> 8) goto cant_match
;
2552 if (green_bits
< value
) green_bits
= value
;
2555 case WGL_BLUE_BITS_ARB
:
2556 if (srgb
&& value
> 8) goto cant_match
;
2557 if (blue_bits
< value
) blue_bits
= value
;
2560 case WGL_ALPHA_BITS_ARB
:
2561 if (alpha_bits
< value
) alpha_bits
= value
;
2564 case WGL_ACCUM_BITS_ARB
:
2565 if (accum_bits
< value
) accum_bits
= value
;
2568 case WGL_ACCUM_RED_BITS_ARB
:
2569 if (accum_red_bits
< value
) accum_red_bits
= value
;
2572 case WGL_ACCUM_GREEN_BITS_ARB
:
2573 if (accum_green_bits
< value
) accum_green_bits
= value
;
2576 case WGL_ACCUM_BLUE_BITS_ARB
:
2577 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2580 case WGL_ACCUM_ALPHA_BITS_ARB
:
2581 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2584 case WGL_DEPTH_BITS_ARB
:
2585 if (value
> 255) goto cant_match
;
2586 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2589 case WGL_STENCIL_BITS_ARB
:
2590 if (value
> 255) goto cant_match
;
2591 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2594 case WGL_AUX_BUFFERS_ARB
:
2595 if (value
> 7) goto cant_match
;
2596 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2599 case WGL_SAMPLE_BUFFERS_ARB
:
2600 if (value
> 1) goto cant_match
;
2601 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2604 case WGL_SAMPLES_ARB
:
2605 if (value
> 31) goto cant_match
;
2606 if (pf
.samples
< value
) pf
.samples
= value
;
2609 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2610 /* sRGB is only supported for 8-bit integer color components */
2611 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2616 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2617 case WGL_RED_SHIFT_ARB
:
2618 case WGL_GREEN_SHIFT_ARB
:
2619 case WGL_BLUE_SHIFT_ARB
:
2620 case WGL_ALPHA_SHIFT_ARB
:
2621 case WGL_TRANSPARENT_ARB
:
2622 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2623 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2624 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2625 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2626 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2630 case WGL_DRAW_TO_PBUFFER_ARB
:
2631 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2632 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2633 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2634 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2635 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2636 pf
.pbuffer
= (value
!= 0);
2638 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2644 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2649 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",
2650 valid
.window
? (pf
.window
? "1" : "0") : "?",
2651 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2652 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2654 float_color
== -1 ? "?" : float_color
? "f" : "",
2668 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2669 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2670 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2674 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2676 const struct color_mode
*mode
;
2678 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2679 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2680 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2681 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2682 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2683 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2685 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2686 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2687 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2688 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2689 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2691 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2692 /* If the mode doesn't have alpha, check requested color bits against
2693 bits per pixel instead of the mode's color bits. On Windows, color
2694 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2695 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2696 expects that to match such a pixel format, we need to accommodate that. */
2697 if (mode
->alpha_bits
)
2699 if (mode
->color_bits
< color_bits
)
2704 if (mode
->bits_per_pixel
< color_bits
)
2707 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2708 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2710 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2711 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2714 if (pixel_formats
[i
].accum_mode
)
2716 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2717 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2718 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2719 mode
->alpha_bits
< accum_alpha_bits
)
2722 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2725 piFormats
[found
++] = i
+ 1;
2726 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2730 *nNumFormats
= found
;
2736 /***********************************************************************
2737 * macdrv_wglCreateContextAttribsARB
2739 * WGL_ARB_create_context: wglCreateContextAttribsARB
2741 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2742 struct wgl_context
*share_context
,
2743 const int *attrib_list
)
2746 struct wgl_context
*context
;
2748 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2750 GLint renderer_id
= 0;
2752 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2754 format
= get_dc_pixel_format(hdc
);
2756 if (!is_valid_pixel_format(format
))
2758 ERR("Invalid pixel format %d, expect problems!\n", format
);
2759 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2763 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2766 int value
= iptr
[1];
2768 TRACE("%s\n", debugstr_attrib(attr
, value
));
2772 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2776 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2780 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2781 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2784 case WGL_CONTEXT_FLAGS_ARB
:
2786 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2787 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2788 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2791 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2792 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2793 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2795 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2796 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2802 case WGL_RENDERER_ID_WINE
:
2805 CGLRendererInfoObj renderer_info
;
2806 GLint renderer_count
, temp
;
2808 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
2809 if (err
!= kCGLNoError
)
2811 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
2812 SetLastError(ERROR_GEN_FAILURE
);
2816 value
= map_renderer_index(renderer_info
, renderer_count
, value
);
2818 if (value
>= renderer_count
)
2820 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value
, renderer_count
);
2821 CGLDestroyRendererInfo(renderer_info
);
2822 SetLastError(ERROR_INVALID_PARAMETER
);
2826 if (!get_renderer_property(renderer_info
, value
, kCGLRPRendererID
, &temp
))
2828 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value
);
2829 CGLDestroyRendererInfo(renderer_info
);
2830 SetLastError(ERROR_GEN_FAILURE
);
2834 CGLDestroyRendererInfo(renderer_info
);
2836 if (renderer_id
&& temp
!= renderer_id
)
2838 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id
, temp
);
2839 SetLastError(ERROR_INVALID_PARAMETER
);
2847 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2848 SetLastError(ERROR_INVALID_PARAMETER
);
2853 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2854 (major
== 4 && (minor
== 0 || minor
== 1)))
2856 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2858 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2859 SetLastError(ERROR_INVALID_VERSION_ARB
);
2862 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2864 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2865 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2868 if (major
> gl_info
.max_major
||
2869 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2871 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2873 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2878 else if (major
>= 3)
2880 WARN("Profile version %u.%u not supported\n", major
, minor
);
2881 SetLastError(ERROR_INVALID_VERSION_ARB
);
2884 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2885 (major
== 2 && (minor
< 0 || minor
> 1)))
2887 WARN("Invalid GL version requested\n");
2888 SetLastError(ERROR_INVALID_VERSION_ARB
);
2891 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2893 WARN("Forward compatible context requested for GL version < 3\n");
2894 SetLastError(ERROR_INVALID_VERSION_ARB
);
2898 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
2900 context
->format
= format
;
2901 context
->renderer_id
= renderer_id
;
2902 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2904 HeapFree(GetProcessHeap(), 0, context
);
2908 EnterCriticalSection(&context_section
);
2909 list_add_tail(&context_list
, &context
->entry
);
2910 LeaveCriticalSection(&context_section
);
2916 /**********************************************************************
2917 * macdrv_wglCreatePbufferARB
2919 * WGL_ARB_pbuffer: wglCreatePbufferARB
2921 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2922 const int *piAttribList
)
2924 struct wgl_pbuffer
* pbuffer
;
2926 GLenum internalFormat
= 0;
2929 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2930 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2932 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2934 WARN("invalid pixel format %d\n", iPixelFormat
);
2935 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2939 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2940 pbuffer
->format
= iPixelFormat
;
2942 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2944 int attr
= piAttribList
[0];
2945 int value
= piAttribList
[1];
2949 case WGL_PBUFFER_LARGEST_ARB
:
2950 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2953 case WGL_TEXTURE_FORMAT_ARB
:
2956 case WGL_TEXTURE_RGBA_ARB
:
2957 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2958 internalFormat
= GL_RGBA
;
2960 case WGL_TEXTURE_RGB_ARB
:
2961 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2962 internalFormat
= GL_RGB
;
2964 case WGL_NO_TEXTURE_ARB
:
2965 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2969 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2970 SetLastError(ERROR_INVALID_DATA
);
2975 case WGL_TEXTURE_TARGET_ARB
:
2979 case WGL_NO_TEXTURE_ARB
:
2980 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2983 case WGL_TEXTURE_CUBE_MAP_ARB
:
2984 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2985 target
= GL_TEXTURE_CUBE_MAP
;
2986 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2988 case WGL_TEXTURE_1D_ARB
:
2989 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2990 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2992 case WGL_TEXTURE_2D_ARB
:
2993 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2994 target
= GL_TEXTURE_2D
;
2996 case WGL_TEXTURE_RECTANGLE_NV
:
2997 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2998 target
= GL_TEXTURE_RECTANGLE
;
3001 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
3002 SetLastError(ERROR_INVALID_DATA
);
3007 case WGL_MIPMAP_TEXTURE_ARB
:
3008 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
3009 pbuffer
->max_level
= 0;
3012 int size
= min(iWidth
, iHeight
) / 2;
3015 pbuffer
->max_level
++;
3022 WARN("unknown attribute 0x%x\n", attr
);
3023 SetLastError(ERROR_INVALID_DATA
);
3028 if (!target
|| !internalFormat
)
3030 pbuffer
->no_texture
= TRUE
;
3031 /* no actual way to turn off ability to texture; use most permissive target */
3032 target
= GL_TEXTURE_RECTANGLE
;
3033 internalFormat
= GL_RGB
;
3036 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
3037 if (err
!= kCGLNoError
)
3039 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
3040 pbuffer
->pbuffer
= NULL
;
3041 if (err
== kCGLBadAlloc
)
3042 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
3044 SetLastError(ERROR_INVALID_DATA
);
3048 if (!pbuffer
->pbuffer
)
3050 HeapFree(GetProcessHeap(), 0, pbuffer
);
3054 TRACE(" -> %p\n", pbuffer
);
3059 /**********************************************************************
3060 * macdrv_wglDestroyPbufferARB
3062 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3064 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
3066 TRACE("pbuffer %p\n", pbuffer
);
3067 if (pbuffer
&& pbuffer
->pbuffer
)
3068 CGLReleasePBuffer(pbuffer
->pbuffer
);
3069 HeapFree(GetProcessHeap(), 0, pbuffer
);
3074 /**********************************************************************
3075 * macdrv_wglGetExtensionsStringARB
3077 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3079 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
3081 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3082 this can be specific to the CGL renderer like we're supposed to do. */
3083 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3084 return gl_info
.wglExtensions
;
3088 /**********************************************************************
3089 * macdrv_wglGetExtensionsStringEXT
3091 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3093 static const char *macdrv_wglGetExtensionsStringEXT(void)
3095 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3096 return gl_info
.wglExtensions
;
3100 /**********************************************************************
3101 * macdrv_wglGetPbufferDCARB
3103 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3105 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
3108 struct wgl_pbuffer
*prev
;
3110 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
3113 EnterCriticalSection(&dc_pbuffers_section
);
3114 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3117 CGLReleasePBuffer(prev
->pbuffer
);
3118 HeapFree(GetProcessHeap(), 0, prev
);
3120 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
3121 LeaveCriticalSection(&dc_pbuffers_section
);
3123 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
3128 /**********************************************************************
3129 * macdrv_wglGetPixelFormatAttribivARB
3131 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3133 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3134 UINT nAttributes
, const int *piAttributes
, int *piValues
)
3136 const pixel_format
*pf
;
3139 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3140 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
3142 if (!nAttributes
) return GL_TRUE
;
3144 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
3146 piValues
[0] = nb_formats
;
3147 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
3151 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
3154 WARN("invalid pixel format %d\n", iPixelFormat
);
3155 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3159 for (i
= 0; i
< nAttributes
; ++i
)
3161 switch (piAttributes
[i
])
3163 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
3164 piValues
[i
] = nb_formats
;
3167 case WGL_DRAW_TO_WINDOW_ARB
:
3168 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
3171 case WGL_DRAW_TO_BITMAP_ARB
:
3172 piValues
[i
] = GL_FALSE
;
3175 case WGL_ACCELERATION_ARB
:
3176 if (iLayerPlane
) goto invalid_layer
;
3177 if (pf
->accelerated
)
3178 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
3180 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
3183 case WGL_NEED_PALETTE_ARB
:
3184 case WGL_NEED_SYSTEM_PALETTE_ARB
:
3185 case WGL_SWAP_LAYER_BUFFERS_ARB
:
3186 piValues
[i
] = GL_FALSE
;
3189 case WGL_SWAP_METHOD_ARB
:
3190 if (pf
->double_buffer
&& pf
->backing_store
)
3191 piValues
[i
] = WGL_SWAP_COPY_ARB
;
3193 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
3196 case WGL_NUMBER_OVERLAYS_ARB
:
3197 case WGL_NUMBER_UNDERLAYS_ARB
:
3201 case WGL_TRANSPARENT_ARB
:
3202 if (iLayerPlane
) goto invalid_layer
;
3203 piValues
[i
] = GL_FALSE
;
3206 case WGL_TRANSPARENT_RED_VALUE_ARB
:
3207 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
3208 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
3209 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
3210 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
3211 if (iLayerPlane
) goto invalid_layer
;
3215 case WGL_SHARE_DEPTH_ARB
:
3216 case WGL_SHARE_STENCIL_ARB
:
3217 case WGL_SHARE_ACCUM_ARB
:
3218 if (iLayerPlane
) goto invalid_layer
;
3219 piValues
[i
] = GL_TRUE
;
3222 case WGL_SUPPORT_GDI_ARB
:
3223 if (iLayerPlane
) goto invalid_layer
;
3224 piValues
[i
] = GL_FALSE
;
3227 case WGL_SUPPORT_OPENGL_ARB
:
3228 if (iLayerPlane
) goto invalid_layer
;
3229 piValues
[i
] = GL_TRUE
;
3232 case WGL_DOUBLE_BUFFER_ARB
:
3233 if (iLayerPlane
) goto invalid_layer
;
3234 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
3237 case WGL_STEREO_ARB
:
3238 if (iLayerPlane
) goto invalid_layer
;
3239 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
3242 case WGL_PIXEL_TYPE_ARB
:
3243 if (iLayerPlane
) goto invalid_layer
;
3244 if (color_modes
[pf
->color_mode
].is_float
)
3245 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
3247 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
3248 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3249 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3250 However, Mac contexts don't support rendering to unsigned floating-point
3251 formats, even when GL_EXT_packed_float is supported. */
3254 case WGL_COLOR_BITS_ARB
:
3255 if (iLayerPlane
) goto invalid_layer
;
3256 /* If the mode doesn't have alpha, return bits per pixel instead
3257 of color bits. On Windows, color bits sometimes exceeds r+g+b
3258 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3259 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3260 pixel format, we need to accommodate that. */
3261 if (color_modes
[pf
->color_mode
].alpha_bits
)
3262 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
3264 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
3267 case WGL_RED_BITS_ARB
:
3268 if (iLayerPlane
) goto invalid_layer
;
3269 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
3272 case WGL_RED_SHIFT_ARB
:
3273 if (iLayerPlane
) goto invalid_layer
;
3274 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
3277 case WGL_GREEN_BITS_ARB
:
3278 if (iLayerPlane
) goto invalid_layer
;
3279 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
3282 case WGL_GREEN_SHIFT_ARB
:
3283 if (iLayerPlane
) goto invalid_layer
;
3284 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
3287 case WGL_BLUE_BITS_ARB
:
3288 if (iLayerPlane
) goto invalid_layer
;
3289 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
3292 case WGL_BLUE_SHIFT_ARB
:
3293 if (iLayerPlane
) goto invalid_layer
;
3294 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
3297 case WGL_ALPHA_BITS_ARB
:
3298 if (iLayerPlane
) goto invalid_layer
;
3299 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
3302 case WGL_ALPHA_SHIFT_ARB
:
3303 if (iLayerPlane
) goto invalid_layer
;
3304 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
3307 case WGL_ACCUM_BITS_ARB
:
3308 if (iLayerPlane
) goto invalid_layer
;
3310 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3315 case WGL_ACCUM_RED_BITS_ARB
:
3316 if (iLayerPlane
) goto invalid_layer
;
3318 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
3323 case WGL_ACCUM_GREEN_BITS_ARB
:
3324 if (iLayerPlane
) goto invalid_layer
;
3326 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
3331 case WGL_ACCUM_BLUE_BITS_ARB
:
3332 if (iLayerPlane
) goto invalid_layer
;
3334 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
3339 case WGL_ACCUM_ALPHA_BITS_ARB
:
3340 if (iLayerPlane
) goto invalid_layer
;
3342 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
3347 case WGL_DEPTH_BITS_ARB
:
3348 if (iLayerPlane
) goto invalid_layer
;
3349 piValues
[i
] = pf
->depth_bits
;
3352 case WGL_STENCIL_BITS_ARB
:
3353 if (iLayerPlane
) goto invalid_layer
;
3354 piValues
[i
] = pf
->stencil_bits
;
3357 case WGL_AUX_BUFFERS_ARB
:
3358 if (iLayerPlane
) goto invalid_layer
;
3359 piValues
[i
] = pf
->aux_buffers
;
3362 case WGL_SAMPLE_BUFFERS_ARB
:
3363 if (iLayerPlane
) goto invalid_layer
;
3364 piValues
[i
] = pf
->sample_buffers
;
3367 case WGL_SAMPLES_ARB
:
3368 if (iLayerPlane
) goto invalid_layer
;
3369 piValues
[i
] = pf
->samples
;
3372 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3373 if (iLayerPlane
) goto invalid_layer
;
3374 /* sRGB is only supported for 8-bit integer color components */
3375 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
3376 color_modes
[pf
->color_mode
].green_bits
== 8 &&
3377 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
3378 !color_modes
[pf
->color_mode
].is_float
)
3379 piValues
[i
] = GL_TRUE
;
3381 piValues
[i
] = GL_FALSE
;
3384 case WGL_DRAW_TO_PBUFFER_ARB
:
3385 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
3386 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
3387 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
3390 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
3391 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
3392 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
3395 case WGL_MAX_PBUFFER_WIDTH_ARB
:
3396 piValues
[i
] = gl_info
.max_viewport_dims
[0];
3399 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
3400 piValues
[i
] = gl_info
.max_viewport_dims
[1];
3403 case WGL_MAX_PBUFFER_PIXELS_ARB
:
3404 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
3408 WARN("invalid attribute %x\n", piAttributes
[i
]);
3412 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
3418 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
3423 /**********************************************************************
3424 * macdrv_wglGetPixelFormatAttribfvARB
3426 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3428 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3429 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
3434 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3435 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
3437 /* Allocate a temporary array to store integer values */
3438 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
3441 ERR("couldn't allocate %d array\n", nAttributes
);
3445 /* Piggy-back on wglGetPixelFormatAttribivARB */
3446 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
3451 /* Convert integer values to float. Should also check for attributes
3452 that can give decimal values here */
3453 for (i
= 0; i
< nAttributes
; i
++)
3454 pfValues
[i
] = attr
[i
];
3457 HeapFree(GetProcessHeap(), 0, attr
);
3462 /**********************************************************************
3463 * macdrv_wglGetSwapIntervalEXT
3465 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3467 static int macdrv_wglGetSwapIntervalEXT(void)
3469 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3470 struct macdrv_win_data
*data
;
3476 if ((data
= get_win_data(context
->draw_hwnd
)))
3478 value
= data
->swap_interval
;
3479 release_win_data(data
);
3481 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3482 set_swap_interval(context
, allow_vsync
? value
: 0);
3486 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3487 if (err
!= kCGLNoError
)
3489 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3490 err
, CGLErrorString(err
));
3499 /***********************************************************************
3500 * macdrv_wglMakeContextCurrentARB
3502 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3504 * This is not supported directly by OpenGL on the Mac. We emulate it
3505 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3506 * temporarily swap the drawable. This follows the technique used in
3507 * the implementation of Mesa GLX for Apple.
3509 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3511 struct macdrv_win_data
*data
;
3514 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3515 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3519 macdrv_make_context_current(NULL
, NULL
, CGRectNull
);
3520 NtCurrentTeb()->glContext
= NULL
;
3524 if ((hwnd
= WindowFromDC(draw_hdc
)))
3526 if (!(data
= get_win_data(hwnd
)))
3528 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3532 if (!data
->pixel_format
)
3534 WARN("no pixel format set\n");
3535 release_win_data(data
);
3536 SetLastError(ERROR_INVALID_HANDLE
);
3539 if (context
->format
!= data
->pixel_format
)
3541 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3542 release_win_data(data
);
3543 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3547 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
)
3548 set_swap_interval(context
, allow_vsync
? data
->swap_interval
: 0);
3550 context
->draw_hwnd
= hwnd
;
3551 context
->draw_view
= data
->client_cocoa_view
;
3552 context
->draw_rect
= data
->client_rect
;
3553 OffsetRect(&context
->draw_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3554 context
->draw_pbuffer
= NULL
;
3555 release_win_data(data
);
3559 struct wgl_pbuffer
*pbuffer
;
3561 EnterCriticalSection(&dc_pbuffers_section
);
3562 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3565 if (context
->format
!= pbuffer
->format
)
3567 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3568 LeaveCriticalSection(&dc_pbuffers_section
);
3569 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3573 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
)
3574 set_swap_interval(context
, 0);
3578 WARN("no window or pbuffer for DC\n");
3579 LeaveCriticalSection(&dc_pbuffers_section
);
3580 SetLastError(ERROR_INVALID_HANDLE
);
3584 context
->draw_hwnd
= NULL
;
3585 context
->draw_view
= NULL
;
3586 context
->draw_pbuffer
= pbuffer
;
3587 LeaveCriticalSection(&dc_pbuffers_section
);
3590 context
->read_view
= NULL
;
3591 context
->read_pbuffer
= NULL
;
3592 if (read_hdc
&& read_hdc
!= draw_hdc
)
3594 if ((hwnd
= WindowFromDC(read_hdc
)))
3596 if ((data
= get_win_data(hwnd
)))
3598 if (data
->client_cocoa_view
!= context
->draw_view
)
3600 context
->read_view
= data
->client_cocoa_view
;
3601 context
->read_rect
= data
->client_rect
;
3602 OffsetRect(&context
->read_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3604 release_win_data(data
);
3609 EnterCriticalSection(&dc_pbuffers_section
);
3610 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3611 LeaveCriticalSection(&dc_pbuffers_section
);
3615 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3616 context
->draw_view
, wine_dbgstr_rect(&context
->draw_rect
), context
->draw_pbuffer
,
3617 context
->read_view
, wine_dbgstr_rect(&context
->read_rect
), context
->read_pbuffer
, context
->format
);
3619 make_context_current(context
, FALSE
);
3620 context
->has_been_current
= TRUE
;
3621 NtCurrentTeb()->glContext
= context
;
3627 /**********************************************************************
3628 * macdrv_wglQueryCurrentRendererIntegerWINE
3630 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3632 static BOOL
macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute
, GLuint
*value
)
3635 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3636 CGLPixelFormatObj pixel_format
;
3638 GLint virtual_screen
;
3640 GLint pf_renderer_id
;
3641 CGLRendererInfoObj renderer_info
;
3642 GLint renderer_count
;
3645 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context
, (context
? context
->context
: NULL
),
3646 (context
? context
->cglcontext
: NULL
), attribute
, value
);
3648 if (attribute
== WGL_RENDERER_VERSION_WINE
)
3650 if (!parse_renderer_version((const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
), value
))
3651 get_fallback_renderer_version(value
);
3652 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
3656 pixel_format
= CGLGetPixelFormat(context
->cglcontext
);
3657 err
= CGLGetVirtualScreen(context
->cglcontext
, &virtual_screen
);
3658 if (err
!= kCGLNoError
)
3660 WARN("CGLGetVirtualScreen failed: %d %s\n", err
, CGLErrorString(err
));
3664 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFADisplayMask
, &display_mask
);
3665 if (err
!= kCGLNoError
)
3667 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err
, CGLErrorString(err
));
3671 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFARendererID
, &pf_renderer_id
);
3672 if (err
!= kCGLNoError
)
3674 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err
, CGLErrorString(err
));
3678 err
= CGLQueryRendererInfo(display_mask
, &renderer_info
, &renderer_count
);
3679 if (err
!= kCGLNoError
)
3681 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3685 for (renderer
= 0; renderer
< renderer_count
; renderer
++)
3689 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
3692 if (renderer_id
== pf_renderer_id
)
3694 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3699 if (renderer
>= renderer_count
)
3700 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id
, display_mask
);
3702 CGLDestroyRendererInfo(renderer_info
);
3707 /**********************************************************************
3708 * macdrv_wglQueryCurrentRendererStringWINE
3710 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3712 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute
)
3714 const char* ret
= NULL
;
3715 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3717 TRACE("context %p/%p/%p attribute 0x%04x\n", context
, (context
? context
->context
: NULL
),
3718 (context
? context
->cglcontext
: NULL
), attribute
);
3722 case WGL_RENDERER_DEVICE_ID_WINE
:
3724 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_RENDERER
);
3725 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret
));
3729 case WGL_RENDERER_VENDOR_ID_WINE
:
3731 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VENDOR
);
3732 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret
));
3737 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3745 /**********************************************************************
3746 * macdrv_wglQueryPbufferARB
3748 * WGL_ARB_pbuffer: wglQueryPbufferARB
3750 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3756 GLenum internalFormat
;
3759 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3761 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3762 if (err
!= kCGLNoError
)
3764 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3765 SetLastError(ERROR_INVALID_HANDLE
);
3771 case WGL_PBUFFER_WIDTH_ARB
:
3774 case WGL_PBUFFER_HEIGHT_ARB
:
3777 case WGL_PBUFFER_LOST_ARB
:
3778 /* Mac PBuffers can't be lost */
3779 *piValue
= GL_FALSE
;
3781 case WGL_TEXTURE_FORMAT_ARB
:
3782 if (pbuffer
->no_texture
)
3783 *piValue
= WGL_NO_TEXTURE_ARB
;
3784 else switch (internalFormat
)
3787 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3791 *piValue
= WGL_TEXTURE_RGB_ARB
;
3795 case WGL_TEXTURE_TARGET_ARB
:
3796 if (pbuffer
->no_texture
)
3797 *piValue
= WGL_NO_TEXTURE_ARB
;
3798 else switch (target
)
3800 case GL_TEXTURE_CUBE_MAP
:
3801 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3804 *piValue
= WGL_TEXTURE_2D_ARB
;
3806 case GL_TEXTURE_RECTANGLE
:
3808 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3812 case WGL_MIPMAP_TEXTURE_ARB
:
3813 *piValue
= (pbuffer
->max_level
> 0);
3815 case WGL_MIPMAP_LEVEL_ARB
:
3816 *piValue
= pbuffer
->level
;
3818 case WGL_CUBE_MAP_FACE_ARB
:
3819 switch (pbuffer
->face
)
3821 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3823 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3825 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3826 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3828 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3829 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3831 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3832 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3835 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3838 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3843 WARN("invalid attribute 0x%x\n", iAttribute
);
3844 SetLastError(ERROR_INVALID_DATA
);
3852 /**********************************************************************
3853 * macdrv_wglQueryRendererIntegerWINE
3855 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3857 static BOOL
macdrv_wglQueryRendererIntegerWINE(HDC dc
, GLint renderer
, GLenum attribute
, GLuint
*value
)
3860 CGLRendererInfoObj renderer_info
;
3861 GLint renderer_count
;
3864 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc
, renderer
, attribute
, value
);
3866 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3867 if (err
!= kCGLNoError
)
3869 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3873 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3875 if (renderer
< renderer_count
)
3876 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3878 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3880 CGLDestroyRendererInfo(renderer_info
);
3885 /**********************************************************************
3886 * macdrv_wglQueryRendererStringWINE
3888 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3890 static const char *macdrv_wglQueryRendererStringWINE(HDC dc
, GLint renderer
, GLenum attribute
)
3892 const char* ret
= NULL
;
3893 CGLRendererInfoObj renderer_info
;
3894 GLint renderer_count
;
3897 TRACE("dc %p renderer %d attribute 0x%04x\n", dc
, renderer
, attribute
);
3899 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3900 if (err
!= kCGLNoError
)
3902 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3906 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3908 if (renderer
>= renderer_count
)
3910 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3916 case WGL_RENDERER_DEVICE_ID_WINE
:
3917 case WGL_RENDERER_VENDOR_ID_WINE
:
3919 BOOL device
= (attribute
== WGL_RENDERER_DEVICE_ID_WINE
);
3920 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
3923 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
3926 ret
= get_gl_string(pixel_format
, device
? GL_RENDERER
: GL_VENDOR
);
3927 CGLReleasePixelFormat(pixel_format
);
3930 TRACE("%s -> %s\n", device
? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret
));
3935 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3940 CGLDestroyRendererInfo(renderer_info
);
3945 /**********************************************************************
3946 * macdrv_wglReleasePbufferDCARB
3948 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3950 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3952 struct wgl_pbuffer
*prev
;
3954 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3956 EnterCriticalSection(&dc_pbuffers_section
);
3958 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3961 if (prev
!= pbuffer
)
3962 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3963 CGLReleasePBuffer(prev
->pbuffer
);
3964 HeapFree(GetProcessHeap(), 0, prev
);
3965 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3969 LeaveCriticalSection(&dc_pbuffers_section
);
3971 return hdc
&& DeleteDC(hdc
);
3975 /**********************************************************************
3976 * macdrv_wglReleaseTexImageARB
3978 * WGL_ARB_render_texture: wglReleaseTexImageARB
3980 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3982 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3985 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3987 if (pbuffer
->no_texture
)
3989 SetLastError(ERROR_INVALID_OPERATION
);
3993 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3994 if (err
!= kCGLNoError
)
3996 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3997 SetLastError(ERROR_INVALID_OPERATION
);
4005 /**********************************************************************
4006 * macdrv_wglSetPbufferAttribARB
4008 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4010 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
4012 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4014 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
4016 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
4018 int attr
= piAttribList
[0];
4019 int value
= piAttribList
[1];
4022 case WGL_MIPMAP_LEVEL_ARB
:
4023 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
4024 pbuffer
->level
= value
;
4026 case WGL_CUBE_MAP_FACE_ARB
:
4029 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
4030 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4031 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
4033 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4034 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4035 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
4037 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4038 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4039 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
4041 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4042 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4043 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
4045 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4046 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4047 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
4049 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4050 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4051 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
4054 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
4055 SetLastError(ERROR_INVALID_DATA
);
4060 WARN("invalid attribute 0x%x\n", attr
);
4061 SetLastError(ERROR_INVALID_DATA
);
4066 if (context
&& context
->draw_pbuffer
== pbuffer
)
4067 make_context_current(context
, FALSE
);
4073 /**********************************************************************
4074 * macdrv_wglSetPixelFormatWINE
4076 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4078 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
4080 return set_pixel_format(hdc
, fmt
, TRUE
);
4084 /**********************************************************************
4085 * macdrv_wglSwapIntervalEXT
4087 * WGL_EXT_swap_control: wglSwapIntervalEXT
4089 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
4091 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4092 BOOL changed
= FALSE
;
4094 TRACE("interval %d\n", interval
);
4098 SetLastError(ERROR_INVALID_DATA
);
4104 if (context
->draw_hwnd
)
4106 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
4109 changed
= data
->swap_interval
!= interval
;
4111 data
->swap_interval
= interval
;
4112 release_win_data(data
);
4121 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
4122 if (!set_swap_interval(context
, interval
))
4124 SetLastError(ERROR_GEN_FAILURE
);
4130 struct wgl_context
*ctx
;
4132 EnterCriticalSection(&context_section
);
4133 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
4135 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
4136 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
4138 LeaveCriticalSection(&context_section
);
4145 static void register_extension(const char *ext
)
4147 if (gl_info
.wglExtensions
[0])
4148 strcat(gl_info
.wglExtensions
, " ");
4149 strcat(gl_info
.wglExtensions
, ext
);
4151 TRACE("'%s'\n", ext
);
4154 static void load_extensions(void)
4159 register_extension("WGL_ARB_extensions_string");
4160 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
4162 register_extension("WGL_ARB_make_current_read");
4163 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
4164 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
4166 register_extension("WGL_ARB_pixel_format");
4167 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
4168 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
4169 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
4171 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
4173 register_extension("WGL_ARB_pixel_format_float");
4174 register_extension("WGL_ATI_pixel_format_float");
4177 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
4178 register_extension("WGL_ARB_multisample");
4180 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4181 register_extension("WGL_ARB_framebuffer_sRGB");
4183 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
4185 register_extension("WGL_ARB_pbuffer");
4186 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
4187 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
4188 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
4189 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
4190 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
4192 register_extension("WGL_ARB_render_texture");
4193 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
4194 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
4195 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
4197 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
4198 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
4199 register_extension("WGL_NV_render_texture_rectangle");
4202 register_extension("WGL_ARB_create_context");
4203 register_extension("WGL_ARB_create_context_profile");
4204 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
4209 register_extension("WGL_EXT_extensions_string");
4210 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
4214 register_extension("WGL_EXT_swap_control");
4215 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
4216 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
4219 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4220 check for either, so register them separately. */
4221 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4222 register_extension("WGL_EXT_framebuffer_sRGB");
4224 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
4225 register_extension("WGL_EXT_pixel_format_packed_float");
4228 * WINE-specific WGL Extensions
4231 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4232 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4234 register_extension("WGL_WINE_pixel_format_passthrough");
4235 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
4237 register_extension("WGL_WINE_query_renderer");
4238 opengl_funcs
.ext
.p_wglQueryCurrentRendererIntegerWINE
= macdrv_wglQueryCurrentRendererIntegerWINE
;
4239 opengl_funcs
.ext
.p_wglQueryCurrentRendererStringWINE
= macdrv_wglQueryCurrentRendererStringWINE
;
4240 opengl_funcs
.ext
.p_wglQueryRendererIntegerWINE
= macdrv_wglQueryRendererIntegerWINE
;
4241 opengl_funcs
.ext
.p_wglQueryRendererStringWINE
= macdrv_wglQueryRendererStringWINE
;
4245 static BOOL CALLBACK
init_opengl(INIT_ONCE
*init_once
, void *context
, void **param
)
4247 static BOOL init_done
= FALSE
;
4250 if (init_done
) return (opengl_handle
!= NULL
);
4255 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
4258 WARN("CFDictionaryCreateMutable failed\n");
4262 opengl_handle
= dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
);
4265 ERR("Failed to load OpenGL: %s\n", dlerror());
4266 ERR("OpenGL support is disabled.\n");
4270 for (i
= 0; i
< ARRAY_SIZE(opengl_func_names
); i
++)
4272 if (!(((void **)&opengl_funcs
.gl
)[i
] = dlsym(opengl_handle
, opengl_func_names
[i
])))
4274 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
4279 if (!init_gl_info())
4282 /* redirect some standard OpenGL functions */
4283 #define REDIRECT(func) \
4284 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4285 REDIRECT(glCopyPixels
);
4286 REDIRECT(glGetString
);
4287 REDIRECT(glReadPixels
);
4288 REDIRECT(glViewport
);
4289 if (skip_single_buffer_flushes
|| allow_vsync
)
4295 /* redirect some OpenGL extension functions */
4296 #define REDIRECT(func) \
4297 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4298 REDIRECT(glCopyColorTable
);
4301 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
4302 pglFlushRenderAPPLE
= dlsym(opengl_handle
, "glFlushRenderAPPLE");
4305 if (!init_pixel_formats())
4311 dlclose(opengl_handle
);
4312 opengl_handle
= NULL
;
4317 /***********************************************************************
4320 * Synchronize the Mac GL view position with the Windows child window
4323 void sync_gl_view(struct macdrv_win_data
* data
, const RECT
* old_whole_rect
, const RECT
* old_client_rect
)
4325 if (data
->client_cocoa_view
&& data
->pixel_format
)
4327 RECT old
= *old_client_rect
, new = data
->client_rect
;
4329 OffsetRect(&old
, -old_whole_rect
->left
, -old_whole_rect
->top
);
4330 OffsetRect(&new, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
4331 if (!EqualRect(&old
, &new))
4333 TRACE("GL view %p changed position; marking contexts\n", data
->client_cocoa_view
);
4334 mark_contexts_for_moved_view(data
->client_cocoa_view
);
4340 /**********************************************************************
4341 * macdrv_wglDescribePixelFormat
4343 static int WINAPI
macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
4345 const pixel_format
*pf
;
4346 const struct color_mode
*mode
;
4348 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
4350 if (!descr
) return nb_displayable_formats
;
4351 if (size
< sizeof(*descr
)) return 0;
4353 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
4356 memset(descr
, 0, sizeof(*descr
));
4357 descr
->nSize
= sizeof(*descr
);
4358 descr
->nVersion
= 1;
4360 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
4361 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
4362 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
4363 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
4364 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
4365 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
4367 descr
->iPixelType
= PFD_TYPE_RGBA
;
4369 mode
= &color_modes
[pf
->color_mode
];
4370 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4371 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4372 R8G8B8A0 pixel format). If an app depends on that and expects that
4373 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4374 if (mode
->alpha_bits
)
4375 descr
->cColorBits
= mode
->color_bits
;
4377 descr
->cColorBits
= mode
->bits_per_pixel
;
4378 descr
->cRedBits
= mode
->red_bits
;
4379 descr
->cRedShift
= mode
->red_shift
;
4380 descr
->cGreenBits
= mode
->green_bits
;
4381 descr
->cGreenShift
= mode
->green_shift
;
4382 descr
->cBlueBits
= mode
->blue_bits
;
4383 descr
->cBlueShift
= mode
->blue_shift
;
4384 descr
->cAlphaBits
= mode
->alpha_bits
;
4385 descr
->cAlphaShift
= mode
->alpha_shift
;
4389 mode
= &color_modes
[pf
->accum_mode
- 1];
4390 descr
->cAccumBits
= mode
->color_bits
;
4391 descr
->cAccumRedBits
= mode
->red_bits
;
4392 descr
->cAccumGreenBits
= mode
->green_bits
;
4393 descr
->cAccumBlueBits
= mode
->blue_bits
;
4394 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
4397 descr
->cDepthBits
= pf
->depth_bits
;
4398 descr
->cStencilBits
= pf
->stencil_bits
;
4399 descr
->cAuxBuffers
= pf
->aux_buffers
;
4400 descr
->iLayerType
= PFD_MAIN_PLANE
;
4402 TRACE("%s\n", debugstr_pf(pf
));
4403 return nb_displayable_formats
;
4406 /***********************************************************************
4407 * macdrv_wglCopyContext
4409 static BOOL WINAPI
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
4413 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
4415 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
4416 if (err
!= kCGLNoError
)
4417 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
4418 return (err
== kCGLNoError
);
4421 /***********************************************************************
4422 * macdrv_wglCreateContext
4424 static struct wgl_context
* WINAPI
macdrv_wglCreateContext(HDC hdc
)
4426 struct wgl_context
*context
;
4428 TRACE("hdc %p\n", hdc
);
4430 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
4435 /***********************************************************************
4436 * macdrv_wglDeleteContext
4438 static BOOL WINAPI
macdrv_wglDeleteContext(struct wgl_context
*context
)
4440 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
4442 EnterCriticalSection(&context_section
);
4443 list_remove(&context
->entry
);
4444 LeaveCriticalSection(&context_section
);
4446 macdrv_dispose_opengl_context(context
->context
);
4447 return HeapFree(GetProcessHeap(), 0, context
);
4450 /***********************************************************************
4451 * macdrv_wglGetPixelFormat
4453 static int WINAPI
macdrv_wglGetPixelFormat(HDC hdc
)
4457 format
= get_dc_pixel_format(hdc
);
4459 if (!is_valid_pixel_format(format
)) /* not set yet */
4461 else if (!is_displayable_pixel_format(format
))
4463 /* Non-displayable formats can't be used with traditional WGL calls.
4464 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4468 TRACE(" hdc %p -> %d\n", hdc
, format
);
4472 /***********************************************************************
4473 * macdrv_wglGetProcAddress
4475 static PROC WINAPI
macdrv_wglGetProcAddress(const char *proc
)
4479 if (!strncmp(proc
, "wgl", 3)) return NULL
;
4480 ret
= dlsym(opengl_handle
, proc
);
4486 if (dladdr(ret
, &info
))
4487 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
4489 TRACE("%s -> %p (no library info)\n", proc
, ret
);
4493 WARN("failed to find proc %s\n", debugstr_a(proc
));
4497 /***********************************************************************
4498 * macdrv_wglMakeCurrent
4500 static BOOL WINAPI
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
4502 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4503 (context
? context
->cglcontext
: NULL
));
4505 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
4508 /**********************************************************************
4509 * macdrv_wglSetPixelFormat
4511 static BOOL WINAPI
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
4513 return set_pixel_format(hdc
, fmt
, FALSE
);
4516 /***********************************************************************
4517 * macdrv_wglShareLists
4519 static BOOL WINAPI
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
4521 macdrv_opengl_context saved_context
;
4522 CGLContextObj saved_cglcontext
;
4524 TRACE("org %p dest %p\n", org
, dest
);
4526 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4527 * at context creation time but in case of WGL it is done using wglShareLists.
4529 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4530 * and when a program requests sharing we recreate the destination context if it hasn't been made
4531 * current or when it hasn't shared display lists before.
4534 if (dest
->has_been_current
)
4536 WARN("could not share display lists, the destination context has been current already\n");
4539 else if (dest
->sharing
)
4541 WARN("could not share display lists because dest has already shared lists before\n");
4545 /* Re-create the Mac context and share display lists */
4546 saved_context
= dest
->context
;
4547 saved_cglcontext
= dest
->cglcontext
;
4548 dest
->context
= NULL
;
4549 dest
->cglcontext
= NULL
;
4550 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
4552 dest
->context
= saved_context
;
4553 dest
->cglcontext
= saved_cglcontext
;
4557 /* Implicitly disposes of saved_cglcontext. */
4558 macdrv_dispose_opengl_context(saved_context
);
4560 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4561 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
4563 org
->sharing
= TRUE
;
4564 dest
->sharing
= TRUE
;
4569 /**********************************************************************
4570 * macdrv_wglSwapBuffers
4572 static BOOL WINAPI
macdrv_wglSwapBuffers(HDC hdc
)
4574 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4578 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4579 (context
? context
->cglcontext
: NULL
));
4583 sync_swap_interval(context
);
4584 sync_context(context
);
4587 if ((hwnd
= WindowFromDC(hdc
)))
4589 struct macdrv_win_data
*data
;
4591 if (!(data
= get_win_data(hwnd
)))
4593 SetLastError(ERROR_INVALID_HANDLE
);
4597 if (context
&& context
->draw_view
== data
->client_cocoa_view
)
4600 release_win_data(data
);
4604 struct wgl_pbuffer
*pbuffer
;
4606 EnterCriticalSection(&dc_pbuffers_section
);
4607 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4608 LeaveCriticalSection(&dc_pbuffers_section
);
4612 SetLastError(ERROR_INVALID_HANDLE
);
4616 if (context
&& context
->draw_pbuffer
== pbuffer
)
4621 macdrv_flush_opengl_context(context
->context
);
4624 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
4626 /* If there is a current context, then wglSwapBuffers should do an implicit
4627 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4628 in the other branch, but we have to do it explicitly here. */
4636 static struct opengl_funcs opengl_funcs
=
4639 macdrv_wglCopyContext
, /* p_wglCopyContext */
4640 macdrv_wglCreateContext
, /* p_wglCreateContext */
4641 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
4642 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
4643 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
4644 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
4645 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
4646 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
4647 macdrv_wglShareLists
, /* p_wglShareLists */
4648 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
4652 /**********************************************************************
4653 * macdrv_wine_get_wgl_driver
4655 struct opengl_funcs
* CDECL
macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
4657 static INIT_ONCE opengl_init
= INIT_ONCE_STATIC_INIT
;
4659 if (version
!= WINE_WGL_DRIVER_VERSION
)
4661 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
4665 if (!InitOnceExecuteOnce(&opengl_init
, init_opengl
, NULL
, NULL
)) return (void *)-1;
4667 return &opengl_funcs
;