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 &&
745 depth_stencil_modes
[depth_mode
].bits
!= 32 && stencil_mode
> 0)
748 attribs
[n
++] = kCGLPFAStencilSize
;
749 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
750 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
752 /* FIXME: Could trim search space a bit here depending on GPU.
753 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
754 n_stack
[++n_stack_idx
] = n
;
755 for (stereo
= 0; stereo
<= 1; stereo
++)
759 n
= n_stack
[n_stack_idx
];
761 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
762 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
766 attribs
[n
++] = kCGLPFAStereo
;
767 request
.stereo
= stereo
;
769 /* Starts at -1 for a 0 accum size */
770 n_stack
[++n_stack_idx
] = n
;
771 for (accum_mode
= -1; accum_mode
< (int) ARRAY_SIZE(color_modes
); accum_mode
++)
773 unsigned int target_pass
;
775 n
= n_stack
[n_stack_idx
];
779 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
782 attribs
[n
++] = kCGLPFAAccumSize
;
783 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
784 request
.accum_mode
= accum_mode
+ 1;
787 request
.accum_mode
= 0;
789 /* Targets to request are:
790 accelerated: window OR window + pbuffer
791 software: window + pbuffer */
792 n_stack
[++n_stack_idx
] = n
;
793 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
795 unsigned int samples
, max_samples
;
797 n
= n_stack
[n_stack_idx
];
799 attribs
[n
++] = kCGLPFAWindow
;
802 if (!accelerated
|| target_pass
> 0)
804 attribs
[n
++] = kCGLPFAPBuffer
;
810 /* FIXME: Could trim search space a bit here depending on GPU.
811 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
812 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
813 n_stack
[++n_stack_idx
] = n
;
814 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
815 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
817 unsigned int backing_store
, min_backing_store
, max_backing_store
;
819 n
= n_stack
[n_stack_idx
];
823 attribs
[n
++] = kCGLPFASampleBuffers
;
824 attribs
[n
++] = renderer
.max_sample_buffers
;
825 attribs
[n
++] = kCGLPFASamples
;
826 attribs
[n
++] = samples
;
827 request
.sample_buffers
= renderer
.max_sample_buffers
;
828 request
.samples
= samples
;
831 request
.sample_buffers
= request
.samples
= 0;
833 if (renderer
.backing_store
&& double_buffer
)
835 /* The software renderer seems to always preserve the backing store, whether
836 we ask for it or not. So don't bother not asking for it. */
837 min_backing_store
= accelerated
? 0 : 1;
838 max_backing_store
= 1;
841 min_backing_store
= max_backing_store
= 0;
842 n_stack
[++n_stack_idx
] = n
;
843 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
845 CGLPixelFormatObj pix
;
846 GLint virtualScreens
;
849 n
= n_stack
[n_stack_idx
];
852 attribs
[n
++] = kCGLPFABackingStore
;
853 request
.backing_store
= backing_store
;
857 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
858 if (err
== kCGLNoError
&& pix
)
861 GLint value
, color_size
, alpha_size
, color_float
;
863 CFNumberRef code_object
;
866 memset(&pf
, 0, sizeof(pf
));
868 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
869 pf
.accelerated
= value
;
870 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
871 pf
.aux_buffers
= value
;
872 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
873 pf
.depth_bits
= value
;
874 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
875 pf
.double_buffer
= value
;
876 if (pf
.double_buffer
&&
877 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
878 pf
.backing_store
= value
;
879 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
881 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
882 pf
.sample_buffers
= value
;
883 if (pf
.sample_buffers
&&
884 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
886 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
887 pf
.stencil_bits
= value
;
888 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
890 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
893 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
895 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
897 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
899 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
901 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
902 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
904 CGLReleasePixelFormat(pix
);
906 pf_code
= code_for_pixel_format(&pf
);
908 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
909 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
910 dupe_pixel_formats
++;
913 CFSetAddValue(pixel_format_set
, code_object
);
914 CFArrayAppendValue(pixel_format_array
, code_object
);
917 CFRelease(code_object
);
919 if (pf_code
== code_for_pixel_format(&request
))
920 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
923 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
924 dupe
? " (duplicate)" : "");
929 failed_pixel_formats
++;
930 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
933 tried_pixel_formats
++;
965 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
966 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
967 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
968 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
972 /* The docs for WGL_ARB_pixel_format say:
973 Indices are assigned to pixel formats in the following order:
974 1. Accelerated pixel formats that are displayable
975 2. Accelerated pixel formats that are displayable and which have
977 3. Generic pixel formats
978 4. Accelerated pixel formats that are non displayable
980 static int pixel_format_category(pixel_format pf
)
982 /* non-displayable */
986 /* non-accelerated a.k.a. software a.k.a. generic */
990 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
991 if (color_modes
[pf
.color_mode
].is_float
)
994 /* accelerated, displayable, no extended attributes */
999 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
1001 CFNumberRef number1
= val1
;
1002 CFNumberRef number2
= val2
;
1003 UInt64 code1
, code2
;
1004 pixel_format pf1
, pf2
;
1005 int category1
, category2
;
1007 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
1008 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
1009 pf1
= pixel_format_for_code(code1
);
1010 pf2
= pixel_format_for_code(code2
);
1011 category1
= pixel_format_category(pf1
);
1012 category2
= pixel_format_category(pf2
);
1014 if (category1
< category2
)
1015 return kCFCompareLessThan
;
1016 if (category1
> category2
)
1017 return kCFCompareGreaterThan
;
1019 /* Within a category, sort the "best" formats toward the front since that's
1020 what wglChoosePixelFormatARB() has to do. The ordering implemented here
1021 matches at least one Windows 7 machine's behavior.
1023 /* Accelerated before unaccelerated. */
1024 if (pf1
.accelerated
&& !pf2
.accelerated
)
1025 return kCFCompareLessThan
;
1026 if (!pf1
.accelerated
&& pf2
.accelerated
)
1027 return kCFCompareGreaterThan
;
1029 /* Explicit color mode ordering. */
1030 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1031 return kCFCompareLessThan
;
1032 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1033 return kCFCompareGreaterThan
;
1035 /* Non-pbuffer-capable before pbuffer-capable. */
1036 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1037 return kCFCompareLessThan
;
1038 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1039 return kCFCompareGreaterThan
;
1041 /* Fewer samples before more samples. */
1042 if (pf1
.samples
< pf2
.samples
)
1043 return kCFCompareLessThan
;
1044 if (pf1
.samples
> pf2
.samples
)
1045 return kCFCompareGreaterThan
;
1047 /* Monoscopic before stereoscopic. (This is a guess.) */
1048 if (!pf1
.stereo
&& pf2
.stereo
)
1049 return kCFCompareLessThan
;
1050 if (pf1
.stereo
&& !pf2
.stereo
)
1051 return kCFCompareGreaterThan
;
1053 /* Single buffered before double buffered. */
1054 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1055 return kCFCompareLessThan
;
1056 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1057 return kCFCompareGreaterThan
;
1059 /* Possibly-optimized double buffering before backing-store-preserving
1060 double buffering. */
1061 if (!pf1
.backing_store
&& pf2
.backing_store
)
1062 return kCFCompareLessThan
;
1063 if (pf1
.backing_store
&& !pf2
.backing_store
)
1064 return kCFCompareGreaterThan
;
1066 /* Bigger depth buffer before smaller depth buffer. */
1067 if (pf1
.depth_bits
> pf2
.depth_bits
)
1068 return kCFCompareLessThan
;
1069 if (pf1
.depth_bits
< pf2
.depth_bits
)
1070 return kCFCompareGreaterThan
;
1072 /* Smaller stencil buffer before bigger stencil buffer. */
1073 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1074 return kCFCompareLessThan
;
1075 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1076 return kCFCompareGreaterThan
;
1078 /* Smaller alpha bits before larger alpha bits. */
1079 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1080 return kCFCompareLessThan
;
1081 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1082 return kCFCompareGreaterThan
;
1084 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1089 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1090 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1091 return kCFCompareLessThan
;
1092 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1093 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1094 return kCFCompareGreaterThan
;
1096 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1097 return kCFCompareLessThan
;
1098 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1099 return kCFCompareGreaterThan
;
1101 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1102 return kCFCompareLessThan
;
1103 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1104 return kCFCompareGreaterThan
;
1107 return kCFCompareGreaterThan
;
1109 else if (pf2
.accum_mode
)
1110 return kCFCompareLessThan
;
1112 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1113 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1114 return kCFCompareLessThan
;
1115 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1116 return kCFCompareGreaterThan
;
1118 /* If we get here, arbitrarily sort based on code. */
1120 return kCFCompareLessThan
;
1122 return kCFCompareGreaterThan
;
1123 return kCFCompareEqualTo
;
1127 static BOOL
init_pixel_formats(void)
1130 CGLRendererInfoObj renderer_info
;
1131 GLint rendererCount
;
1133 CFMutableSetRef pixel_format_set
;
1134 CFMutableArrayRef pixel_format_array
;
1140 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1143 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1147 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1148 if (!pixel_format_set
)
1150 WARN("CFSetCreateMutable failed\n");
1151 CGLDestroyRendererInfo(renderer_info
);
1155 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1156 if (!pixel_format_array
)
1158 WARN("CFArrayCreateMutable failed\n");
1159 CFRelease(pixel_format_set
);
1160 CGLDestroyRendererInfo(renderer_info
);
1164 for (i
= 0; i
< rendererCount
; i
++)
1166 renderer_properties renderer
;
1168 get_renderer_properties(renderer_info
, i
, &renderer
);
1171 TRACE("renderer_properties %d:\n", i
);
1172 dump_renderer(&renderer
);
1175 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1178 CFRelease(pixel_format_set
);
1179 CGLDestroyRendererInfo(renderer_info
);
1181 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1184 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1187 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1188 for (i
= 0; i
< range
.length
; i
++)
1190 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1193 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1194 pixel_formats
[i
] = pixel_format_for_code(code
);
1195 if (pixel_formats
[i
].window
)
1196 nb_displayable_formats
++;
1199 nb_formats
= range
.length
;
1200 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1204 WARN("failed to allocate pixel format list\n");
1207 WARN("got no pixel formats\n");
1209 CFRelease(pixel_format_array
);
1214 static inline BOOL
is_valid_pixel_format(int format
)
1216 return format
> 0 && format
<= nb_formats
;
1220 static inline BOOL
is_displayable_pixel_format(int format
)
1222 return format
> 0 && format
<= nb_displayable_formats
;
1226 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1228 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1229 * format in case of probing the number of pixel formats.
1231 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1233 TRACE("Returning format %d\n", format
);
1234 return &pixel_formats
[format
- 1];
1240 static BOOL
init_gl_info(void)
1242 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1243 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1245 CGDirectDisplayID display
= CGMainDisplayID();
1246 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1247 CGLPixelFormatAttribute attribs
[] = {
1248 kCGLPFADisplayMask
, displayMask
,
1251 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1252 CGLPixelFormatAttribute core_attribs
[] =
1254 kCGLPFADisplayMask
, displayMask
,
1256 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1260 CGLPixelFormatObj pix
;
1261 GLint virtualScreens
;
1263 CGLContextObj context
;
1264 CGLContextObj old_context
= CGLGetCurrentContext();
1268 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1269 if (err
!= kCGLNoError
|| !pix
)
1271 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1275 err
= CGLCreateContext(pix
, NULL
, &context
);
1276 CGLReleasePixelFormat(pix
);
1277 if (err
!= kCGLNoError
|| !context
)
1279 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1283 err
= CGLSetCurrentContext(context
);
1284 if (err
!= kCGLNoError
)
1286 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1287 CGLReleaseContext(context
);
1291 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1292 length
= strlen(str
) + sizeof(legacy_extensions
);
1294 length
+= strlen(legacy_ext_swap_control
);
1295 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1296 strcpy(gl_info
.glExtensions
, str
);
1297 strcat(gl_info
.glExtensions
, legacy_extensions
);
1299 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1301 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1303 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1304 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1305 TRACE("GL version : %s\n", str
);
1306 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1308 CGLSetCurrentContext(old_context
);
1309 CGLReleaseContext(context
);
1311 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1312 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1313 if (err
!= kCGLNoError
|| !pix
)
1315 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1316 err
, CGLErrorString(err
));
1320 err
= CGLCreateContext(pix
, NULL
, &context
);
1321 CGLReleasePixelFormat(pix
);
1322 if (err
!= kCGLNoError
|| !context
)
1324 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1325 err
, CGLErrorString(err
));
1329 err
= CGLSetCurrentContext(context
);
1330 if (err
!= kCGLNoError
)
1332 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1333 err
, CGLErrorString(err
));
1334 CGLReleaseContext(context
);
1338 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1339 TRACE("Core context GL version: %s\n", str
);
1340 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1341 CGLSetCurrentContext(old_context
);
1342 CGLReleaseContext(context
);
1349 static int get_dc_pixel_format(HDC hdc
)
1354 if ((hwnd
= WindowFromDC(hdc
)))
1356 struct macdrv_win_data
*data
;
1358 if (!(data
= get_win_data(hwnd
)))
1360 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1364 format
= data
->pixel_format
;
1365 release_win_data(data
);
1369 struct wgl_pbuffer
*pbuffer
;
1371 EnterCriticalSection(&dc_pbuffers_section
);
1372 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1374 format
= pbuffer
->format
;
1377 WARN("no window or pbuffer for DC %p\n", hdc
);
1380 LeaveCriticalSection(&dc_pbuffers_section
);
1387 /**********************************************************************
1390 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1392 const pixel_format
*pf
;
1393 CGLPixelFormatAttribute attribs
[64];
1395 CGLPixelFormatObj pix
;
1396 GLint virtualScreens
;
1398 BOOL core
= major
>= 3;
1400 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1403 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1408 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1411 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1412 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1416 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1417 attribs
[n
++] = kCGLPFAClosestPolicy
;
1419 if (context
->renderer_id
)
1421 attribs
[n
++] = kCGLPFARendererID
;
1422 attribs
[n
++] = context
->renderer_id
;
1423 attribs
[n
++] = kCGLPFASingleRenderer
;
1424 attribs
[n
++] = kCGLPFANoRecovery
;
1427 if (pf
->accelerated
)
1429 attribs
[n
++] = kCGLPFAAccelerated
;
1430 attribs
[n
++] = kCGLPFANoRecovery
;
1434 attribs
[n
++] = kCGLPFARendererID
;
1435 attribs
[n
++] = kCGLRendererGenericFloatID
;
1438 if (pf
->double_buffer
)
1439 attribs
[n
++] = kCGLPFADoubleBuffer
;
1443 attribs
[n
++] = kCGLPFAAuxBuffers
;
1444 attribs
[n
++] = pf
->aux_buffers
;
1447 attribs
[n
++] = kCGLPFAColorSize
;
1448 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1449 attribs
[n
++] = kCGLPFAAlphaSize
;
1450 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1451 if (color_modes
[pf
->color_mode
].is_float
)
1452 attribs
[n
++] = kCGLPFAColorFloat
;
1454 attribs
[n
++] = kCGLPFADepthSize
;
1455 attribs
[n
++] = pf
->depth_bits
;
1457 attribs
[n
++] = kCGLPFAStencilSize
;
1458 attribs
[n
++] = pf
->stencil_bits
;
1461 attribs
[n
++] = kCGLPFAStereo
;
1463 if (pf
->accum_mode
&& !core
)
1465 attribs
[n
++] = kCGLPFAAccumSize
;
1466 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1469 if (pf
->pbuffer
&& !core
)
1470 attribs
[n
++] = kCGLPFAPBuffer
;
1472 if (pf
->sample_buffers
&& pf
->samples
)
1474 attribs
[n
++] = kCGLPFASampleBuffers
;
1475 attribs
[n
++] = pf
->sample_buffers
;
1476 attribs
[n
++] = kCGLPFASamples
;
1477 attribs
[n
++] = pf
->samples
;
1480 if (pf
->backing_store
)
1481 attribs
[n
++] = kCGLPFABackingStore
;
1483 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1486 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1487 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1489 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1491 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1493 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1500 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1501 if (err
!= kCGLNoError
|| !pix
)
1503 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1504 SetLastError(ERROR_INVALID_OPERATION
);
1508 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1509 CGLReleasePixelFormat(pix
);
1510 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1512 context
->cglcontext
= NULL
;
1513 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1514 SetLastError(ERROR_INVALID_OPERATION
);
1518 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1521 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1522 if (err
!= kCGLNoError
)
1523 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1525 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1528 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1529 if (err
!= kCGLNoError
)
1530 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1533 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1534 CGLReleaseContext(context
->cglcontext
);
1535 if (!context
->context
)
1537 WARN("macdrv_create_opengl_context() failed\n");
1538 SetLastError(ERROR_INVALID_OPERATION
);
1541 context
->major
= major
;
1543 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1545 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1551 /**********************************************************************
1554 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1556 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1558 struct macdrv_win_data
*data
;
1559 const pixel_format
*pf
;
1560 HWND hwnd
= WindowFromDC(hdc
);
1563 TRACE("hdc %p format %d\n", hdc
, fmt
);
1565 if (!hwnd
|| hwnd
== GetDesktopWindow())
1567 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1571 if (!(data
= get_win_data(hwnd
)))
1573 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1577 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1579 ret
= (data
->pixel_format
== fmt
);
1583 /* Check if fmt is in our list of supported formats to see if it is supported. */
1584 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1587 ERR("Invalid pixel format: %d\n", fmt
);
1593 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1597 data
->pixel_format
= fmt
;
1599 TRACE("pixel format:\n");
1600 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1601 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1602 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1603 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1604 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1605 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1606 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1607 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1608 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1609 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1610 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1611 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1612 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1613 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1617 release_win_data(data
);
1618 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) __wine_set_pixel_format(hwnd
, fmt
);
1623 /**********************************************************************
1624 * mark_contexts_for_moved_view
1626 static void mark_contexts_for_moved_view(macdrv_view view
)
1628 struct wgl_context
*context
;
1630 EnterCriticalSection(&context_section
);
1631 LIST_FOR_EACH_ENTRY(context
, &context_list
, struct wgl_context
, entry
)
1633 if (context
->draw_view
== view
)
1634 InterlockedExchange(&context
->view_moved
, TRUE
);
1636 LeaveCriticalSection(&context_section
);
1640 /**********************************************************************
1643 static BOOL
sync_context_rect(struct wgl_context
*context
)
1646 if (InterlockedCompareExchange(&context
->view_moved
, FALSE
, TRUE
))
1648 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1650 if (data
&& data
->client_cocoa_view
== context
->draw_view
)
1652 RECT rect
= data
->client_rect
;
1653 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1654 if (!EqualRect(&context
->draw_rect
, &rect
))
1656 context
->draw_rect
= rect
;
1660 release_win_data(data
);
1666 /**********************************************************************
1667 * make_context_current
1669 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1673 struct wgl_pbuffer
*pbuffer
;
1677 view
= context
->read_view
;
1678 view_rect
= context
->read_rect
;
1679 pbuffer
= context
->read_pbuffer
;
1683 sync_context_rect(context
);
1685 view
= context
->draw_view
;
1686 view_rect
= context
->draw_rect
;
1687 pbuffer
= context
->draw_pbuffer
;
1690 if (view
|| !pbuffer
)
1691 macdrv_make_context_current(context
->context
, view
, cgrect_from_rect(view_rect
));
1696 if (CGLIsEnabled(context
->cglcontext
, kCGLCESurfaceBackingSize
, &enabled
) == kCGLNoError
&& enabled
)
1697 CGLDisable(context
->cglcontext
, kCGLCESurfaceBackingSize
);
1698 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1700 CGLSetCurrentContext(context
->cglcontext
);
1705 /**********************************************************************
1708 static void sync_context(struct wgl_context
*context
)
1710 if (sync_context_rect(context
))
1711 make_context_current(context
, FALSE
);
1715 /**********************************************************************
1718 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1722 /* In theory, for single-buffered contexts, there's no such thing as a swap
1723 so the swap interval shouldn't matter. But OS X will synchronize flushes
1724 of single-buffered contexts if the interval is set to non-zero. */
1725 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1728 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1729 if (err
!= kCGLNoError
)
1730 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1732 return err
== kCGLNoError
;
1736 /**********************************************************************
1737 * sync_swap_interval
1739 static void sync_swap_interval(struct wgl_context
*context
)
1741 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1747 else if (context
->draw_hwnd
)
1749 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1752 interval
= data
->swap_interval
;
1753 release_win_data(data
);
1755 else /* window was destroyed? */
1761 set_swap_interval(context
, interval
);
1766 /**********************************************************************
1767 * get_iokit_display_property
1769 static BOOL
get_iokit_display_property(CGLRendererInfoObj renderer_info
, GLint renderer
, CFStringRef property
, GLuint
* value
)
1775 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, &accelerated
) || !accelerated
)
1777 TRACE("assuming unaccelerated renderers don't have IOKit properties\n");
1781 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPDisplayMask
, &display_mask
))
1783 WARN("failed to get kCGLRPDisplayMask\n");
1787 for (i
= 0; i
< sizeof(GLint
) * 8; i
++)
1789 GLint this_display_mask
= (GLint
)(1U << i
);
1790 if (this_display_mask
& display_mask
)
1792 CGDirectDisplayID display_id
= CGOpenGLDisplayMaskToDisplayID(this_display_mask
);
1793 io_service_t service
;
1795 uint32_t prop_value
;
1799 service
= CGDisplayIOServicePort(display_id
);
1802 WARN("CGDisplayIOServicePort(%u) failed\n", display_id
);
1806 data
= IORegistryEntrySearchCFProperty(service
, kIOServicePlane
, property
, NULL
,
1807 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1810 WARN("IORegistryEntrySearchCFProperty(%s) failed for display %u\n", debugstr_cf(property
), display_id
);
1813 if (CFGetTypeID(data
) != CFDataGetTypeID())
1815 WARN("property %s is not a data object: %s\n", debugstr_cf(property
), debugstr_cf(data
));
1819 if (CFDataGetLength(data
) != sizeof(prop_value
))
1821 WARN("%s data for display %u has unexpected length %llu\n", debugstr_cf(property
), display_id
,
1822 (unsigned long long)CFDataGetLength(data
));
1827 CFDataGetBytes(data
, CFRangeMake(0, sizeof(prop_value
)), (UInt8
*)&prop_value
);
1829 *value
= prop_value
;
1838 /**********************************************************************
1839 * create_pixel_format_for_renderer
1841 * Helper for macdrv_wglQueryRendererIntegerWINE(). Caller is
1842 * responsible for releasing the pixel format object.
1844 static CGLPixelFormatObj
create_pixel_format_for_renderer(CGLRendererInfoObj renderer_info
, GLint renderer
, BOOL core
)
1847 CGLPixelFormatAttribute attrs
[] = {
1848 kCGLPFARendererID
, 0,
1849 kCGLPFASingleRenderer
,
1850 0, 0, /* reserve spots for kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core */
1854 CGLPixelFormatObj pixel_format
;
1855 GLint virtual_screens
;
1859 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1860 attrs
[3] = kCGLPFAOpenGLProfile
;
1861 attrs
[4] = (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
;
1867 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
1870 attrs
[1] = renderer_id
;
1871 err
= CGLChoosePixelFormat(attrs
, &pixel_format
, &virtual_screens
);
1872 if (err
!= kCGLNoError
)
1873 pixel_format
= NULL
;
1874 return pixel_format
;
1878 /**********************************************************************
1879 * map_renderer_index
1881 * We can't create pixel formats for all renderers listed. For example,
1882 * in a dual-GPU system, the integrated GPU is typically unavailable
1883 * when the discrete GPU is active.
1885 * This function conceptually creates a list of "good" renderers from the
1886 * list of all renderers. It treats the input "renderer" parameter as an
1887 * index into that list of good renderers and returns the corresponding
1888 * index into the list of all renderers.
1890 static GLint
map_renderer_index(CGLRendererInfoObj renderer_info
, GLint renderer_count
, GLint renderer
)
1892 GLint good_count
, i
;
1895 for (i
= 0; i
< renderer_count
; i
++)
1897 CGLPixelFormatObj pix
= create_pixel_format_for_renderer(renderer_info
, i
, FALSE
);
1900 CGLReleasePixelFormat(pix
);
1902 if (good_count
> renderer
)
1906 TRACE("skipping bad renderer %d\n", i
);
1909 TRACE("mapped requested renderer %d to index %d\n", renderer
, i
);
1914 /**********************************************************************
1917 static const char* get_gl_string(CGLPixelFormatObj pixel_format
, GLenum name
)
1919 const char* ret
= NULL
;
1920 CGLContextObj context
, old_context
;
1923 err
= CGLCreateContext(pixel_format
, NULL
, &context
);
1924 if (err
== kCGLNoError
&& context
)
1926 old_context
= CGLGetCurrentContext();
1927 err
= CGLSetCurrentContext(context
);
1928 if (err
== kCGLNoError
)
1930 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(name
);
1931 CGLSetCurrentContext(old_context
);
1934 WARN("CGLSetCurrentContext failed: %d %s\n", err
, CGLErrorString(err
));
1935 CGLReleaseContext(context
);
1938 WARN("CGLCreateContext failed: %d %s\n", err
, CGLErrorString(err
));
1944 /**********************************************************************
1945 * get_fallback_renderer_version
1947 static void get_fallback_renderer_version(GLuint
*value
)
1949 BOOL got_it
= FALSE
;
1950 CFURLRef url
= CFURLCreateWithFileSystemPath(NULL
, CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1951 kCFURLPOSIXPathStyle
, TRUE
);
1954 CFBundleRef bundle
= CFBundleCreate(NULL
, url
);
1958 CFStringRef version
= CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleVersionKey
);
1959 if (version
&& CFGetTypeID(version
) == CFStringGetTypeID())
1961 size_t len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(version
), kCFStringEncodingUTF8
);
1962 char* buf
= HeapAlloc(GetProcessHeap(), 0, len
);
1963 if (buf
&& CFStringGetCString(version
, buf
, len
, kCFStringEncodingUTF8
))
1965 unsigned int major
, minor
, bugfix
;
1966 int count
= sscanf(buf
, "%u.%u.%u", &major
, &minor
, &bugfix
);
1978 HeapFree(GetProcessHeap(), 0, buf
);
1986 /* Use the version of the OpenGL framework from OS X 10.6, which is the
1987 earliest version that the Mac driver supports. */
1995 /**********************************************************************
1996 * parse_renderer_version
1998 * Get the renderer version from the OpenGL version string. Assumes
1999 * the string is of the form
2000 * <GL major>.<GL minor>[.<GL bugfix>] <vendor>-<major>.<minor>[.<bugfix>]
2001 * where major, minor, and bugfix are what we're interested in. This
2002 * form for the vendor specific information is not generally applicable,
2003 * but seems reliable on OS X.
2005 static BOOL
parse_renderer_version(const char* version
, GLuint
*value
)
2007 const char* p
= strchr(version
, ' ');
2009 unsigned int major
, minor
, bugfix
;
2011 if (p
) p
= strchr(p
+ 1, '-');
2012 if (!p
) return FALSE
;
2014 count
= sscanf(p
+ 1, "%u.%u.%u", &major
, &minor
, &bugfix
);
2029 /**********************************************************************
2030 * query_renderer_integer
2032 static BOOL
query_renderer_integer(CGLRendererInfoObj renderer_info
, GLint renderer
, GLenum attribute
, GLuint
*value
)
2040 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
2042 TRACE("renderer %d (ID 0x%08x) attribute 0x%04x value %p\n", renderer
, renderer_id
, attribute
, value
);
2047 case WGL_RENDERER_ACCELERATED_WINE
:
2048 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPAccelerated
, (GLint
*)value
))
2052 TRACE("WGL_RENDERER_ACCELERATED_WINE -> %u\n", *value
);
2055 case WGL_RENDERER_DEVICE_ID_WINE
:
2056 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("device-id"), value
);
2059 *value
= 0xffffffff;
2062 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> 0x%04x\n", *value
);
2065 case WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE
:
2066 case WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
:
2068 BOOL core
= (attribute
== WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE
);
2069 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, core
);
2073 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2075 CGLReleasePixelFormat(pixel_format
);
2078 unsigned int major
, minor
;
2080 if (sscanf(version
, "%u.%u", &major
, &minor
) == 2)
2091 value
[0] = value
[1] = 0;
2094 TRACE("%s -> %u.%u\n", core
? "WGL_RENDERER_OPENGL_CORE_PROFILE_VERSION_WINE" :
2095 "WGL_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_WINE", value
[0], value
[1]);
2099 case WGL_RENDERER_PREFERRED_PROFILE_WINE
:
2101 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2105 CGLReleasePixelFormat(pixel_format
);
2106 *value
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
2107 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_CORE_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2111 *value
= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
2112 TRACE("WGL_RENDERER_PREFERRED_PROFILE_WINE -> WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x%04x)\n", *value
);
2118 case WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE
:
2119 /* FIXME: no API to query this */
2122 TRACE("WGL_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_WINE -> %u\n", *value
);
2125 case WGL_RENDERER_VENDOR_ID_WINE
:
2126 ret
= get_iokit_display_property(renderer_info
, renderer
, CFSTR("vendor-id"), value
);
2129 *value
= 0xffffffff;
2132 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> 0x%04x\n", *value
);
2135 case WGL_RENDERER_VERSION_WINE
:
2137 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
2140 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
2143 const char* version
= get_gl_string(pixel_format
, GL_VERSION
);
2145 CGLReleasePixelFormat(pixel_format
);
2147 ret
= parse_renderer_version(version
, value
);
2152 get_fallback_renderer_version(value
);
2155 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
2159 case WGL_RENDERER_VIDEO_MEMORY_WINE
:
2160 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2161 err
= CGLDescribeRenderer(renderer_info
, renderer
, kCGLRPVideoMemoryMegabytes
, (GLint
*)value
);
2162 if (err
!= kCGLNoError
&& err
!= kCGLBadProperty
)
2163 WARN("CGLDescribeRenderer(kCGLRPVideoMemoryMegabytes) failed: %d %s\n", err
, CGLErrorString(err
));
2164 if (err
!= kCGLNoError
)
2167 if (get_renderer_property(renderer_info
, renderer
, kCGLRPVideoMemory
, (GLint
*)value
))
2168 *value
/= 1024 * 1024;
2173 TRACE("WGL_RENDERER_VIDEO_MEMORY_WINE -> %uMB\n", *value
);
2177 FIXME("unrecognized attribute 0x%04x\n", attribute
);
2185 /**********************************************************************
2186 * macdrv_glCopyColorTable
2188 * Hook into glCopyColorTable as part of the implementation of
2189 * wglMakeContextCurrentARB. If the context has a separate readable,
2190 * temporarily make that current, do glCopyColorTable, and then set it
2191 * back to the drawable. This is modeled after what Mesa GLX's Apple
2192 * implementation does.
2194 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
2197 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2199 if (context
->read_view
|| context
->read_pbuffer
)
2200 make_context_current(context
, TRUE
);
2202 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
2204 if (context
->read_view
|| context
->read_pbuffer
)
2205 make_context_current(context
, FALSE
);
2209 /**********************************************************************
2210 * macdrv_glCopyPixels
2212 * Hook into glCopyPixels as part of the implementation of
2213 * wglMakeContextCurrentARB. If the context has a separate readable,
2214 * temporarily make that current, do glCopyPixels, and then set it back
2215 * to the drawable. This is modeled after what Mesa GLX's Apple
2216 * implementation does.
2218 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
2220 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2222 if (context
->read_view
|| context
->read_pbuffer
)
2223 make_context_current(context
, TRUE
);
2225 pglCopyPixels(x
, y
, width
, height
, type
);
2227 if (context
->read_view
|| context
->read_pbuffer
)
2228 make_context_current(context
, FALSE
);
2232 /**********************************************************************
2235 static void macdrv_glFinish(void)
2237 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2239 sync_swap_interval(context
);
2240 sync_context(context
);
2245 /**********************************************************************
2248 static void macdrv_glFlush(void)
2250 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2252 sync_swap_interval(context
);
2253 sync_context(context
);
2255 if (skip_single_buffer_flushes
)
2257 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
2258 DWORD now
= GetTickCount();
2260 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
2261 context
->last_flush_time
, now
);
2262 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
2264 TRACE("calling glFlushRenderAPPLE()\n");
2265 pglFlushRenderAPPLE();
2270 TRACE("calling glFlush()\n");
2271 context
->last_flush_time
= now
;
2279 /**********************************************************************
2280 * macdrv_glGetString
2282 * Hook into glGetString in order to return some legacy WGL extensions
2283 * that couldn't be advertised via the standard
2284 * WGL_ARB_extensions_string mechanism. Some programs, especially
2285 * older ones, expect to find certain older extensions, such as
2286 * WGL_EXT_extensions_string itself, in the standard GL extensions
2287 * string, and won't query any other WGL extensions unless they find
2288 * that particular extension there.
2290 static const GLubyte
*macdrv_glGetString(GLenum name
)
2292 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
2293 return (const GLubyte
*)gl_info
.glExtensions
;
2295 return pglGetString(name
);
2299 /**********************************************************************
2300 * macdrv_glReadPixels
2302 * Hook into glReadPixels as part of the implementation of
2303 * wglMakeContextCurrentARB. If the context has a separate readable,
2304 * temporarily make that current, do glReadPixels, and then set it back
2305 * to the drawable. This is modeled after what Mesa GLX's Apple
2306 * implementation does.
2308 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2309 GLenum format
, GLenum type
, void *pixels
)
2311 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2313 if (context
->read_view
|| context
->read_pbuffer
)
2314 make_context_current(context
, TRUE
);
2316 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2318 if (context
->read_view
|| context
->read_pbuffer
)
2319 make_context_current(context
, FALSE
);
2323 /**********************************************************************
2326 * Hook into glViewport as an opportunity to update the OpenGL context
2327 * if necessary. This is modeled after what Mesa GLX's Apple
2328 * implementation does.
2330 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2332 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2334 sync_context(context
);
2335 macdrv_update_opengl_context(context
->context
);
2336 pglViewport(x
, y
, width
, height
);
2340 /***********************************************************************
2341 * macdrv_wglBindTexImageARB
2343 * WGL_ARB_render_texture: wglBindTexImageARB
2345 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2347 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2351 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
2353 if (pbuffer
->no_texture
)
2355 SetLastError(ERROR_INVALID_OPERATION
);
2359 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
2360 opengl_funcs
.gl
.p_glFlush();
2364 case WGL_FRONT_LEFT_ARB
:
2365 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2366 source
= GL_FRONT_LEFT
;
2370 case WGL_FRONT_RIGHT_ARB
:
2371 source
= GL_FRONT_RIGHT
;
2373 case WGL_BACK_LEFT_ARB
:
2374 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
2375 source
= GL_BACK_LEFT
;
2379 case WGL_BACK_RIGHT_ARB
:
2380 source
= GL_BACK_RIGHT
;
2382 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
2383 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
2384 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
2385 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
2393 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
2394 SetLastError(ERROR_INVALID_DATA
);
2398 WARN("unknown source buffer 0x%x\n", iBuffer
);
2399 SetLastError(ERROR_INVALID_DATA
);
2403 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
2404 if (err
!= kCGLNoError
)
2406 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2407 SetLastError(ERROR_INVALID_OPERATION
);
2415 /***********************************************************************
2416 * macdrv_wglChoosePixelFormatARB
2418 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2420 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2421 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2422 int *piFormats
, UINT
*nNumFormats
)
2424 pixel_format pf
, valid
;
2426 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2427 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2432 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2433 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2435 FIXME("unused pfAttribFList\n");
2437 memset(&pf
, 0, sizeof(pf
));
2438 memset(&valid
, 0, sizeof(valid
));
2439 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2440 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2444 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2447 int value
= iptr
[1];
2449 TRACE("%s\n", debugstr_attrib(attr
, value
));
2453 case WGL_DRAW_TO_WINDOW_ARB
:
2454 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2455 pf
.window
= (value
!= 0);
2459 case WGL_DRAW_TO_BITMAP_ARB
:
2462 case WGL_ACCELERATION_ARB
:
2463 if (value
== WGL_FULL_ACCELERATION_ARB
)
2465 else if (value
== WGL_NO_ACCELERATION_ARB
)
2469 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2470 pf
.accelerated
= value
;
2471 valid
.accelerated
= 1;
2474 case WGL_NEED_PALETTE_ARB
:
2475 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2476 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2477 if (value
) goto cant_match
;
2480 case WGL_SWAP_METHOD_ARB
:
2481 if (value
== WGL_SWAP_COPY_ARB
)
2483 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2487 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2488 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2489 pf
.backing_store
= value
;
2490 valid
.backing_store
= 1;
2493 case WGL_NUMBER_OVERLAYS_ARB
:
2494 case WGL_NUMBER_UNDERLAYS_ARB
:
2495 if (value
) goto cant_match
;
2498 case WGL_SHARE_DEPTH_ARB
:
2499 case WGL_SHARE_STENCIL_ARB
:
2500 case WGL_SHARE_ACCUM_ARB
:
2504 case WGL_SUPPORT_GDI_ARB
:
2505 if (value
) goto cant_match
;
2508 case WGL_SUPPORT_OPENGL_ARB
:
2509 if (!value
) goto cant_match
;
2512 case WGL_DOUBLE_BUFFER_ARB
:
2513 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2514 pf
.double_buffer
= (value
!= 0);
2515 valid
.double_buffer
= 1;
2516 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2519 case WGL_STEREO_ARB
:
2520 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2521 pf
.stereo
= (value
!= 0);
2525 case WGL_PIXEL_TYPE_ARB
:
2526 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2528 else if (value
== WGL_TYPE_RGBA_ARB
)
2532 /* Mac contexts don't support rendering to unsigned floating
2533 point formats, even if GL_EXT_packed_float is supported.
2534 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2537 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2538 if (srgb
&& value
) goto cant_match
;
2539 float_color
= value
;
2542 case WGL_COLOR_BITS_ARB
:
2543 if (color_bits
< value
) color_bits
= value
;
2546 case WGL_RED_BITS_ARB
:
2547 if (srgb
&& value
> 8) goto cant_match
;
2548 if (red_bits
< value
) red_bits
= value
;
2551 case WGL_GREEN_BITS_ARB
:
2552 if (srgb
&& value
> 8) goto cant_match
;
2553 if (green_bits
< value
) green_bits
= value
;
2556 case WGL_BLUE_BITS_ARB
:
2557 if (srgb
&& value
> 8) goto cant_match
;
2558 if (blue_bits
< value
) blue_bits
= value
;
2561 case WGL_ALPHA_BITS_ARB
:
2562 if (alpha_bits
< value
) alpha_bits
= value
;
2565 case WGL_ACCUM_BITS_ARB
:
2566 if (accum_bits
< value
) accum_bits
= value
;
2569 case WGL_ACCUM_RED_BITS_ARB
:
2570 if (accum_red_bits
< value
) accum_red_bits
= value
;
2573 case WGL_ACCUM_GREEN_BITS_ARB
:
2574 if (accum_green_bits
< value
) accum_green_bits
= value
;
2577 case WGL_ACCUM_BLUE_BITS_ARB
:
2578 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2581 case WGL_ACCUM_ALPHA_BITS_ARB
:
2582 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2585 case WGL_DEPTH_BITS_ARB
:
2586 if (value
> 255) goto cant_match
;
2587 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2590 case WGL_STENCIL_BITS_ARB
:
2591 if (value
> 255) goto cant_match
;
2592 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2595 case WGL_AUX_BUFFERS_ARB
:
2596 if (value
> 7) goto cant_match
;
2597 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2600 case WGL_SAMPLE_BUFFERS_ARB
:
2601 if (value
> 1) goto cant_match
;
2602 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2605 case WGL_SAMPLES_ARB
:
2606 if (value
> 31) goto cant_match
;
2607 if (pf
.samples
< value
) pf
.samples
= value
;
2610 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2611 /* sRGB is only supported for 8-bit integer color components */
2612 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2617 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2618 case WGL_RED_SHIFT_ARB
:
2619 case WGL_GREEN_SHIFT_ARB
:
2620 case WGL_BLUE_SHIFT_ARB
:
2621 case WGL_ALPHA_SHIFT_ARB
:
2622 case WGL_TRANSPARENT_ARB
:
2623 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2624 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2625 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2626 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2627 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2631 case WGL_DRAW_TO_PBUFFER_ARB
:
2632 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2633 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2634 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2635 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2636 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2637 pf
.pbuffer
= (value
!= 0);
2639 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2645 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2650 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",
2651 valid
.window
? (pf
.window
? "1" : "0") : "?",
2652 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2653 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2655 float_color
== -1 ? "?" : float_color
? "f" : "",
2669 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2670 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2671 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2675 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2677 const struct color_mode
*mode
;
2679 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2680 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2681 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2682 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2683 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2684 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2686 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2687 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2688 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2689 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2690 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2692 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2693 /* If the mode doesn't have alpha, check requested color bits against
2694 bits per pixel instead of the mode's color bits. On Windows, color
2695 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2696 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2697 expects that to match such a pixel format, we need to accommodate that. */
2698 if (mode
->alpha_bits
)
2700 if (mode
->color_bits
< color_bits
)
2705 if (mode
->bits_per_pixel
< color_bits
)
2708 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2709 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2711 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2712 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2715 if (pixel_formats
[i
].accum_mode
)
2717 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2718 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2719 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2720 mode
->alpha_bits
< accum_alpha_bits
)
2723 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2726 piFormats
[found
++] = i
+ 1;
2727 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2731 *nNumFormats
= found
;
2737 /***********************************************************************
2738 * macdrv_wglCreateContextAttribsARB
2740 * WGL_ARB_create_context: wglCreateContextAttribsARB
2742 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2743 struct wgl_context
*share_context
,
2744 const int *attrib_list
)
2747 struct wgl_context
*context
;
2749 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2751 GLint renderer_id
= 0;
2753 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2755 format
= get_dc_pixel_format(hdc
);
2757 if (!is_valid_pixel_format(format
))
2759 ERR("Invalid pixel format %d, expect problems!\n", format
);
2760 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2764 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2767 int value
= iptr
[1];
2769 TRACE("%s\n", debugstr_attrib(attr
, value
));
2773 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2777 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2781 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2782 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2785 case WGL_CONTEXT_FLAGS_ARB
:
2787 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2788 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2789 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2792 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2793 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2794 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2796 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2797 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2803 case WGL_RENDERER_ID_WINE
:
2806 CGLRendererInfoObj renderer_info
;
2807 GLint renderer_count
, temp
;
2809 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
2810 if (err
!= kCGLNoError
)
2812 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
2813 SetLastError(ERROR_GEN_FAILURE
);
2817 value
= map_renderer_index(renderer_info
, renderer_count
, value
);
2819 if (value
>= renderer_count
)
2821 WARN("WGL_RENDERER_ID_WINE renderer %d exceeds count (%d)\n", value
, renderer_count
);
2822 CGLDestroyRendererInfo(renderer_info
);
2823 SetLastError(ERROR_INVALID_PARAMETER
);
2827 if (!get_renderer_property(renderer_info
, value
, kCGLRPRendererID
, &temp
))
2829 WARN("WGL_RENDERER_ID_WINE failed to get ID of renderer %d\n", value
);
2830 CGLDestroyRendererInfo(renderer_info
);
2831 SetLastError(ERROR_GEN_FAILURE
);
2835 CGLDestroyRendererInfo(renderer_info
);
2837 if (renderer_id
&& temp
!= renderer_id
)
2839 WARN("WGL_RENDERER_ID_WINE requested two different renderers (0x%08x vs. 0x%08x)\n", renderer_id
, temp
);
2840 SetLastError(ERROR_INVALID_PARAMETER
);
2848 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2849 SetLastError(ERROR_INVALID_PARAMETER
);
2854 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2855 (major
== 4 && (minor
== 0 || minor
== 1)))
2857 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2859 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2860 SetLastError(ERROR_INVALID_VERSION_ARB
);
2863 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2865 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2866 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2869 if (major
> gl_info
.max_major
||
2870 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2872 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2874 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2879 else if (major
>= 3)
2881 WARN("Profile version %u.%u not supported\n", major
, minor
);
2882 SetLastError(ERROR_INVALID_VERSION_ARB
);
2885 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2886 (major
== 2 && (minor
< 0 || minor
> 1)))
2888 WARN("Invalid GL version requested\n");
2889 SetLastError(ERROR_INVALID_VERSION_ARB
);
2892 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2894 WARN("Forward compatible context requested for GL version < 3\n");
2895 SetLastError(ERROR_INVALID_VERSION_ARB
);
2899 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
2901 context
->format
= format
;
2902 context
->renderer_id
= renderer_id
;
2903 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2905 HeapFree(GetProcessHeap(), 0, context
);
2909 EnterCriticalSection(&context_section
);
2910 list_add_tail(&context_list
, &context
->entry
);
2911 LeaveCriticalSection(&context_section
);
2917 /**********************************************************************
2918 * macdrv_wglCreatePbufferARB
2920 * WGL_ARB_pbuffer: wglCreatePbufferARB
2922 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2923 const int *piAttribList
)
2925 struct wgl_pbuffer
* pbuffer
;
2927 GLenum internalFormat
= 0;
2930 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2931 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2933 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2935 WARN("invalid pixel format %d\n", iPixelFormat
);
2936 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2940 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2941 pbuffer
->format
= iPixelFormat
;
2943 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2945 int attr
= piAttribList
[0];
2946 int value
= piAttribList
[1];
2950 case WGL_PBUFFER_LARGEST_ARB
:
2951 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2954 case WGL_TEXTURE_FORMAT_ARB
:
2957 case WGL_TEXTURE_RGBA_ARB
:
2958 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2959 internalFormat
= GL_RGBA
;
2961 case WGL_TEXTURE_RGB_ARB
:
2962 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2963 internalFormat
= GL_RGB
;
2965 case WGL_NO_TEXTURE_ARB
:
2966 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2970 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2971 SetLastError(ERROR_INVALID_DATA
);
2976 case WGL_TEXTURE_TARGET_ARB
:
2980 case WGL_NO_TEXTURE_ARB
:
2981 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2984 case WGL_TEXTURE_CUBE_MAP_ARB
:
2985 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2986 target
= GL_TEXTURE_CUBE_MAP
;
2987 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2989 case WGL_TEXTURE_1D_ARB
:
2990 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2991 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2993 case WGL_TEXTURE_2D_ARB
:
2994 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2995 target
= GL_TEXTURE_2D
;
2997 case WGL_TEXTURE_RECTANGLE_NV
:
2998 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2999 target
= GL_TEXTURE_RECTANGLE
;
3002 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
3003 SetLastError(ERROR_INVALID_DATA
);
3008 case WGL_MIPMAP_TEXTURE_ARB
:
3009 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
3010 pbuffer
->max_level
= 0;
3013 int size
= min(iWidth
, iHeight
) / 2;
3016 pbuffer
->max_level
++;
3023 WARN("unknown attribute 0x%x\n", attr
);
3024 SetLastError(ERROR_INVALID_DATA
);
3029 if (!target
|| !internalFormat
)
3031 pbuffer
->no_texture
= TRUE
;
3032 /* no actual way to turn off ability to texture; use most permissive target */
3033 target
= GL_TEXTURE_RECTANGLE
;
3034 internalFormat
= GL_RGB
;
3037 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
3038 if (err
!= kCGLNoError
)
3040 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
3041 pbuffer
->pbuffer
= NULL
;
3042 if (err
== kCGLBadAlloc
)
3043 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
3045 SetLastError(ERROR_INVALID_DATA
);
3049 if (!pbuffer
->pbuffer
)
3051 HeapFree(GetProcessHeap(), 0, pbuffer
);
3055 TRACE(" -> %p\n", pbuffer
);
3060 /**********************************************************************
3061 * macdrv_wglDestroyPbufferARB
3063 * WGL_ARB_pbuffer: wglDestroyPbufferARB
3065 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
3067 TRACE("pbuffer %p\n", pbuffer
);
3068 if (pbuffer
&& pbuffer
->pbuffer
)
3069 CGLReleasePBuffer(pbuffer
->pbuffer
);
3070 HeapFree(GetProcessHeap(), 0, pbuffer
);
3075 /**********************************************************************
3076 * macdrv_wglGetExtensionsStringARB
3078 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
3080 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
3082 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
3083 this can be specific to the CGL renderer like we're supposed to do. */
3084 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3085 return gl_info
.wglExtensions
;
3089 /**********************************************************************
3090 * macdrv_wglGetExtensionsStringEXT
3092 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3094 static const char *macdrv_wglGetExtensionsStringEXT(void)
3096 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
3097 return gl_info
.wglExtensions
;
3101 /**********************************************************************
3102 * macdrv_wglGetPbufferDCARB
3104 * WGL_ARB_pbuffer: wglGetPbufferDCARB
3106 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
3109 struct wgl_pbuffer
*prev
;
3111 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
3114 EnterCriticalSection(&dc_pbuffers_section
);
3115 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3118 CGLReleasePBuffer(prev
->pbuffer
);
3119 HeapFree(GetProcessHeap(), 0, prev
);
3121 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
3122 LeaveCriticalSection(&dc_pbuffers_section
);
3124 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
3129 /**********************************************************************
3130 * macdrv_wglGetPixelFormatAttribivARB
3132 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
3134 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3135 UINT nAttributes
, const int *piAttributes
, int *piValues
)
3137 const pixel_format
*pf
;
3140 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
3141 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
3143 if (!nAttributes
) return GL_TRUE
;
3145 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
3147 piValues
[0] = nb_formats
;
3148 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
3152 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
3155 WARN("invalid pixel format %d\n", iPixelFormat
);
3156 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3160 for (i
= 0; i
< nAttributes
; ++i
)
3162 switch (piAttributes
[i
])
3164 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
3165 piValues
[i
] = nb_formats
;
3168 case WGL_DRAW_TO_WINDOW_ARB
:
3169 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
3172 case WGL_DRAW_TO_BITMAP_ARB
:
3173 piValues
[i
] = GL_FALSE
;
3176 case WGL_ACCELERATION_ARB
:
3177 if (iLayerPlane
) goto invalid_layer
;
3178 if (pf
->accelerated
)
3179 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
3181 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
3184 case WGL_NEED_PALETTE_ARB
:
3185 case WGL_NEED_SYSTEM_PALETTE_ARB
:
3186 case WGL_SWAP_LAYER_BUFFERS_ARB
:
3187 piValues
[i
] = GL_FALSE
;
3190 case WGL_SWAP_METHOD_ARB
:
3191 if (pf
->double_buffer
&& pf
->backing_store
)
3192 piValues
[i
] = WGL_SWAP_COPY_ARB
;
3194 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
3197 case WGL_NUMBER_OVERLAYS_ARB
:
3198 case WGL_NUMBER_UNDERLAYS_ARB
:
3202 case WGL_TRANSPARENT_ARB
:
3203 if (iLayerPlane
) goto invalid_layer
;
3204 piValues
[i
] = GL_FALSE
;
3207 case WGL_TRANSPARENT_RED_VALUE_ARB
:
3208 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
3209 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
3210 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
3211 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
3212 if (iLayerPlane
) goto invalid_layer
;
3216 case WGL_SHARE_DEPTH_ARB
:
3217 case WGL_SHARE_STENCIL_ARB
:
3218 case WGL_SHARE_ACCUM_ARB
:
3219 if (iLayerPlane
) goto invalid_layer
;
3220 piValues
[i
] = GL_TRUE
;
3223 case WGL_SUPPORT_GDI_ARB
:
3224 if (iLayerPlane
) goto invalid_layer
;
3225 piValues
[i
] = GL_FALSE
;
3228 case WGL_SUPPORT_OPENGL_ARB
:
3229 if (iLayerPlane
) goto invalid_layer
;
3230 piValues
[i
] = GL_TRUE
;
3233 case WGL_DOUBLE_BUFFER_ARB
:
3234 if (iLayerPlane
) goto invalid_layer
;
3235 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
3238 case WGL_STEREO_ARB
:
3239 if (iLayerPlane
) goto invalid_layer
;
3240 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
3243 case WGL_PIXEL_TYPE_ARB
:
3244 if (iLayerPlane
) goto invalid_layer
;
3245 if (color_modes
[pf
->color_mode
].is_float
)
3246 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
3248 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
3249 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
3250 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
3251 However, Mac contexts don't support rendering to unsigned floating-point
3252 formats, even when GL_EXT_packed_float is supported. */
3255 case WGL_COLOR_BITS_ARB
:
3256 if (iLayerPlane
) goto invalid_layer
;
3257 /* If the mode doesn't have alpha, return bits per pixel instead
3258 of color bits. On Windows, color bits sometimes exceeds r+g+b
3259 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
3260 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
3261 pixel format, we need to accommodate that. */
3262 if (color_modes
[pf
->color_mode
].alpha_bits
)
3263 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
3265 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
3268 case WGL_RED_BITS_ARB
:
3269 if (iLayerPlane
) goto invalid_layer
;
3270 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
3273 case WGL_RED_SHIFT_ARB
:
3274 if (iLayerPlane
) goto invalid_layer
;
3275 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
3278 case WGL_GREEN_BITS_ARB
:
3279 if (iLayerPlane
) goto invalid_layer
;
3280 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
3283 case WGL_GREEN_SHIFT_ARB
:
3284 if (iLayerPlane
) goto invalid_layer
;
3285 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
3288 case WGL_BLUE_BITS_ARB
:
3289 if (iLayerPlane
) goto invalid_layer
;
3290 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
3293 case WGL_BLUE_SHIFT_ARB
:
3294 if (iLayerPlane
) goto invalid_layer
;
3295 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
3298 case WGL_ALPHA_BITS_ARB
:
3299 if (iLayerPlane
) goto invalid_layer
;
3300 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
3303 case WGL_ALPHA_SHIFT_ARB
:
3304 if (iLayerPlane
) goto invalid_layer
;
3305 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
3308 case WGL_ACCUM_BITS_ARB
:
3309 if (iLayerPlane
) goto invalid_layer
;
3311 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3316 case WGL_ACCUM_RED_BITS_ARB
:
3317 if (iLayerPlane
) goto invalid_layer
;
3319 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
3324 case WGL_ACCUM_GREEN_BITS_ARB
:
3325 if (iLayerPlane
) goto invalid_layer
;
3327 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
3332 case WGL_ACCUM_BLUE_BITS_ARB
:
3333 if (iLayerPlane
) goto invalid_layer
;
3335 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
3340 case WGL_ACCUM_ALPHA_BITS_ARB
:
3341 if (iLayerPlane
) goto invalid_layer
;
3343 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
3348 case WGL_DEPTH_BITS_ARB
:
3349 if (iLayerPlane
) goto invalid_layer
;
3350 piValues
[i
] = pf
->depth_bits
;
3353 case WGL_STENCIL_BITS_ARB
:
3354 if (iLayerPlane
) goto invalid_layer
;
3355 piValues
[i
] = pf
->stencil_bits
;
3358 case WGL_AUX_BUFFERS_ARB
:
3359 if (iLayerPlane
) goto invalid_layer
;
3360 piValues
[i
] = pf
->aux_buffers
;
3363 case WGL_SAMPLE_BUFFERS_ARB
:
3364 if (iLayerPlane
) goto invalid_layer
;
3365 piValues
[i
] = pf
->sample_buffers
;
3368 case WGL_SAMPLES_ARB
:
3369 if (iLayerPlane
) goto invalid_layer
;
3370 piValues
[i
] = pf
->samples
;
3373 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
3374 if (iLayerPlane
) goto invalid_layer
;
3375 /* sRGB is only supported for 8-bit integer color components */
3376 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
3377 color_modes
[pf
->color_mode
].green_bits
== 8 &&
3378 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
3379 !color_modes
[pf
->color_mode
].is_float
)
3380 piValues
[i
] = GL_TRUE
;
3382 piValues
[i
] = GL_FALSE
;
3385 case WGL_DRAW_TO_PBUFFER_ARB
:
3386 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
3387 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
3388 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
3391 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
3392 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
3393 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
3396 case WGL_MAX_PBUFFER_WIDTH_ARB
:
3397 piValues
[i
] = gl_info
.max_viewport_dims
[0];
3400 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
3401 piValues
[i
] = gl_info
.max_viewport_dims
[1];
3404 case WGL_MAX_PBUFFER_PIXELS_ARB
:
3405 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
3409 WARN("invalid attribute %x\n", piAttributes
[i
]);
3413 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
3419 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
3424 /**********************************************************************
3425 * macdrv_wglGetPixelFormatAttribfvARB
3427 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
3429 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
3430 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
3435 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
3436 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
3438 /* Allocate a temporary array to store integer values */
3439 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
3442 ERR("couldn't allocate %d array\n", nAttributes
);
3446 /* Piggy-back on wglGetPixelFormatAttribivARB */
3447 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
3452 /* Convert integer values to float. Should also check for attributes
3453 that can give decimal values here */
3454 for (i
= 0; i
< nAttributes
; i
++)
3455 pfValues
[i
] = attr
[i
];
3458 HeapFree(GetProcessHeap(), 0, attr
);
3463 /**********************************************************************
3464 * macdrv_wglGetSwapIntervalEXT
3466 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3468 static int macdrv_wglGetSwapIntervalEXT(void)
3470 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3471 struct macdrv_win_data
*data
;
3477 if ((data
= get_win_data(context
->draw_hwnd
)))
3479 value
= data
->swap_interval
;
3480 release_win_data(data
);
3482 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3483 set_swap_interval(context
, allow_vsync
? value
: 0);
3487 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3488 if (err
!= kCGLNoError
)
3490 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3491 err
, CGLErrorString(err
));
3500 /***********************************************************************
3501 * macdrv_wglMakeContextCurrentARB
3503 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3505 * This is not supported directly by OpenGL on the Mac. We emulate it
3506 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3507 * temporarily swap the drawable. This follows the technique used in
3508 * the implementation of Mesa GLX for Apple.
3510 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3512 struct macdrv_win_data
*data
;
3515 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3516 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3520 macdrv_make_context_current(NULL
, NULL
, CGRectNull
);
3521 NtCurrentTeb()->glContext
= NULL
;
3525 if ((hwnd
= WindowFromDC(draw_hdc
)))
3527 if (!(data
= get_win_data(hwnd
)))
3529 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3533 if (!data
->pixel_format
)
3535 WARN("no pixel format set\n");
3536 release_win_data(data
);
3537 SetLastError(ERROR_INVALID_HANDLE
);
3540 if (context
->format
!= data
->pixel_format
)
3542 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3543 release_win_data(data
);
3544 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3548 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
)
3549 set_swap_interval(context
, allow_vsync
? data
->swap_interval
: 0);
3551 context
->draw_hwnd
= hwnd
;
3552 context
->draw_view
= data
->client_cocoa_view
;
3553 context
->draw_rect
= data
->client_rect
;
3554 OffsetRect(&context
->draw_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3555 context
->draw_pbuffer
= NULL
;
3556 release_win_data(data
);
3560 struct wgl_pbuffer
*pbuffer
;
3562 EnterCriticalSection(&dc_pbuffers_section
);
3563 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3566 if (context
->format
!= pbuffer
->format
)
3568 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3569 LeaveCriticalSection(&dc_pbuffers_section
);
3570 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3574 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
)
3575 set_swap_interval(context
, 0);
3579 WARN("no window or pbuffer for DC\n");
3580 LeaveCriticalSection(&dc_pbuffers_section
);
3581 SetLastError(ERROR_INVALID_HANDLE
);
3585 context
->draw_hwnd
= NULL
;
3586 context
->draw_view
= NULL
;
3587 context
->draw_pbuffer
= pbuffer
;
3588 LeaveCriticalSection(&dc_pbuffers_section
);
3591 context
->read_view
= NULL
;
3592 context
->read_pbuffer
= NULL
;
3593 if (read_hdc
&& read_hdc
!= draw_hdc
)
3595 if ((hwnd
= WindowFromDC(read_hdc
)))
3597 if ((data
= get_win_data(hwnd
)))
3599 if (data
->client_cocoa_view
!= context
->draw_view
)
3601 context
->read_view
= data
->client_cocoa_view
;
3602 context
->read_rect
= data
->client_rect
;
3603 OffsetRect(&context
->read_rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
3605 release_win_data(data
);
3610 EnterCriticalSection(&dc_pbuffers_section
);
3611 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3612 LeaveCriticalSection(&dc_pbuffers_section
);
3616 TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
3617 context
->draw_view
, wine_dbgstr_rect(&context
->draw_rect
), context
->draw_pbuffer
,
3618 context
->read_view
, wine_dbgstr_rect(&context
->read_rect
), context
->read_pbuffer
, context
->format
);
3620 make_context_current(context
, FALSE
);
3621 context
->has_been_current
= TRUE
;
3622 NtCurrentTeb()->glContext
= context
;
3628 /**********************************************************************
3629 * macdrv_wglQueryCurrentRendererIntegerWINE
3631 * WGL_WINE_query_renderer: wglQueryCurrentRendererIntegerWINE
3633 static BOOL
macdrv_wglQueryCurrentRendererIntegerWINE(GLenum attribute
, GLuint
*value
)
3636 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3637 CGLPixelFormatObj pixel_format
;
3639 GLint virtual_screen
;
3641 GLint pf_renderer_id
;
3642 CGLRendererInfoObj renderer_info
;
3643 GLint renderer_count
;
3646 TRACE("context %p/%p/%p attribute 0x%04x value %p\n", context
, (context
? context
->context
: NULL
),
3647 (context
? context
->cglcontext
: NULL
), attribute
, value
);
3649 if (attribute
== WGL_RENDERER_VERSION_WINE
)
3651 if (!parse_renderer_version((const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
), value
))
3652 get_fallback_renderer_version(value
);
3653 TRACE("WGL_RENDERER_VERSION_WINE -> %u.%u.%u\n", value
[0], value
[1], value
[2]);
3657 pixel_format
= CGLGetPixelFormat(context
->cglcontext
);
3658 err
= CGLGetVirtualScreen(context
->cglcontext
, &virtual_screen
);
3659 if (err
!= kCGLNoError
)
3661 WARN("CGLGetVirtualScreen failed: %d %s\n", err
, CGLErrorString(err
));
3665 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFADisplayMask
, &display_mask
);
3666 if (err
!= kCGLNoError
)
3668 WARN("CGLDescribePixelFormat(kCGLPFADisplayMask) failed: %d %s\n", err
, CGLErrorString(err
));
3672 err
= CGLDescribePixelFormat(pixel_format
, virtual_screen
, kCGLPFARendererID
, &pf_renderer_id
);
3673 if (err
!= kCGLNoError
)
3675 WARN("CGLDescribePixelFormat(kCGLPFARendererID) failed: %d %s\n", err
, CGLErrorString(err
));
3679 err
= CGLQueryRendererInfo(display_mask
, &renderer_info
, &renderer_count
);
3680 if (err
!= kCGLNoError
)
3682 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3686 for (renderer
= 0; renderer
< renderer_count
; renderer
++)
3690 if (!get_renderer_property(renderer_info
, renderer
, kCGLRPRendererID
, &renderer_id
))
3693 if (renderer_id
== pf_renderer_id
)
3695 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3700 if (renderer
>= renderer_count
)
3701 ERR("failed to find renderer ID 0x%08x for display mask 0x%08x\n", pf_renderer_id
, display_mask
);
3703 CGLDestroyRendererInfo(renderer_info
);
3708 /**********************************************************************
3709 * macdrv_wglQueryCurrentRendererStringWINE
3711 * WGL_WINE_query_renderer: wglQueryCurrentRendererStringWINE
3713 static const char *macdrv_wglQueryCurrentRendererStringWINE(GLenum attribute
)
3715 const char* ret
= NULL
;
3716 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3718 TRACE("context %p/%p/%p attribute 0x%04x\n", context
, (context
? context
->context
: NULL
),
3719 (context
? context
->cglcontext
: NULL
), attribute
);
3723 case WGL_RENDERER_DEVICE_ID_WINE
:
3725 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_RENDERER
);
3726 TRACE("WGL_RENDERER_DEVICE_ID_WINE -> %s\n", debugstr_a(ret
));
3730 case WGL_RENDERER_VENDOR_ID_WINE
:
3732 ret
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VENDOR
);
3733 TRACE("WGL_RENDERER_VENDOR_ID_WINE -> %s\n", debugstr_a(ret
));
3738 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3746 /**********************************************************************
3747 * macdrv_wglQueryPbufferARB
3749 * WGL_ARB_pbuffer: wglQueryPbufferARB
3751 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3757 GLenum internalFormat
;
3760 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3762 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3763 if (err
!= kCGLNoError
)
3765 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3766 SetLastError(ERROR_INVALID_HANDLE
);
3772 case WGL_PBUFFER_WIDTH_ARB
:
3775 case WGL_PBUFFER_HEIGHT_ARB
:
3778 case WGL_PBUFFER_LOST_ARB
:
3779 /* Mac PBuffers can't be lost */
3780 *piValue
= GL_FALSE
;
3782 case WGL_TEXTURE_FORMAT_ARB
:
3783 if (pbuffer
->no_texture
)
3784 *piValue
= WGL_NO_TEXTURE_ARB
;
3785 else switch (internalFormat
)
3788 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3792 *piValue
= WGL_TEXTURE_RGB_ARB
;
3796 case WGL_TEXTURE_TARGET_ARB
:
3797 if (pbuffer
->no_texture
)
3798 *piValue
= WGL_NO_TEXTURE_ARB
;
3799 else switch (target
)
3801 case GL_TEXTURE_CUBE_MAP
:
3802 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3805 *piValue
= WGL_TEXTURE_2D_ARB
;
3807 case GL_TEXTURE_RECTANGLE
:
3809 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3813 case WGL_MIPMAP_TEXTURE_ARB
:
3814 *piValue
= (pbuffer
->max_level
> 0);
3816 case WGL_MIPMAP_LEVEL_ARB
:
3817 *piValue
= pbuffer
->level
;
3819 case WGL_CUBE_MAP_FACE_ARB
:
3820 switch (pbuffer
->face
)
3822 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3824 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3826 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3827 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3829 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3830 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3833 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3835 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3836 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3838 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3839 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3844 WARN("invalid attribute 0x%x\n", iAttribute
);
3845 SetLastError(ERROR_INVALID_DATA
);
3853 /**********************************************************************
3854 * macdrv_wglQueryRendererIntegerWINE
3856 * WGL_WINE_query_renderer: wglQueryRendererIntegerWINE
3858 static BOOL
macdrv_wglQueryRendererIntegerWINE(HDC dc
, GLint renderer
, GLenum attribute
, GLuint
*value
)
3861 CGLRendererInfoObj renderer_info
;
3862 GLint renderer_count
;
3865 TRACE("dc %p renderer %d attribute 0x%04x value %p\n", dc
, renderer
, attribute
, value
);
3867 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3868 if (err
!= kCGLNoError
)
3870 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3874 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3876 if (renderer
< renderer_count
)
3877 ret
= query_renderer_integer(renderer_info
, renderer
, attribute
, value
);
3879 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3881 CGLDestroyRendererInfo(renderer_info
);
3886 /**********************************************************************
3887 * macdrv_wglQueryRendererStringWINE
3889 * WGL_WINE_query_renderer: wglQueryRendererStringWINE
3891 static const char *macdrv_wglQueryRendererStringWINE(HDC dc
, GLint renderer
, GLenum attribute
)
3893 const char* ret
= NULL
;
3894 CGLRendererInfoObj renderer_info
;
3895 GLint renderer_count
;
3898 TRACE("dc %p renderer %d attribute 0x%04x\n", dc
, renderer
, attribute
);
3900 err
= CGLQueryRendererInfo(active_displays_mask(), &renderer_info
, &renderer_count
);
3901 if (err
!= kCGLNoError
)
3903 WARN("CGLQueryRendererInfo failed: %d %s\n", err
, CGLErrorString(err
));
3907 renderer
= map_renderer_index(renderer_info
, renderer_count
, renderer
);
3909 if (renderer
>= renderer_count
)
3911 TRACE("requested information for renderer %d exceeding count %d\n", renderer
, renderer_count
);
3917 case WGL_RENDERER_DEVICE_ID_WINE
:
3918 case WGL_RENDERER_VENDOR_ID_WINE
:
3920 BOOL device
= (attribute
== WGL_RENDERER_DEVICE_ID_WINE
);
3921 CGLPixelFormatObj pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, TRUE
);
3924 pixel_format
= create_pixel_format_for_renderer(renderer_info
, renderer
, FALSE
);
3927 ret
= get_gl_string(pixel_format
, device
? GL_RENDERER
: GL_VENDOR
);
3928 CGLReleasePixelFormat(pixel_format
);
3931 TRACE("%s -> %s\n", device
? "WGL_RENDERER_DEVICE_ID_WINE" : "WGL_RENDERER_VENDOR_ID_WINE", debugstr_a(ret
));
3936 FIXME("unrecognized attribute 0x%04x\n", attribute
);
3941 CGLDestroyRendererInfo(renderer_info
);
3946 /**********************************************************************
3947 * macdrv_wglReleasePbufferDCARB
3949 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3951 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3953 struct wgl_pbuffer
*prev
;
3955 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3957 EnterCriticalSection(&dc_pbuffers_section
);
3959 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3962 if (prev
!= pbuffer
)
3963 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3964 CGLReleasePBuffer(prev
->pbuffer
);
3965 HeapFree(GetProcessHeap(), 0, prev
);
3966 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3970 LeaveCriticalSection(&dc_pbuffers_section
);
3972 return hdc
&& DeleteDC(hdc
);
3976 /**********************************************************************
3977 * macdrv_wglReleaseTexImageARB
3979 * WGL_ARB_render_texture: wglReleaseTexImageARB
3981 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3983 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3986 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3988 if (pbuffer
->no_texture
)
3990 SetLastError(ERROR_INVALID_OPERATION
);
3994 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3995 if (err
!= kCGLNoError
)
3997 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3998 SetLastError(ERROR_INVALID_OPERATION
);
4006 /**********************************************************************
4007 * macdrv_wglSetPbufferAttribARB
4009 * WGL_ARB_render_texture: wglSetPbufferAttribARB
4011 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
4013 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4015 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
4017 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
4019 int attr
= piAttribList
[0];
4020 int value
= piAttribList
[1];
4023 case WGL_MIPMAP_LEVEL_ARB
:
4024 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
4025 pbuffer
->level
= value
;
4027 case WGL_CUBE_MAP_FACE_ARB
:
4030 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
4031 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
4032 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
4034 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
4035 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
4036 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
4038 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
4039 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
4040 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
4042 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
4043 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
4044 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
4046 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
4047 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
4048 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
4050 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
4051 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
4052 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
4055 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
4056 SetLastError(ERROR_INVALID_DATA
);
4061 WARN("invalid attribute 0x%x\n", attr
);
4062 SetLastError(ERROR_INVALID_DATA
);
4067 if (context
&& context
->draw_pbuffer
== pbuffer
)
4068 make_context_current(context
, FALSE
);
4074 /**********************************************************************
4075 * macdrv_wglSetPixelFormatWINE
4077 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
4079 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
4081 return set_pixel_format(hdc
, fmt
, TRUE
);
4085 /**********************************************************************
4086 * macdrv_wglSwapIntervalEXT
4088 * WGL_EXT_swap_control: wglSwapIntervalEXT
4090 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
4092 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4093 BOOL changed
= FALSE
;
4095 TRACE("interval %d\n", interval
);
4099 SetLastError(ERROR_INVALID_DATA
);
4105 if (context
->draw_hwnd
)
4107 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
4110 changed
= data
->swap_interval
!= interval
;
4112 data
->swap_interval
= interval
;
4113 release_win_data(data
);
4122 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
4123 if (!set_swap_interval(context
, interval
))
4125 SetLastError(ERROR_GEN_FAILURE
);
4131 struct wgl_context
*ctx
;
4133 EnterCriticalSection(&context_section
);
4134 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
4136 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
4137 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
4139 LeaveCriticalSection(&context_section
);
4146 static void register_extension(const char *ext
)
4148 if (gl_info
.wglExtensions
[0])
4149 strcat(gl_info
.wglExtensions
, " ");
4150 strcat(gl_info
.wglExtensions
, ext
);
4152 TRACE("'%s'\n", ext
);
4155 static void load_extensions(void)
4160 register_extension("WGL_ARB_extensions_string");
4161 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
4163 register_extension("WGL_ARB_make_current_read");
4164 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
4165 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
4167 register_extension("WGL_ARB_pixel_format");
4168 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
4169 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
4170 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
4172 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
4174 register_extension("WGL_ARB_pixel_format_float");
4175 register_extension("WGL_ATI_pixel_format_float");
4178 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
4179 register_extension("WGL_ARB_multisample");
4181 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4182 register_extension("WGL_ARB_framebuffer_sRGB");
4184 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
4186 register_extension("WGL_ARB_pbuffer");
4187 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
4188 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
4189 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
4190 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
4191 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
4193 register_extension("WGL_ARB_render_texture");
4194 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
4195 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
4196 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
4198 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
4199 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
4200 register_extension("WGL_NV_render_texture_rectangle");
4203 register_extension("WGL_ARB_create_context");
4204 register_extension("WGL_ARB_create_context_profile");
4205 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
4210 register_extension("WGL_EXT_extensions_string");
4211 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
4215 register_extension("WGL_EXT_swap_control");
4216 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
4217 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
4220 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
4221 check for either, so register them separately. */
4222 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
4223 register_extension("WGL_EXT_framebuffer_sRGB");
4225 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
4226 register_extension("WGL_EXT_pixel_format_packed_float");
4229 * WINE-specific WGL Extensions
4232 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
4233 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
4235 register_extension("WGL_WINE_pixel_format_passthrough");
4236 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
4238 register_extension("WGL_WINE_query_renderer");
4239 opengl_funcs
.ext
.p_wglQueryCurrentRendererIntegerWINE
= macdrv_wglQueryCurrentRendererIntegerWINE
;
4240 opengl_funcs
.ext
.p_wglQueryCurrentRendererStringWINE
= macdrv_wglQueryCurrentRendererStringWINE
;
4241 opengl_funcs
.ext
.p_wglQueryRendererIntegerWINE
= macdrv_wglQueryRendererIntegerWINE
;
4242 opengl_funcs
.ext
.p_wglQueryRendererStringWINE
= macdrv_wglQueryRendererStringWINE
;
4246 static BOOL CALLBACK
init_opengl(INIT_ONCE
*init_once
, void *context
, void **param
)
4248 static BOOL init_done
= FALSE
;
4251 if (init_done
) return (opengl_handle
!= NULL
);
4256 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
4259 WARN("CFDictionaryCreateMutable failed\n");
4263 opengl_handle
= dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
);
4266 ERR("Failed to load OpenGL: %s\n", dlerror());
4267 ERR("OpenGL support is disabled.\n");
4271 for (i
= 0; i
< ARRAY_SIZE(opengl_func_names
); i
++)
4273 if (!(((void **)&opengl_funcs
.gl
)[i
] = dlsym(opengl_handle
, opengl_func_names
[i
])))
4275 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
4280 if (!init_gl_info())
4283 /* redirect some standard OpenGL functions */
4284 #define REDIRECT(func) \
4285 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
4286 REDIRECT(glCopyPixels
);
4287 REDIRECT(glGetString
);
4288 REDIRECT(glReadPixels
);
4289 REDIRECT(glViewport
);
4290 if (skip_single_buffer_flushes
|| allow_vsync
)
4296 /* redirect some OpenGL extension functions */
4297 #define REDIRECT(func) \
4298 do { if ((p##func = dlsym(opengl_handle, #func))) { opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
4299 REDIRECT(glCopyColorTable
);
4302 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
4303 pglFlushRenderAPPLE
= dlsym(opengl_handle
, "glFlushRenderAPPLE");
4306 if (!init_pixel_formats())
4312 dlclose(opengl_handle
);
4313 opengl_handle
= NULL
;
4318 /***********************************************************************
4321 * Synchronize the Mac GL view position with the Windows child window
4324 void sync_gl_view(struct macdrv_win_data
* data
, const RECT
* old_whole_rect
, const RECT
* old_client_rect
)
4326 if (data
->client_cocoa_view
&& data
->pixel_format
)
4328 RECT old
= *old_client_rect
, new = data
->client_rect
;
4330 OffsetRect(&old
, -old_whole_rect
->left
, -old_whole_rect
->top
);
4331 OffsetRect(&new, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
4332 if (!EqualRect(&old
, &new))
4334 TRACE("GL view %p changed position; marking contexts\n", data
->client_cocoa_view
);
4335 mark_contexts_for_moved_view(data
->client_cocoa_view
);
4341 /**********************************************************************
4342 * macdrv_wglDescribePixelFormat
4344 static int WINAPI
macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
4346 const pixel_format
*pf
;
4347 const struct color_mode
*mode
;
4349 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
4351 if (!descr
) return nb_displayable_formats
;
4352 if (size
< sizeof(*descr
)) return 0;
4354 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
4357 memset(descr
, 0, sizeof(*descr
));
4358 descr
->nSize
= sizeof(*descr
);
4359 descr
->nVersion
= 1;
4361 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
4362 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
4363 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
4364 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
4365 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
4366 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
4368 descr
->iPixelType
= PFD_TYPE_RGBA
;
4370 mode
= &color_modes
[pf
->color_mode
];
4371 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
4372 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
4373 R8G8B8A0 pixel format). If an app depends on that and expects that
4374 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
4375 if (mode
->alpha_bits
)
4376 descr
->cColorBits
= mode
->color_bits
;
4378 descr
->cColorBits
= mode
->bits_per_pixel
;
4379 descr
->cRedBits
= mode
->red_bits
;
4380 descr
->cRedShift
= mode
->red_shift
;
4381 descr
->cGreenBits
= mode
->green_bits
;
4382 descr
->cGreenShift
= mode
->green_shift
;
4383 descr
->cBlueBits
= mode
->blue_bits
;
4384 descr
->cBlueShift
= mode
->blue_shift
;
4385 descr
->cAlphaBits
= mode
->alpha_bits
;
4386 descr
->cAlphaShift
= mode
->alpha_shift
;
4390 mode
= &color_modes
[pf
->accum_mode
- 1];
4391 descr
->cAccumBits
= mode
->color_bits
;
4392 descr
->cAccumRedBits
= mode
->red_bits
;
4393 descr
->cAccumGreenBits
= mode
->green_bits
;
4394 descr
->cAccumBlueBits
= mode
->blue_bits
;
4395 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
4398 descr
->cDepthBits
= pf
->depth_bits
;
4399 descr
->cStencilBits
= pf
->stencil_bits
;
4400 descr
->cAuxBuffers
= pf
->aux_buffers
;
4401 descr
->iLayerType
= PFD_MAIN_PLANE
;
4403 TRACE("%s\n", debugstr_pf(pf
));
4404 return nb_displayable_formats
;
4407 /***********************************************************************
4408 * macdrv_wglCopyContext
4410 static BOOL WINAPI
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
4414 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
4416 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
4417 if (err
!= kCGLNoError
)
4418 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
4419 return (err
== kCGLNoError
);
4422 /***********************************************************************
4423 * macdrv_wglCreateContext
4425 static struct wgl_context
* WINAPI
macdrv_wglCreateContext(HDC hdc
)
4427 struct wgl_context
*context
;
4429 TRACE("hdc %p\n", hdc
);
4431 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
4436 /***********************************************************************
4437 * macdrv_wglDeleteContext
4439 static BOOL WINAPI
macdrv_wglDeleteContext(struct wgl_context
*context
)
4441 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
4443 EnterCriticalSection(&context_section
);
4444 list_remove(&context
->entry
);
4445 LeaveCriticalSection(&context_section
);
4447 macdrv_dispose_opengl_context(context
->context
);
4448 return HeapFree(GetProcessHeap(), 0, context
);
4451 /***********************************************************************
4452 * macdrv_wglGetPixelFormat
4454 static int WINAPI
macdrv_wglGetPixelFormat(HDC hdc
)
4458 format
= get_dc_pixel_format(hdc
);
4460 if (!is_valid_pixel_format(format
)) /* not set yet */
4462 else if (!is_displayable_pixel_format(format
))
4464 /* Non-displayable formats can't be used with traditional WGL calls.
4465 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
4469 TRACE(" hdc %p -> %d\n", hdc
, format
);
4473 /***********************************************************************
4474 * macdrv_wglGetProcAddress
4476 static PROC WINAPI
macdrv_wglGetProcAddress(const char *proc
)
4480 if (!strncmp(proc
, "wgl", 3)) return NULL
;
4481 ret
= dlsym(opengl_handle
, proc
);
4487 if (dladdr(ret
, &info
))
4488 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
4490 TRACE("%s -> %p (no library info)\n", proc
, ret
);
4494 WARN("failed to find proc %s\n", debugstr_a(proc
));
4498 /***********************************************************************
4499 * macdrv_wglMakeCurrent
4501 static BOOL WINAPI
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
4503 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4504 (context
? context
->cglcontext
: NULL
));
4506 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
4509 /**********************************************************************
4510 * macdrv_wglSetPixelFormat
4512 static BOOL WINAPI
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
4514 return set_pixel_format(hdc
, fmt
, FALSE
);
4517 /***********************************************************************
4518 * macdrv_wglShareLists
4520 static BOOL WINAPI
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
4522 macdrv_opengl_context saved_context
;
4523 CGLContextObj saved_cglcontext
;
4525 TRACE("org %p dest %p\n", org
, dest
);
4527 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
4528 * at context creation time but in case of WGL it is done using wglShareLists.
4530 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
4531 * and when a program requests sharing we recreate the destination context if it hasn't been made
4532 * current or when it hasn't shared display lists before.
4535 if (dest
->has_been_current
)
4537 WARN("could not share display lists, the destination context has been current already\n");
4540 else if (dest
->sharing
)
4542 WARN("could not share display lists because dest has already shared lists before\n");
4546 /* Re-create the Mac context and share display lists */
4547 saved_context
= dest
->context
;
4548 saved_cglcontext
= dest
->cglcontext
;
4549 dest
->context
= NULL
;
4550 dest
->cglcontext
= NULL
;
4551 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
4553 dest
->context
= saved_context
;
4554 dest
->cglcontext
= saved_cglcontext
;
4558 /* Implicitly disposes of saved_cglcontext. */
4559 macdrv_dispose_opengl_context(saved_context
);
4561 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
4562 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
4564 org
->sharing
= TRUE
;
4565 dest
->sharing
= TRUE
;
4570 /**********************************************************************
4571 * macdrv_wglSwapBuffers
4573 static BOOL WINAPI
macdrv_wglSwapBuffers(HDC hdc
)
4575 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
4579 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
4580 (context
? context
->cglcontext
: NULL
));
4584 sync_swap_interval(context
);
4585 sync_context(context
);
4588 if ((hwnd
= WindowFromDC(hdc
)))
4590 struct macdrv_win_data
*data
;
4592 if (!(data
= get_win_data(hwnd
)))
4594 SetLastError(ERROR_INVALID_HANDLE
);
4598 if (context
&& context
->draw_view
== data
->client_cocoa_view
)
4601 release_win_data(data
);
4605 struct wgl_pbuffer
*pbuffer
;
4607 EnterCriticalSection(&dc_pbuffers_section
);
4608 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
4609 LeaveCriticalSection(&dc_pbuffers_section
);
4613 SetLastError(ERROR_INVALID_HANDLE
);
4617 if (context
&& context
->draw_pbuffer
== pbuffer
)
4622 macdrv_flush_opengl_context(context
->context
);
4625 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
4627 /* If there is a current context, then wglSwapBuffers should do an implicit
4628 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
4629 in the other branch, but we have to do it explicitly here. */
4637 static struct opengl_funcs opengl_funcs
=
4640 macdrv_wglCopyContext
, /* p_wglCopyContext */
4641 macdrv_wglCreateContext
, /* p_wglCreateContext */
4642 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
4643 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
4644 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
4645 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
4646 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
4647 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
4648 macdrv_wglShareLists
, /* p_wglShareLists */
4649 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
4653 /**********************************************************************
4654 * macdrv_wine_get_wgl_driver
4656 struct opengl_funcs
* CDECL
macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
4658 static INIT_ONCE opengl_init
= INIT_ONCE_STATIC_INIT
;
4660 if (version
!= WINE_WGL_DRIVER_VERSION
)
4662 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
4666 if (!InitOnceExecuteOnce(&opengl_init
, init_opengl
, NULL
, NULL
)) return (void *)-1;
4668 return &opengl_funcs
;