2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
50 char wglExtensions
[4096];
52 GLint max_viewport_dims
[2];
55 static struct gl_info gl_info
;
62 macdrv_opengl_context context
;
63 CGLContextObj cglcontext
;
65 macdrv_view draw_view
;
66 struct wgl_pbuffer
*draw_pbuffer
;
67 macdrv_view read_view
;
68 struct wgl_pbuffer
*read_pbuffer
;
69 BOOL has_been_current
;
71 LONG update_swap_interval
;
72 DWORD last_flush_time
;
75 static struct list context_list
= LIST_INIT(context_list
);
77 static CRITICAL_SECTION context_section
;
78 static CRITICAL_SECTION_DEBUG critsect_debug
=
80 0, 0, &context_section
,
81 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
82 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
84 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
89 CGLPBufferObj pbuffer
;
97 static CFMutableDictionaryRef dc_pbuffers
;
99 static CRITICAL_SECTION dc_pbuffers_section
;
100 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
102 0, 0, &dc_pbuffers_section
,
103 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
104 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
106 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
109 static struct opengl_funcs opengl_funcs
;
111 #define USE_GL_FUNC(name) #name,
112 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
116 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
118 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
119 static void (*pglFinish
)(void);
120 static void (*pglFlush
)(void);
121 static void (*pglFlushRenderAPPLE
)(void);
122 static const GLubyte
*(*pglGetString
)(GLenum name
);
123 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
124 GLenum format
, GLenum type
, void *pixels
);
125 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
131 GLint color_bits
; /* including alpha_bits */
132 int red_bits
, red_shift
;
133 int green_bits
, green_shift
;
134 int blue_bits
, blue_shift
;
135 GLint alpha_bits
, alpha_shift
;
140 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
141 observations of the behavior of Windows systems, but also subjective judgments
142 about what color formats are more "normal" than others.
144 On at least some Windows systems, integer color formats are listed before
145 floating-point formats. Within the integer formats, higher color bits were
146 usually listed before lower color bits, while for floating-point formats it
147 was the reverse. However, that leads D3D to select 64-bit integer formats in
148 preference to 32-bit formats when the latter would be sufficient. It seems
149 that a 32-bit format is much more likely to be normally used in that case.
151 Also, there are certain odd color formats supported on the Mac which seem like
152 they would be less appropriate than more common ones. For instance, the color
153 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
154 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
157 For two color formats which differ only in whether or not they have alpha bits,
158 we use the same ordering. pixel_format_comparator() gives alpha bits a
159 different weight than color formats.
161 static const struct color_mode color_modes
[] = {
162 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
163 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
164 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
165 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
166 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
167 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
168 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
169 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
170 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
171 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
172 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
173 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
174 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
175 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
176 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
177 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
178 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
179 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
180 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
181 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
182 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
183 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
184 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
185 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
189 static const struct {
192 } depth_stencil_modes
[] = {
220 GLint max_aux_buffers
;
221 GLint max_sample_buffers
;
228 } renderer_properties
;
232 unsigned int window
:1;
233 unsigned int pbuffer
:1;
234 unsigned int accelerated
:1;
235 unsigned int color_mode
:5; /* index into color_modes table */
236 unsigned int aux_buffers
:3;
237 unsigned int depth_bits
:8;
238 unsigned int stencil_bits
:8;
239 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
240 unsigned int double_buffer
:1;
241 unsigned int stereo
:1;
242 unsigned int sample_buffers
:1;
243 unsigned int samples
:5;
244 unsigned int backing_store
:1;
252 } pixel_format_or_code
;
253 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
256 static pixel_format
*pixel_formats
;
257 static int nb_formats
, nb_displayable_formats
;
260 static void *opengl_handle
;
263 static const char* debugstr_attrib(int attrib
, int value
)
265 static const struct {
269 #define ATTRIB(a) { a, #a }
270 ATTRIB(WGL_ACCELERATION_ARB
),
271 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
272 ATTRIB(WGL_ACCUM_BITS_ARB
),
273 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
274 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
275 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
276 ATTRIB(WGL_ALPHA_BITS_ARB
),
277 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
278 ATTRIB(WGL_AUX_BUFFERS_ARB
),
279 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
280 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
281 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
283 ATTRIB(WGL_BLUE_BITS_ARB
),
284 ATTRIB(WGL_BLUE_SHIFT_ARB
),
285 ATTRIB(WGL_COLOR_BITS_ARB
),
286 ATTRIB(WGL_DEPTH_BITS_ARB
),
287 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
288 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
289 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
290 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
291 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
292 ATTRIB(WGL_GREEN_BITS_ARB
),
293 ATTRIB(WGL_GREEN_SHIFT_ARB
),
294 ATTRIB(WGL_NEED_PALETTE_ARB
),
295 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
296 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
297 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
298 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
299 ATTRIB(WGL_PIXEL_TYPE_ARB
),
300 ATTRIB(WGL_RED_BITS_ARB
),
301 ATTRIB(WGL_RED_SHIFT_ARB
),
302 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
303 ATTRIB(WGL_SAMPLES_ARB
),
304 ATTRIB(WGL_SHARE_ACCUM_ARB
),
305 ATTRIB(WGL_SHARE_DEPTH_ARB
),
306 ATTRIB(WGL_SHARE_STENCIL_ARB
),
307 ATTRIB(WGL_STENCIL_BITS_ARB
),
308 ATTRIB(WGL_STEREO_ARB
),
309 ATTRIB(WGL_SUPPORT_GDI_ARB
),
310 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
311 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
312 ATTRIB(WGL_SWAP_METHOD_ARB
),
313 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
314 ATTRIB(WGL_TRANSPARENT_ARB
),
315 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
316 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
317 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
318 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
322 const char *attrib_name
= NULL
;
323 const char *value_name
= NULL
;
325 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
327 if (attrib_names
[i
].attrib
== attrib
)
329 attrib_name
= attrib_names
[i
].name
;
335 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
339 case WGL_ACCELERATION_ARB
:
342 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
343 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
344 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
347 case WGL_PIXEL_TYPE_ARB
:
350 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
351 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
352 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
353 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
356 case WGL_SWAP_METHOD_ARB
:
359 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
360 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
361 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
367 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
369 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
373 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
374 CGLRendererProperty property
, GLint
*value
)
376 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
377 if (err
!= kCGLNoError
)
378 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
379 return (err
== kCGLNoError
);
383 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
387 memset(properties
, 0, sizeof(*properties
));
389 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
390 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
392 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
393 properties
->buffer_modes
= value
;
395 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
396 properties
->color_modes
= value
;
398 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
399 properties
->accum_modes
= value
;
401 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
402 properties
->depth_modes
= value
;
404 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
405 properties
->stencil_modes
= value
;
407 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
408 properties
->max_aux_buffers
= value
;
410 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
411 properties
->max_sample_buffers
= value
;
413 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
414 properties
->max_samples
= value
;
416 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
417 properties
->offscreen
= (value
!= 0);
419 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
420 properties
->accelerated
= (value
!= 0);
422 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
423 properties
->backing_store
= (value
!= 0);
425 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
426 properties
->window
= (value
!= 0);
428 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
429 properties
->online
= (value
!= 0);
433 static void dump_renderer(const renderer_properties
* renderer
)
437 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
438 TRACE("Buffer modes:\n");
439 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
440 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
441 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
442 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
444 TRACE("Color buffer modes:\n");
445 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
447 if (renderer
->color_modes
& color_modes
[i
].mode
)
449 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
450 if (color_modes
[i
].is_float
)
456 TRACE("Accumulation buffer sizes: { ");
457 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
459 if (renderer
->accum_modes
& color_modes
[i
].mode
)
460 TRACE("%d, ", color_modes
[i
].color_bits
);
464 TRACE("Depth buffer sizes: { ");
465 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
467 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
468 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
472 TRACE("Stencil buffer sizes: { ");
473 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
475 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
476 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
480 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
481 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
482 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
483 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
484 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
485 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
486 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
487 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
491 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
493 pixel_format_or_code pfc
;
496 pfc
.format
= *format
;
501 static inline pixel_format
pixel_format_for_code(UInt64 code
)
503 pixel_format_or_code pfc
;
510 static const char *debugstr_pf(const pixel_format
*pf
)
512 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",
516 color_modes
[pf
->color_mode
].color_bits
,
517 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
518 color_modes
[pf
->color_mode
].alpha_bits
,
521 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
528 code_for_pixel_format(pf
));
532 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
537 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
539 if ((modes
& color_modes
[i
].mode
) &&
540 color_modes
[i
].color_bits
>= color_size
&&
541 color_modes
[i
].alpha_bits
>= alpha_size
&&
542 !color_modes
[i
].is_float
== !color_float
)
544 if (best
< 0) /* no existing best choice */
546 else if (color_modes
[i
].color_bits
== color_size
&&
547 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
549 /* prefer it over a best which isn't exact or which has a higher bpp */
550 if (color_modes
[best
].color_bits
!= color_size
||
551 color_modes
[best
].alpha_bits
!= alpha_size
||
552 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
555 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
556 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
557 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
564 /* Couldn't find a match. Return first one that renderer supports. */
565 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
567 if (modes
& color_modes
[i
].mode
)
576 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
581 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
583 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
585 /* Prefer the fewest color bits, then prefer more alpha bits, then
586 prefer more bits per pixel. */
589 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
591 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
593 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
595 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
596 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
604 /* Couldn't find a match. Return last one that renderer supports. */
605 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
607 if (modes
& color_modes
[i
].mode
)
616 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
617 CFMutableSetRef pixel_format_set
)
619 CGLPixelFormatAttribute attribs
[64] = {
620 kCGLPFAMinimumPolicy
,
621 kCGLPFAClosestPolicy
,
622 kCGLPFARendererID
, renderer
.renderer_id
,
623 kCGLPFASingleRenderer
,
625 int n
= 5, n_stack
[16], n_stack_idx
= -1;
626 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
627 new_pixel_formats
= 0;
628 pixel_format request
;
629 unsigned int double_buffer
;
630 unsigned int accelerated
= renderer
.accelerated
;
634 attribs
[n
++] = kCGLPFAAccelerated
;
635 attribs
[n
++] = kCGLPFANoRecovery
;
637 else if (!allow_software_rendering
)
639 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
643 n_stack
[++n_stack_idx
] = n
;
644 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
648 n
= n_stack
[n_stack_idx
];
650 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
651 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
655 attribs
[n
++] = kCGLPFADoubleBuffer
;
656 memset(&request
, 0, sizeof(request
));
657 request
.accelerated
= accelerated
;
658 request
.double_buffer
= double_buffer
;
660 /* Don't bother with in-between aux buffers values: either 0 or max. */
661 n_stack
[++n_stack_idx
] = n
;
662 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
664 unsigned int color_mode
;
666 n
= n_stack
[n_stack_idx
];
668 attribs
[n
++] = kCGLPFAAuxBuffers
;
670 request
.aux_buffers
= aux
;
672 n_stack
[++n_stack_idx
] = n
;
673 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
675 unsigned int depth_mode
;
677 n
= n_stack
[n_stack_idx
];
679 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
682 attribs
[n
++] = kCGLPFAColorSize
;
683 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
684 attribs
[n
++] = kCGLPFAAlphaSize
;
685 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
686 if (color_modes
[color_mode
].is_float
)
687 attribs
[n
++] = kCGLPFAColorFloat
;
688 request
.color_mode
= color_mode
;
690 n_stack
[++n_stack_idx
] = n
;
691 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
693 unsigned int stencil_mode
;
695 n
= n_stack
[n_stack_idx
];
697 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
700 attribs
[n
++] = kCGLPFADepthSize
;
701 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
702 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
704 n_stack
[++n_stack_idx
] = n
;
705 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
709 n
= n_stack
[n_stack_idx
];
711 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
713 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
716 attribs
[n
++] = kCGLPFAStencilSize
;
717 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
718 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
720 /* FIXME: Could trim search space a bit here depending on GPU.
721 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
722 n_stack
[++n_stack_idx
] = n
;
723 for (stereo
= 0; stereo
<= 1; stereo
++)
727 n
= n_stack
[n_stack_idx
];
729 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
730 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
734 attribs
[n
++] = kCGLPFAStereo
;
735 request
.stereo
= stereo
;
737 /* Starts at -1 for a 0 accum size */
738 n_stack
[++n_stack_idx
] = n
;
739 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
741 unsigned int target_pass
;
743 n
= n_stack
[n_stack_idx
];
747 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
750 attribs
[n
++] = kCGLPFAAccumSize
;
751 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
752 request
.accum_mode
= accum_mode
+ 1;
755 request
.accum_mode
= 0;
757 /* Targets to request are:
758 accelerated: window OR window + pbuffer
759 software: window + pbuffer */
760 n_stack
[++n_stack_idx
] = n
;
761 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
763 unsigned int samples
, max_samples
;
765 n
= n_stack
[n_stack_idx
];
767 attribs
[n
++] = kCGLPFAWindow
;
770 if (!accelerated
|| target_pass
> 0)
772 attribs
[n
++] = kCGLPFAPBuffer
;
778 /* FIXME: Could trim search space a bit here depending on GPU.
779 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
780 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
781 n_stack
[++n_stack_idx
] = n
;
782 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
783 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
785 unsigned int backing_store
, min_backing_store
, max_backing_store
;
787 n
= n_stack
[n_stack_idx
];
791 attribs
[n
++] = kCGLPFASampleBuffers
;
792 attribs
[n
++] = renderer
.max_sample_buffers
;
793 attribs
[n
++] = kCGLPFASamples
;
794 attribs
[n
++] = samples
;
795 request
.sample_buffers
= renderer
.max_sample_buffers
;
796 request
.samples
= samples
;
799 request
.sample_buffers
= request
.samples
= 0;
801 if (renderer
.backing_store
&& double_buffer
)
803 /* The software renderer seems to always preserve the backing store, whether
804 we ask for it or not. So don't bother not asking for it. */
805 min_backing_store
= accelerated
? 0 : 1;
806 max_backing_store
= 1;
809 min_backing_store
= max_backing_store
= 0;
810 n_stack
[++n_stack_idx
] = n
;
811 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
813 CGLPixelFormatObj pix
;
814 GLint virtualScreens
;
817 n
= n_stack
[n_stack_idx
];
820 attribs
[n
++] = kCGLPFABackingStore
;
821 request
.backing_store
= backing_store
;
825 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
826 if (err
== kCGLNoError
&& pix
)
829 GLint value
, color_size
, alpha_size
, color_float
;
831 CFNumberRef code_object
;
834 memset(&pf
, 0, sizeof(pf
));
836 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
837 pf
.accelerated
= value
;
838 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
839 pf
.aux_buffers
= value
;
840 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
841 pf
.depth_bits
= value
;
842 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
843 pf
.double_buffer
= value
;
844 if (pf
.double_buffer
&&
845 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
846 pf
.backing_store
= value
;
847 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
849 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
850 pf
.sample_buffers
= value
;
851 if (pf
.sample_buffers
&&
852 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
854 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
855 pf
.stencil_bits
= value
;
856 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
858 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
861 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
863 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
865 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
867 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
869 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
870 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
872 CGLReleasePixelFormat(pix
);
874 pf_code
= code_for_pixel_format(&pf
);
876 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
877 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
878 dupe_pixel_formats
++;
881 CFSetAddValue(pixel_format_set
, code_object
);
882 CFArrayAppendValue(pixel_format_array
, code_object
);
885 CFRelease(code_object
);
887 if (pf_code
== code_for_pixel_format(&request
))
888 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
891 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
892 dupe
? " (duplicate)" : "");
897 failed_pixel_formats
++;
898 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
901 tried_pixel_formats
++;
933 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
934 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
935 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
936 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
940 /* The docs for WGL_ARB_pixel_format say:
941 Indices are assigned to pixel formats in the following order:
942 1. Accelerated pixel formats that are displayable
943 2. Accelerated pixel formats that are displayable and which have
945 3. Generic pixel formats
946 4. Accelerated pixel formats that are non displayable
948 static int pixel_format_category(pixel_format pf
)
950 /* non-displayable */
954 /* non-accelerated a.k.a. software a.k.a. generic */
958 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
959 if (color_modes
[pf
.color_mode
].is_float
)
962 /* accelerated, displayable, no extended attributes */
967 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
969 CFNumberRef number1
= val1
;
970 CFNumberRef number2
= val2
;
972 pixel_format pf1
, pf2
;
973 int category1
, category2
;
975 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
976 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
977 pf1
= pixel_format_for_code(code1
);
978 pf2
= pixel_format_for_code(code2
);
979 category1
= pixel_format_category(pf1
);
980 category2
= pixel_format_category(pf2
);
982 if (category1
< category2
)
983 return kCFCompareLessThan
;
984 if (category1
> category2
)
985 return kCFCompareGreaterThan
;
987 /* Within a category, sort the "best" formats toward the front since that's
988 what wglChoosePixelFormatARB() has to do. The ordering implemented here
989 matches at least one Windows 7 machine's behavior.
991 /* Accelerated before unaccelerated. */
992 if (pf1
.accelerated
&& !pf2
.accelerated
)
993 return kCFCompareLessThan
;
994 if (!pf1
.accelerated
&& pf2
.accelerated
)
995 return kCFCompareGreaterThan
;
997 /* Explicit color mode ordering. */
998 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
999 return kCFCompareLessThan
;
1000 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1001 return kCFCompareGreaterThan
;
1003 /* Non-pbuffer-capable before pbuffer-capable. */
1004 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1005 return kCFCompareLessThan
;
1006 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1007 return kCFCompareGreaterThan
;
1009 /* Fewer samples before more samples. */
1010 if (pf1
.samples
< pf2
.samples
)
1011 return kCFCompareLessThan
;
1012 if (pf1
.samples
> pf2
.samples
)
1013 return kCFCompareGreaterThan
;
1015 /* Monoscopic before stereoscopic. (This is a guess.) */
1016 if (!pf1
.stereo
&& pf2
.stereo
)
1017 return kCFCompareLessThan
;
1018 if (pf1
.stereo
&& !pf2
.stereo
)
1019 return kCFCompareGreaterThan
;
1021 /* Single buffered before double buffered. */
1022 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1023 return kCFCompareLessThan
;
1024 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1025 return kCFCompareGreaterThan
;
1027 /* Possibly-optimized double buffering before backing-store-preserving
1028 double buffering. */
1029 if (!pf1
.backing_store
&& pf2
.backing_store
)
1030 return kCFCompareLessThan
;
1031 if (pf1
.backing_store
&& !pf2
.backing_store
)
1032 return kCFCompareGreaterThan
;
1034 /* Bigger depth buffer before smaller depth buffer. */
1035 if (pf1
.depth_bits
> pf2
.depth_bits
)
1036 return kCFCompareLessThan
;
1037 if (pf1
.depth_bits
< pf2
.depth_bits
)
1038 return kCFCompareGreaterThan
;
1040 /* Smaller stencil buffer before bigger stencil buffer. */
1041 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1042 return kCFCompareLessThan
;
1043 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1044 return kCFCompareGreaterThan
;
1046 /* Smaller alpha bits before larger alpha bits. */
1047 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1048 return kCFCompareLessThan
;
1049 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1050 return kCFCompareGreaterThan
;
1052 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1057 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1058 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1059 return kCFCompareLessThan
;
1060 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1061 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1062 return kCFCompareGreaterThan
;
1064 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1065 return kCFCompareLessThan
;
1066 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1067 return kCFCompareGreaterThan
;
1069 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1070 return kCFCompareLessThan
;
1071 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1072 return kCFCompareGreaterThan
;
1075 return kCFCompareGreaterThan
;
1077 else if (pf2
.accum_mode
)
1078 return kCFCompareLessThan
;
1080 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1081 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1082 return kCFCompareLessThan
;
1083 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1084 return kCFCompareGreaterThan
;
1086 /* If we get here, arbitrarily sort based on code. */
1088 return kCFCompareLessThan
;
1090 return kCFCompareGreaterThan
;
1091 return kCFCompareEqualTo
;
1095 static BOOL
init_pixel_formats(void)
1098 CGLRendererInfoObj renderer_info
;
1099 GLint rendererCount
;
1101 CFMutableSetRef pixel_format_set
;
1102 CFMutableArrayRef pixel_format_array
;
1108 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1111 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1115 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1116 if (!pixel_format_set
)
1118 WARN("CFSetCreateMutable failed\n");
1119 CGLDestroyRendererInfo(renderer_info
);
1123 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1124 if (!pixel_format_array
)
1126 WARN("CFArrayCreateMutable failed\n");
1127 CFRelease(pixel_format_set
);
1128 CGLDestroyRendererInfo(renderer_info
);
1132 for (i
= 0; i
< rendererCount
; i
++)
1134 renderer_properties renderer
;
1136 get_renderer_properties(renderer_info
, i
, &renderer
);
1139 TRACE("renderer_properties %d:\n", i
);
1140 dump_renderer(&renderer
);
1143 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1146 CFRelease(pixel_format_set
);
1147 CGLDestroyRendererInfo(renderer_info
);
1149 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1152 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1155 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1156 for (i
= 0; i
< range
.length
; i
++)
1158 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1161 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1162 pixel_formats
[i
] = pixel_format_for_code(code
);
1163 if (pixel_formats
[i
].window
)
1164 nb_displayable_formats
++;
1167 nb_formats
= range
.length
;
1168 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1172 WARN("failed to allocate pixel format list\n");
1175 WARN("got no pixel formats\n");
1177 CFRelease(pixel_format_array
);
1182 static inline BOOL
is_valid_pixel_format(int format
)
1184 return format
> 0 && format
<= nb_formats
;
1188 static inline BOOL
is_displayable_pixel_format(int format
)
1190 return format
> 0 && format
<= nb_displayable_formats
;
1194 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1196 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1197 * format in case of probing the number of pixel formats.
1199 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1201 TRACE("Returning format %d\n", format
);
1202 return &pixel_formats
[format
- 1];
1208 static BOOL
init_gl_info(void)
1210 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1211 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1213 CGDirectDisplayID display
= CGMainDisplayID();
1214 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1215 CGLPixelFormatAttribute attribs
[] = {
1216 kCGLPFADisplayMask
, displayMask
,
1219 CGLPixelFormatObj pix
;
1220 GLint virtualScreens
;
1222 CGLContextObj context
;
1223 CGLContextObj old_context
= CGLGetCurrentContext();
1227 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1228 if (err
!= kCGLNoError
|| !pix
)
1230 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1234 err
= CGLCreateContext(pix
, NULL
, &context
);
1235 CGLReleasePixelFormat(pix
);
1236 if (err
!= kCGLNoError
|| !context
)
1238 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1242 err
= CGLSetCurrentContext(context
);
1243 if (err
!= kCGLNoError
)
1245 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1246 CGLReleaseContext(context
);
1250 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1251 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1252 strcpy(gl_info
.glVersion
, str
);
1253 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1254 length
= strlen(str
) + sizeof(legacy_extensions
);
1256 length
+= strlen(legacy_ext_swap_control
);
1257 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1258 strcpy(gl_info
.glExtensions
, str
);
1259 strcat(gl_info
.glExtensions
, legacy_extensions
);
1261 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1263 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1265 TRACE("GL version : %s\n", gl_info
.glVersion
);
1266 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1268 CGLSetCurrentContext(old_context
);
1269 CGLReleaseContext(context
);
1275 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1278 *rect
= data
->client_rect
;
1280 if (data
->cocoa_window
)
1283 *window
= data
->cocoa_window
;
1284 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1288 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1289 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1290 struct macdrv_win_data
*top_data
= get_win_data(top
);
1292 if (top_data
&& top_data
->cocoa_window
)
1295 *window
= top_data
->cocoa_window
;
1296 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1297 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1302 release_win_data(top_data
);
1309 /***********************************************************************
1312 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1314 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1318 macdrv_window cocoa_window
;
1320 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1322 ERR("no top-level parent with Cocoa window in this process\n");
1326 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1329 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1333 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1334 wine_dbgstr_rect(&data
->gl_rect
));
1337 data
->pixel_format
= format
;
1343 /**********************************************************************
1346 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1348 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1350 struct macdrv_win_data
*data
;
1351 const pixel_format
*pf
;
1352 HWND hwnd
= WindowFromDC(hdc
);
1355 TRACE("hdc %p format %d\n", hdc
, fmt
);
1357 if (!hwnd
|| hwnd
== GetDesktopWindow())
1359 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1363 if (!(data
= get_win_data(hwnd
)))
1365 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1369 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1371 ret
= (data
->pixel_format
== fmt
);
1375 /* Check if fmt is in our list of supported formats to see if it is supported. */
1376 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1379 ERR("Invalid pixel format: %d\n", fmt
);
1385 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1389 if (!set_win_format(data
, fmt
))
1391 WARN("Couldn't set format of the window, returning failure\n");
1395 TRACE("pixel format:\n");
1396 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1397 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1398 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1399 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1400 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1401 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1402 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1403 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1404 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1405 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1406 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1407 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1408 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1409 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1413 release_win_data(data
);
1414 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1419 /**********************************************************************
1420 * set_gl_view_parent
1422 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1424 struct macdrv_win_data
*data
;
1426 if (!(data
= get_win_data(hwnd
))) return;
1430 macdrv_window cocoa_window
;
1432 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1434 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1436 ERR("no top-level parent with Cocoa window in this process\n");
1437 macdrv_dispose_view(data
->gl_view
);
1438 data
->gl_view
= NULL
;
1439 release_win_data(data
);
1440 __wine_set_pixel_format( hwnd
, 0 );
1444 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1447 release_win_data(data
);
1451 /**********************************************************************
1452 * make_context_current
1454 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1457 struct wgl_pbuffer
*pbuffer
;
1461 view
= context
->read_view
;
1462 pbuffer
= context
->read_pbuffer
;
1466 view
= context
->draw_view
;
1467 pbuffer
= context
->draw_pbuffer
;
1470 if (view
|| !pbuffer
)
1471 macdrv_make_context_current(context
->context
, view
);
1474 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1476 CGLSetCurrentContext(context
->cglcontext
);
1481 /**********************************************************************
1484 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1488 /* In theory, for single-buffered contexts, there's no such thing as a swap
1489 so the swap interval shouldn't matter. But OS X will synchronize flushes
1490 of single-buffered contexts if the interval is set to non-zero. */
1491 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1494 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1495 if (err
!= kCGLNoError
)
1496 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1498 return err
== kCGLNoError
;
1502 /**********************************************************************
1503 * sync_swap_interval
1505 static void sync_swap_interval(struct wgl_context
*context
)
1507 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1511 if (context
->draw_hwnd
)
1513 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1516 interval
= data
->swap_interval
;
1517 release_win_data(data
);
1519 else /* window was destroyed? */
1525 set_swap_interval(context
, interval
);
1530 /**********************************************************************
1531 * macdrv_glCopyColorTable
1533 * Hook into glCopyColorTable as part of the implementation of
1534 * wglMakeContextCurrentARB. If the context has a separate readable,
1535 * temporarily make that current, do glCopyColorTable, and then set it
1536 * back to the drawable. This is modeled after what Mesa GLX's Apple
1537 * implementation does.
1539 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1542 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1544 if (context
->read_view
|| context
->read_pbuffer
)
1545 make_context_current(context
, TRUE
);
1547 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1549 if (context
->read_view
|| context
->read_pbuffer
)
1550 make_context_current(context
, FALSE
);
1554 /**********************************************************************
1555 * macdrv_glCopyPixels
1557 * Hook into glCopyPixels as part of the implementation of
1558 * wglMakeContextCurrentARB. If the context has a separate readable,
1559 * temporarily make that current, do glCopyPixels, and then set it back
1560 * to the drawable. This is modeled after what Mesa GLX's Apple
1561 * implementation does.
1563 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1565 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1567 if (context
->read_view
|| context
->read_pbuffer
)
1568 make_context_current(context
, TRUE
);
1570 pglCopyPixels(x
, y
, width
, height
, type
);
1572 if (context
->read_view
|| context
->read_pbuffer
)
1573 make_context_current(context
, FALSE
);
1577 /**********************************************************************
1580 static void macdrv_glFinish(void)
1582 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1584 sync_swap_interval(context
);
1589 /**********************************************************************
1592 static void macdrv_glFlush(void)
1594 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1596 sync_swap_interval(context
);
1598 if (skip_single_buffer_flushes
)
1600 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1601 DWORD now
= GetTickCount();
1603 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1604 context
->last_flush_time
, now
);
1605 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1607 TRACE("calling glFlushRenderAPPLE()\n");
1608 pglFlushRenderAPPLE();
1613 TRACE("calling glFlush()\n");
1614 context
->last_flush_time
= now
;
1622 /**********************************************************************
1623 * macdrv_glGetString
1625 * Hook into glGetString in order to return some legacy WGL extensions
1626 * that couldn't be advertised via the standard
1627 * WGL_ARB_extensions_string mechanism. Some programs, especially
1628 * older ones, expect to find certain older extensions, such as
1629 * WGL_EXT_extensions_string itself, in the standard GL extensions
1630 * string, and won't query any other WGL extensions unless they find
1631 * that particular extension there.
1633 static const GLubyte
*macdrv_glGetString(GLenum name
)
1635 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1636 return (const GLubyte
*)gl_info
.glExtensions
;
1638 return pglGetString(name
);
1642 /**********************************************************************
1643 * macdrv_glReadPixels
1645 * Hook into glReadPixels as part of the implementation of
1646 * wglMakeContextCurrentARB. If the context has a separate readable,
1647 * temporarily make that current, do glReadPixels, and then set it back
1648 * to the drawable. This is modeled after what Mesa GLX's Apple
1649 * implementation does.
1651 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1652 GLenum format
, GLenum type
, void *pixels
)
1654 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1656 if (context
->read_view
|| context
->read_pbuffer
)
1657 make_context_current(context
, TRUE
);
1659 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1661 if (context
->read_view
|| context
->read_pbuffer
)
1662 make_context_current(context
, FALSE
);
1666 /**********************************************************************
1669 * Hook into glViewport as an opportunity to update the OpenGL context
1670 * if necessary. This is modeled after what Mesa GLX's Apple
1671 * implementation does.
1673 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1675 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1677 macdrv_update_opengl_context(context
->context
);
1678 pglViewport(x
, y
, width
, height
);
1682 /***********************************************************************
1683 * macdrv_wglBindTexImageARB
1685 * WGL_ARB_render_texture: wglBindTexImageARB
1687 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1689 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1693 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1695 if (pbuffer
->no_texture
)
1697 SetLastError(ERROR_INVALID_OPERATION
);
1701 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1702 opengl_funcs
.gl
.p_glFlush();
1706 case WGL_FRONT_LEFT_ARB
:
1707 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1708 source
= GL_FRONT_LEFT
;
1712 case WGL_FRONT_RIGHT_ARB
:
1713 source
= GL_FRONT_RIGHT
;
1715 case WGL_BACK_LEFT_ARB
:
1716 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1717 source
= GL_BACK_LEFT
;
1721 case WGL_BACK_RIGHT_ARB
:
1722 source
= GL_BACK_RIGHT
;
1724 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1725 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1726 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1727 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1735 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1736 SetLastError(ERROR_INVALID_DATA
);
1740 WARN("unknown source buffer 0x%x\n", iBuffer
);
1741 SetLastError(ERROR_INVALID_DATA
);
1745 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1746 if (err
!= kCGLNoError
)
1748 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1749 SetLastError(ERROR_INVALID_OPERATION
);
1757 /***********************************************************************
1758 * macdrv_wglChoosePixelFormatARB
1760 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1762 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1763 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1764 int *piFormats
, UINT
*nNumFormats
)
1766 pixel_format pf
, valid
;
1768 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1769 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
1774 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1775 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
1777 FIXME("unused pfAttribFList\n");
1779 memset(&pf
, 0, sizeof(pf
));
1780 memset(&valid
, 0, sizeof(valid
));
1781 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
1782 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
1786 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
1789 int value
= iptr
[1];
1791 TRACE("%s\n", debugstr_attrib(attr
, value
));
1795 case WGL_DRAW_TO_WINDOW_ARB
:
1796 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
1797 pf
.window
= (value
!= 0);
1801 case WGL_DRAW_TO_BITMAP_ARB
:
1804 case WGL_ACCELERATION_ARB
:
1805 if (value
== WGL_FULL_ACCELERATION_ARB
)
1807 else if (value
== WGL_NO_ACCELERATION_ARB
)
1811 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
1812 pf
.accelerated
= value
;
1813 valid
.accelerated
= 1;
1816 case WGL_NEED_PALETTE_ARB
:
1817 case WGL_NEED_SYSTEM_PALETTE_ARB
:
1818 case WGL_SWAP_LAYER_BUFFERS_ARB
:
1819 if (value
) goto cant_match
;
1822 case WGL_SWAP_METHOD_ARB
:
1823 if (value
== WGL_SWAP_COPY_ARB
)
1825 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
1829 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
1830 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
1831 pf
.backing_store
= value
;
1832 valid
.backing_store
= 1;
1835 case WGL_NUMBER_OVERLAYS_ARB
:
1836 case WGL_NUMBER_UNDERLAYS_ARB
:
1837 if (value
) goto cant_match
;
1840 case WGL_SHARE_DEPTH_ARB
:
1841 case WGL_SHARE_STENCIL_ARB
:
1842 case WGL_SHARE_ACCUM_ARB
:
1846 case WGL_SUPPORT_GDI_ARB
:
1847 if (value
) goto cant_match
;
1850 case WGL_SUPPORT_OPENGL_ARB
:
1851 if (!value
) goto cant_match
;
1854 case WGL_DOUBLE_BUFFER_ARB
:
1855 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
1856 pf
.double_buffer
= (value
!= 0);
1857 valid
.double_buffer
= 1;
1858 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
1861 case WGL_STEREO_ARB
:
1862 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
1863 pf
.stereo
= (value
!= 0);
1867 case WGL_PIXEL_TYPE_ARB
:
1868 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
1870 else if (value
== WGL_TYPE_RGBA_ARB
)
1874 /* Mac contexts don't support rendering to unsigned floating
1875 point formats, even if GL_EXT_packed_float is supported.
1876 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1879 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
1880 if (srgb
&& value
) goto cant_match
;
1881 float_color
= value
;
1884 case WGL_COLOR_BITS_ARB
:
1885 if (color_bits
< value
) color_bits
= value
;
1888 case WGL_RED_BITS_ARB
:
1889 if (srgb
&& value
> 8) goto cant_match
;
1890 if (red_bits
< value
) red_bits
= value
;
1893 case WGL_GREEN_BITS_ARB
:
1894 if (srgb
&& value
> 8) goto cant_match
;
1895 if (green_bits
< value
) green_bits
= value
;
1898 case WGL_BLUE_BITS_ARB
:
1899 if (srgb
&& value
> 8) goto cant_match
;
1900 if (blue_bits
< value
) blue_bits
= value
;
1903 case WGL_ALPHA_BITS_ARB
:
1904 if (alpha_bits
< value
) alpha_bits
= value
;
1907 case WGL_ACCUM_BITS_ARB
:
1908 if (accum_bits
< value
) accum_bits
= value
;
1911 case WGL_ACCUM_RED_BITS_ARB
:
1912 if (accum_red_bits
< value
) accum_red_bits
= value
;
1915 case WGL_ACCUM_GREEN_BITS_ARB
:
1916 if (accum_green_bits
< value
) accum_green_bits
= value
;
1919 case WGL_ACCUM_BLUE_BITS_ARB
:
1920 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
1923 case WGL_ACCUM_ALPHA_BITS_ARB
:
1924 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
1927 case WGL_DEPTH_BITS_ARB
:
1928 if (value
> 255) goto cant_match
;
1929 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
1932 case WGL_STENCIL_BITS_ARB
:
1933 if (value
> 255) goto cant_match
;
1934 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
1937 case WGL_AUX_BUFFERS_ARB
:
1938 if (value
> 7) goto cant_match
;
1939 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
1942 case WGL_SAMPLE_BUFFERS_ARB
:
1943 if (value
> 1) goto cant_match
;
1944 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
1947 case WGL_SAMPLES_ARB
:
1948 if (value
> 31) goto cant_match
;
1949 if (pf
.samples
< value
) pf
.samples
= value
;
1952 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1953 /* sRGB is only supported for 8-bit integer color components */
1954 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
1959 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
1960 case WGL_RED_SHIFT_ARB
:
1961 case WGL_GREEN_SHIFT_ARB
:
1962 case WGL_BLUE_SHIFT_ARB
:
1963 case WGL_ALPHA_SHIFT_ARB
:
1964 case WGL_TRANSPARENT_ARB
:
1965 case WGL_TRANSPARENT_RED_VALUE_ARB
:
1966 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
1967 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
1968 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
1969 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
1973 case WGL_DRAW_TO_PBUFFER_ARB
:
1974 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
1975 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
1976 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
1977 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
1978 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
1979 pf
.pbuffer
= (value
!= 0);
1981 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
1987 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
1992 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",
1993 valid
.window
? (pf
.window
? "1" : "0") : "?",
1994 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
1995 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
1997 float_color
== -1 ? "?" : float_color
? "f" : "",
2011 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2012 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2013 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2017 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2019 const struct color_mode
*mode
;
2021 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2022 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2023 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2024 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2025 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2026 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2028 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2029 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2030 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2031 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2032 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2034 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2035 /* If the mode doesn't have alpha, check requested color bits against
2036 bits per pixel instead of the mode's color bits. On Windows, color
2037 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2038 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2039 expects that to match such a pixel format, we need to accommodate that. */
2040 if (mode
->alpha_bits
)
2042 if (mode
->color_bits
< color_bits
)
2047 if (mode
->bits_per_pixel
< color_bits
)
2050 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2051 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2053 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2054 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2057 if (pixel_formats
[i
].accum_mode
)
2059 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2060 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2061 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2062 mode
->alpha_bits
< accum_alpha_bits
)
2065 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2068 piFormats
[found
++] = i
+ 1;
2069 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2073 *nNumFormats
= found
;
2079 /**********************************************************************
2080 * macdrv_wglCreatePbufferARB
2082 * WGL_ARB_pbuffer: wglCreatePbufferARB
2084 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2085 const int *piAttribList
)
2087 struct wgl_pbuffer
* pbuffer
;
2089 GLenum internalFormat
= 0;
2092 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2093 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2095 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2097 WARN("invalid pixel format %d\n", iPixelFormat
);
2098 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2102 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2103 pbuffer
->format
= iPixelFormat
;
2105 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2107 int attr
= piAttribList
[0];
2108 int value
= piAttribList
[1];
2112 case WGL_PBUFFER_LARGEST_ARB
:
2113 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2116 case WGL_TEXTURE_FORMAT_ARB
:
2119 case WGL_TEXTURE_RGBA_ARB
:
2120 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2121 internalFormat
= GL_RGBA
;
2123 case WGL_TEXTURE_RGB_ARB
:
2124 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2125 internalFormat
= GL_RGB
;
2127 case WGL_NO_TEXTURE_ARB
:
2128 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2132 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2133 SetLastError(ERROR_INVALID_DATA
);
2138 case WGL_TEXTURE_TARGET_ARB
:
2142 case WGL_NO_TEXTURE_ARB
:
2143 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2146 case WGL_TEXTURE_CUBE_MAP_ARB
:
2147 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2148 target
= GL_TEXTURE_CUBE_MAP
;
2149 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2151 case WGL_TEXTURE_1D_ARB
:
2152 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2153 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2155 case WGL_TEXTURE_2D_ARB
:
2156 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2157 target
= GL_TEXTURE_2D
;
2159 case WGL_TEXTURE_RECTANGLE_NV
:
2160 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2161 target
= GL_TEXTURE_RECTANGLE
;
2164 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2165 SetLastError(ERROR_INVALID_DATA
);
2170 case WGL_MIPMAP_TEXTURE_ARB
:
2171 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2172 pbuffer
->max_level
= 0;
2175 int size
= min(iWidth
, iHeight
) / 2;
2178 pbuffer
->max_level
++;
2185 WARN("unknown attribute 0x%x\n", attr
);
2186 SetLastError(ERROR_INVALID_DATA
);
2191 if (!target
|| !internalFormat
)
2193 pbuffer
->no_texture
= TRUE
;
2194 /* no actual way to turn off ability to texture; use most permissive target */
2195 target
= GL_TEXTURE_RECTANGLE
;
2196 internalFormat
= GL_RGB
;
2199 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2200 if (err
!= kCGLNoError
)
2202 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2203 pbuffer
->pbuffer
= NULL
;
2204 if (err
== kCGLBadAlloc
)
2205 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2207 SetLastError(ERROR_INVALID_DATA
);
2211 if (!pbuffer
->pbuffer
)
2213 HeapFree(GetProcessHeap(), 0, pbuffer
);
2217 TRACE(" -> %p\n", pbuffer
);
2222 /**********************************************************************
2223 * macdrv_wglDestroyPbufferARB
2225 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2227 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2229 TRACE("pbuffer %p\n", pbuffer
);
2230 if (pbuffer
&& pbuffer
->pbuffer
)
2231 CGLReleasePBuffer(pbuffer
->pbuffer
);
2232 HeapFree(GetProcessHeap(), 0, pbuffer
);
2237 /**********************************************************************
2238 * macdrv_wglGetExtensionsStringARB
2240 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2242 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2244 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2245 this can be specific to the CGL renderer like we're supposed to do. */
2246 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2247 return gl_info
.wglExtensions
;
2251 /**********************************************************************
2252 * macdrv_wglGetExtensionsStringEXT
2254 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2256 static const char *macdrv_wglGetExtensionsStringEXT(void)
2258 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2259 return gl_info
.wglExtensions
;
2263 /**********************************************************************
2264 * macdrv_wglGetPbufferDCARB
2266 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2268 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2271 struct wgl_pbuffer
*prev
;
2273 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2276 EnterCriticalSection(&dc_pbuffers_section
);
2277 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2280 CGLReleasePBuffer(prev
->pbuffer
);
2281 HeapFree(GetProcessHeap(), 0, prev
);
2283 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2284 LeaveCriticalSection(&dc_pbuffers_section
);
2286 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2291 /**********************************************************************
2292 * macdrv_wglGetPixelFormatAttribivARB
2294 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2296 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2297 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2299 const pixel_format
*pf
;
2302 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2303 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2305 if (!nAttributes
) return GL_TRUE
;
2307 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2309 piValues
[0] = nb_formats
;
2310 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2314 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2317 WARN("invalid pixel format %d\n", iPixelFormat
);
2318 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2322 for (i
= 0; i
< nAttributes
; ++i
)
2324 switch (piAttributes
[i
])
2326 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2327 piValues
[i
] = nb_formats
;
2330 case WGL_DRAW_TO_WINDOW_ARB
:
2331 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2334 case WGL_DRAW_TO_BITMAP_ARB
:
2335 piValues
[i
] = GL_FALSE
;
2338 case WGL_ACCELERATION_ARB
:
2339 if (iLayerPlane
) goto invalid_layer
;
2340 if (pf
->accelerated
)
2341 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2343 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2346 case WGL_NEED_PALETTE_ARB
:
2347 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2348 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2349 piValues
[i
] = GL_FALSE
;
2352 case WGL_SWAP_METHOD_ARB
:
2353 if (pf
->double_buffer
&& pf
->backing_store
)
2354 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2356 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2359 case WGL_NUMBER_OVERLAYS_ARB
:
2360 case WGL_NUMBER_UNDERLAYS_ARB
:
2364 case WGL_TRANSPARENT_ARB
:
2365 if (iLayerPlane
) goto invalid_layer
;
2366 piValues
[i
] = GL_FALSE
;
2369 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2370 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2371 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2372 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2373 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2374 if (iLayerPlane
) goto invalid_layer
;
2378 case WGL_SHARE_DEPTH_ARB
:
2379 case WGL_SHARE_STENCIL_ARB
:
2380 case WGL_SHARE_ACCUM_ARB
:
2381 if (iLayerPlane
) goto invalid_layer
;
2382 piValues
[i
] = GL_TRUE
;
2385 case WGL_SUPPORT_GDI_ARB
:
2386 if (iLayerPlane
) goto invalid_layer
;
2387 piValues
[i
] = GL_FALSE
;
2390 case WGL_SUPPORT_OPENGL_ARB
:
2391 if (iLayerPlane
) goto invalid_layer
;
2392 piValues
[i
] = GL_TRUE
;
2395 case WGL_DOUBLE_BUFFER_ARB
:
2396 if (iLayerPlane
) goto invalid_layer
;
2397 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2400 case WGL_STEREO_ARB
:
2401 if (iLayerPlane
) goto invalid_layer
;
2402 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2405 case WGL_PIXEL_TYPE_ARB
:
2406 if (iLayerPlane
) goto invalid_layer
;
2407 if (color_modes
[pf
->color_mode
].is_float
)
2408 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2410 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2411 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2412 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2413 However, Mac contexts don't support rendering to unsigned floating-point
2414 formats, even when GL_EXT_packed_float is supported. */
2417 case WGL_COLOR_BITS_ARB
:
2418 if (iLayerPlane
) goto invalid_layer
;
2419 /* If the mode doesn't have alpha, return bits per pixel instead
2420 of color bits. On Windows, color bits sometimes exceeds r+g+b
2421 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2422 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2423 pixel format, we need to accommodate that. */
2424 if (color_modes
[pf
->color_mode
].alpha_bits
)
2425 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2427 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2430 case WGL_RED_BITS_ARB
:
2431 if (iLayerPlane
) goto invalid_layer
;
2432 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2435 case WGL_RED_SHIFT_ARB
:
2436 if (iLayerPlane
) goto invalid_layer
;
2437 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2440 case WGL_GREEN_BITS_ARB
:
2441 if (iLayerPlane
) goto invalid_layer
;
2442 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2445 case WGL_GREEN_SHIFT_ARB
:
2446 if (iLayerPlane
) goto invalid_layer
;
2447 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2450 case WGL_BLUE_BITS_ARB
:
2451 if (iLayerPlane
) goto invalid_layer
;
2452 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2455 case WGL_BLUE_SHIFT_ARB
:
2456 if (iLayerPlane
) goto invalid_layer
;
2457 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2460 case WGL_ALPHA_BITS_ARB
:
2461 if (iLayerPlane
) goto invalid_layer
;
2462 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2465 case WGL_ALPHA_SHIFT_ARB
:
2466 if (iLayerPlane
) goto invalid_layer
;
2467 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2470 case WGL_ACCUM_BITS_ARB
:
2471 if (iLayerPlane
) goto invalid_layer
;
2473 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2478 case WGL_ACCUM_RED_BITS_ARB
:
2479 if (iLayerPlane
) goto invalid_layer
;
2481 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2486 case WGL_ACCUM_GREEN_BITS_ARB
:
2487 if (iLayerPlane
) goto invalid_layer
;
2489 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2494 case WGL_ACCUM_BLUE_BITS_ARB
:
2495 if (iLayerPlane
) goto invalid_layer
;
2497 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2502 case WGL_ACCUM_ALPHA_BITS_ARB
:
2503 if (iLayerPlane
) goto invalid_layer
;
2505 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2510 case WGL_DEPTH_BITS_ARB
:
2511 if (iLayerPlane
) goto invalid_layer
;
2512 piValues
[i
] = pf
->depth_bits
;
2515 case WGL_STENCIL_BITS_ARB
:
2516 if (iLayerPlane
) goto invalid_layer
;
2517 piValues
[i
] = pf
->stencil_bits
;
2520 case WGL_AUX_BUFFERS_ARB
:
2521 if (iLayerPlane
) goto invalid_layer
;
2522 piValues
[i
] = pf
->aux_buffers
;
2525 case WGL_SAMPLE_BUFFERS_ARB
:
2526 if (iLayerPlane
) goto invalid_layer
;
2527 piValues
[i
] = pf
->sample_buffers
;
2530 case WGL_SAMPLES_ARB
:
2531 if (iLayerPlane
) goto invalid_layer
;
2532 piValues
[i
] = pf
->samples
;
2535 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2536 if (iLayerPlane
) goto invalid_layer
;
2537 /* sRGB is only supported for 8-bit integer color components */
2538 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2539 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2540 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2541 !color_modes
[pf
->color_mode
].is_float
)
2542 piValues
[i
] = GL_TRUE
;
2544 piValues
[i
] = GL_FALSE
;
2547 case WGL_DRAW_TO_PBUFFER_ARB
:
2548 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2549 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2550 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2553 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2554 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2555 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2558 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2559 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2562 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2563 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2566 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2567 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2571 WARN("invalid attribute %x\n", piAttributes
[i
]);
2575 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2581 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2586 /**********************************************************************
2587 * macdrv_wglGetPixelFormatAttribfvARB
2589 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2591 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2592 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2597 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2598 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2600 /* Allocate a temporary array to store integer values */
2601 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2604 ERR("couldn't allocate %d array\n", nAttributes
);
2608 /* Piggy-back on wglGetPixelFormatAttribivARB */
2609 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2614 /* Convert integer values to float. Should also check for attributes
2615 that can give decimal values here */
2616 for (i
= 0; i
< nAttributes
; i
++)
2617 pfValues
[i
] = attr
[i
];
2620 HeapFree(GetProcessHeap(), 0, attr
);
2625 /**********************************************************************
2626 * macdrv_wglGetSwapIntervalEXT
2628 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2630 static int macdrv_wglGetSwapIntervalEXT(void)
2632 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2633 struct macdrv_win_data
*data
;
2639 if ((data
= get_win_data(context
->draw_hwnd
)))
2641 value
= data
->swap_interval
;
2642 release_win_data(data
);
2644 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
2645 set_swap_interval(context
, value
);
2649 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2650 if (err
!= kCGLNoError
)
2652 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2653 err
, CGLErrorString(err
));
2662 /***********************************************************************
2663 * macdrv_wglMakeContextCurrentARB
2665 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2667 * This is not supported directly by OpenGL on the Mac. We emulate it
2668 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2669 * temporarily swap the drawable. This follows the technique used in
2670 * the implementation of Mesa GLX for Apple.
2672 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
2674 struct macdrv_win_data
*data
;
2677 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
2678 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
2682 macdrv_make_context_current(NULL
, NULL
);
2683 NtCurrentTeb()->glContext
= NULL
;
2687 if ((hwnd
= WindowFromDC(draw_hdc
)))
2689 if (!(data
= get_win_data(hwnd
)))
2691 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
2695 if (!data
->pixel_format
)
2697 WARN("no pixel format set\n");
2698 release_win_data(data
);
2699 SetLastError(ERROR_INVALID_HANDLE
);
2702 if (context
->format
!= data
->pixel_format
)
2704 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
2705 release_win_data(data
);
2706 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2710 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
2711 set_swap_interval(context
, data
->swap_interval
);
2713 context
->draw_hwnd
= hwnd
;
2714 context
->draw_view
= data
->gl_view
;
2715 context
->draw_pbuffer
= NULL
;
2716 release_win_data(data
);
2720 struct wgl_pbuffer
*pbuffer
;
2722 EnterCriticalSection(&dc_pbuffers_section
);
2723 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
2726 if (context
->format
!= pbuffer
->format
)
2728 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
2729 LeaveCriticalSection(&dc_pbuffers_section
);
2730 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2735 (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
))
2736 set_swap_interval(context
, 0);
2740 WARN("no window or pbuffer for DC\n");
2741 LeaveCriticalSection(&dc_pbuffers_section
);
2742 SetLastError(ERROR_INVALID_HANDLE
);
2746 context
->draw_hwnd
= NULL
;
2747 context
->draw_view
= NULL
;
2748 context
->draw_pbuffer
= pbuffer
;
2749 LeaveCriticalSection(&dc_pbuffers_section
);
2752 context
->read_view
= NULL
;
2753 context
->read_pbuffer
= NULL
;
2754 if (read_hdc
&& read_hdc
!= draw_hdc
)
2756 if ((hwnd
= WindowFromDC(read_hdc
)))
2758 if ((data
= get_win_data(hwnd
)))
2760 if (data
->gl_view
!= context
->draw_view
)
2761 context
->read_view
= data
->gl_view
;
2762 release_win_data(data
);
2767 EnterCriticalSection(&dc_pbuffers_section
);
2768 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
2769 LeaveCriticalSection(&dc_pbuffers_section
);
2773 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2774 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
2776 make_context_current(context
, FALSE
);
2777 context
->has_been_current
= TRUE
;
2778 NtCurrentTeb()->glContext
= context
;
2784 /**********************************************************************
2785 * macdrv_wglQueryPbufferARB
2787 * WGL_ARB_pbuffer: wglQueryPbufferARB
2789 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
2795 GLenum internalFormat
;
2798 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
2800 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
2801 if (err
!= kCGLNoError
)
2803 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
2804 SetLastError(ERROR_INVALID_HANDLE
);
2810 case WGL_PBUFFER_WIDTH_ARB
:
2813 case WGL_PBUFFER_HEIGHT_ARB
:
2816 case WGL_PBUFFER_LOST_ARB
:
2817 /* Mac PBuffers can't be lost */
2818 *piValue
= GL_FALSE
;
2820 case WGL_TEXTURE_FORMAT_ARB
:
2821 if (pbuffer
->no_texture
)
2822 *piValue
= WGL_NO_TEXTURE_ARB
;
2823 else switch (internalFormat
)
2826 *piValue
= WGL_TEXTURE_RGBA_ARB
;
2830 *piValue
= WGL_TEXTURE_RGB_ARB
;
2834 case WGL_TEXTURE_TARGET_ARB
:
2835 if (pbuffer
->no_texture
)
2836 *piValue
= WGL_NO_TEXTURE_ARB
;
2837 else switch (target
)
2839 case GL_TEXTURE_CUBE_MAP
:
2840 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
2843 *piValue
= WGL_TEXTURE_2D_ARB
;
2845 case GL_TEXTURE_RECTANGLE
:
2847 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
2851 case WGL_MIPMAP_TEXTURE_ARB
:
2852 *piValue
= (pbuffer
->max_level
> 0);
2854 case WGL_MIPMAP_LEVEL_ARB
:
2855 *piValue
= pbuffer
->level
;
2857 case WGL_CUBE_MAP_FACE_ARB
:
2858 switch (pbuffer
->face
)
2860 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
2862 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
2864 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
2865 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
2867 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
2868 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
2870 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
2871 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
2873 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
2874 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
2876 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
2877 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
2882 WARN("invalid attribute 0x%x\n", iAttribute
);
2883 SetLastError(ERROR_INVALID_DATA
);
2891 /**********************************************************************
2892 * macdrv_wglReleasePbufferDCARB
2894 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2896 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
2898 struct wgl_pbuffer
*prev
;
2900 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
2902 EnterCriticalSection(&dc_pbuffers_section
);
2904 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2907 if (prev
!= pbuffer
)
2908 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
2909 CGLReleasePBuffer(prev
->pbuffer
);
2910 HeapFree(GetProcessHeap(), 0, prev
);
2911 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
2915 LeaveCriticalSection(&dc_pbuffers_section
);
2917 return hdc
&& DeleteDC(hdc
);
2921 /**********************************************************************
2922 * macdrv_wglReleaseTexImageARB
2924 * WGL_ARB_render_texture: wglReleaseTexImageARB
2926 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2928 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2931 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
2933 if (pbuffer
->no_texture
)
2935 SetLastError(ERROR_INVALID_OPERATION
);
2939 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
2940 if (err
!= kCGLNoError
)
2942 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2943 SetLastError(ERROR_INVALID_OPERATION
);
2951 /**********************************************************************
2952 * macdrv_wglSetPbufferAttribARB
2954 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2956 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
2958 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2960 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
2962 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2964 int attr
= piAttribList
[0];
2965 int value
= piAttribList
[1];
2968 case WGL_MIPMAP_LEVEL_ARB
:
2969 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
2970 pbuffer
->level
= value
;
2972 case WGL_CUBE_MAP_FACE_ARB
:
2975 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
2976 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2977 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2979 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
2980 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2981 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
2983 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
2984 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2985 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
2987 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
2988 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2989 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
2991 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
2992 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2993 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
2995 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
2996 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2997 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
3000 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
3001 SetLastError(ERROR_INVALID_DATA
);
3006 WARN("invalide attribute 0x%x\n", attr
);
3007 SetLastError(ERROR_INVALID_DATA
);
3012 if (context
&& context
->draw_pbuffer
== pbuffer
)
3013 make_context_current(context
, FALSE
);
3019 /**********************************************************************
3020 * macdrv_wglSetPixelFormatWINE
3022 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3024 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
3026 return set_pixel_format(hdc
, fmt
, TRUE
);
3030 /**********************************************************************
3031 * macdrv_wglSwapIntervalEXT
3033 * WGL_EXT_swap_control: wglSwapIntervalEXT
3035 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
3037 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3038 BOOL changed
= FALSE
;
3040 TRACE("interval %d\n", interval
);
3044 SetLastError(ERROR_INVALID_DATA
);
3050 if (context
->draw_hwnd
)
3052 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
3055 changed
= data
->swap_interval
!= interval
;
3057 data
->swap_interval
= interval
;
3058 release_win_data(data
);
3064 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
3065 if (!set_swap_interval(context
, interval
))
3067 SetLastError(ERROR_GEN_FAILURE
);
3073 struct wgl_context
*ctx
;
3075 EnterCriticalSection(&context_section
);
3076 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
3078 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
3079 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3081 LeaveCriticalSection(&context_section
);
3088 static void register_extension(const char *ext
)
3090 if (gl_info
.wglExtensions
[0])
3091 strcat(gl_info
.wglExtensions
, " ");
3092 strcat(gl_info
.wglExtensions
, ext
);
3094 TRACE("'%s'\n", ext
);
3097 static void load_extensions(void)
3102 register_extension("WGL_ARB_extensions_string");
3103 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
3105 register_extension("WGL_ARB_make_current_read");
3106 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
3107 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
3109 register_extension("WGL_ARB_pixel_format");
3110 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
3111 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
3112 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
3114 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
3116 register_extension("WGL_ARB_pixel_format_float");
3117 register_extension("WGL_ATI_pixel_format_float");
3120 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
3121 register_extension("WGL_ARB_multisample");
3123 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3124 register_extension("WGL_ARB_framebuffer_sRGB");
3126 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
3128 register_extension("WGL_ARB_pbuffer");
3129 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3130 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3131 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3132 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3133 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3135 register_extension("WGL_ARB_render_texture");
3136 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3137 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3138 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3140 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3141 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3142 register_extension("WGL_NV_render_texture_rectangle");
3146 WGL_ARB_create_context: wglCreateContextAttribsARB
3147 WGL_ARB_create_context_profile
3153 register_extension("WGL_EXT_extensions_string");
3154 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3158 register_extension("WGL_EXT_swap_control");
3159 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3160 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3163 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3164 check for either, so register them separately. */
3165 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3166 register_extension("WGL_EXT_framebuffer_sRGB");
3168 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3169 register_extension("WGL_EXT_pixel_format_packed_float");
3172 * WINE-specific WGL Extensions
3175 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3176 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3178 register_extension("WGL_WINE_pixel_format_passthrough");
3179 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3183 static BOOL
init_opengl(void)
3185 static BOOL init_done
= FALSE
;
3189 if (init_done
) return (opengl_handle
!= NULL
);
3194 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3197 WARN("CFDictionaryCreateMutable failed\n");
3201 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3204 ERR("Failed to load OpenGL: %s\n", buffer
);
3205 ERR("OpenGL support is disabled.\n");
3209 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3211 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3213 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3218 /* redirect some standard OpenGL functions */
3219 #define REDIRECT(func) \
3220 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3221 REDIRECT(glCopyPixels
);
3222 REDIRECT(glGetString
);
3223 REDIRECT(glReadPixels
);
3224 REDIRECT(glViewport
);
3225 if (skip_single_buffer_flushes
|| allow_vsync
)
3231 /* redirect some OpenGL extension functions */
3232 #define REDIRECT(func) \
3233 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3234 REDIRECT(glCopyColorTable
);
3237 if (!init_gl_info())
3240 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3241 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3244 if (!init_pixel_formats())
3250 wine_dlclose(opengl_handle
, NULL
, 0);
3251 opengl_handle
= NULL
;
3256 /***********************************************************************
3259 * Synchronize the Mac GL view position with the Windows child window
3262 void sync_gl_view(struct macdrv_win_data
*data
)
3266 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3268 if (!data
->gl_view
) return;
3270 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3272 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3273 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3274 data
->gl_rect
= rect
;
3279 static int get_dc_pixel_format(HDC hdc
)
3284 if ((hwnd
= WindowFromDC(hdc
)))
3286 struct macdrv_win_data
*data
;
3288 if (!(data
= get_win_data(hwnd
)))
3290 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
3294 format
= data
->pixel_format
;
3295 release_win_data(data
);
3299 struct wgl_pbuffer
*pbuffer
;
3301 EnterCriticalSection(&dc_pbuffers_section
);
3302 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3304 format
= pbuffer
->format
;
3307 WARN("no window or pbuffer for DC %p\n", hdc
);
3310 LeaveCriticalSection(&dc_pbuffers_section
);
3317 /**********************************************************************
3320 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
)
3322 const pixel_format
*pf
;
3323 CGLPixelFormatAttribute attribs
[64];
3325 CGLPixelFormatObj pix
;
3326 GLint virtualScreens
;
3329 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
3332 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
3333 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3337 attribs
[n
++] = kCGLPFAMinimumPolicy
;
3338 attribs
[n
++] = kCGLPFAClosestPolicy
;
3340 if (pf
->accelerated
)
3342 attribs
[n
++] = kCGLPFAAccelerated
;
3343 attribs
[n
++] = kCGLPFANoRecovery
;
3347 attribs
[n
++] = kCGLPFARendererID
;
3348 attribs
[n
++] = kCGLRendererGenericFloatID
;
3351 if (pf
->double_buffer
)
3352 attribs
[n
++] = kCGLPFADoubleBuffer
;
3354 attribs
[n
++] = kCGLPFAAuxBuffers
;
3355 attribs
[n
++] = pf
->aux_buffers
;
3357 attribs
[n
++] = kCGLPFAColorSize
;
3358 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
3359 attribs
[n
++] = kCGLPFAAlphaSize
;
3360 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
3361 if (color_modes
[pf
->color_mode
].is_float
)
3362 attribs
[n
++] = kCGLPFAColorFloat
;
3364 attribs
[n
++] = kCGLPFADepthSize
;
3365 attribs
[n
++] = pf
->depth_bits
;
3367 attribs
[n
++] = kCGLPFAStencilSize
;
3368 attribs
[n
++] = pf
->stencil_bits
;
3371 attribs
[n
++] = kCGLPFAStereo
;
3375 attribs
[n
++] = kCGLPFAAccumSize
;
3376 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3380 attribs
[n
++] = kCGLPFAWindow
;
3382 attribs
[n
++] = kCGLPFAPBuffer
;
3384 if (pf
->sample_buffers
&& pf
->samples
)
3386 attribs
[n
++] = kCGLPFASampleBuffers
;
3387 attribs
[n
++] = pf
->sample_buffers
;
3388 attribs
[n
++] = kCGLPFASamples
;
3389 attribs
[n
++] = pf
->samples
;
3392 if (pf
->backing_store
)
3393 attribs
[n
++] = kCGLPFABackingStore
;
3397 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
3398 if (err
!= kCGLNoError
|| !pix
)
3400 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
3404 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
3405 CGLReleasePixelFormat(pix
);
3406 if (err
!= kCGLNoError
|| !context
->cglcontext
)
3408 context
->cglcontext
= NULL
;
3409 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
3413 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
3414 CGLReleaseContext(context
->cglcontext
);
3415 if (!context
->context
)
3417 WARN("macdrv_create_opengl_context() failed\n");
3422 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3424 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3430 /**********************************************************************
3431 * macdrv_wglDescribePixelFormat
3433 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3435 const pixel_format
*pf
;
3436 const struct color_mode
*mode
;
3438 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3440 if (!descr
) return nb_displayable_formats
;
3441 if (size
< sizeof(*descr
)) return 0;
3443 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3446 memset(descr
, 0, sizeof(*descr
));
3447 descr
->nSize
= sizeof(*descr
);
3448 descr
->nVersion
= 1;
3450 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3451 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3452 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3453 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3454 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3455 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3457 descr
->iPixelType
= PFD_TYPE_RGBA
;
3459 mode
= &color_modes
[pf
->color_mode
];
3460 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3461 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3462 R8G8B8A0 pixel format). If an app depends on that and expects that
3463 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3464 if (mode
->alpha_bits
)
3465 descr
->cColorBits
= mode
->color_bits
;
3467 descr
->cColorBits
= mode
->bits_per_pixel
;
3468 descr
->cRedBits
= mode
->red_bits
;
3469 descr
->cRedShift
= mode
->red_shift
;
3470 descr
->cGreenBits
= mode
->green_bits
;
3471 descr
->cGreenShift
= mode
->green_shift
;
3472 descr
->cBlueBits
= mode
->blue_bits
;
3473 descr
->cBlueShift
= mode
->blue_shift
;
3474 descr
->cAlphaBits
= mode
->alpha_bits
;
3475 descr
->cAlphaShift
= mode
->alpha_shift
;
3479 mode
= &color_modes
[pf
->accum_mode
- 1];
3480 descr
->cAccumBits
= mode
->color_bits
;
3481 descr
->cAccumRedBits
= mode
->red_bits
;
3482 descr
->cAccumGreenBits
= mode
->green_bits
;
3483 descr
->cAccumBlueBits
= mode
->blue_bits
;
3484 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3487 descr
->cDepthBits
= pf
->depth_bits
;
3488 descr
->cStencilBits
= pf
->stencil_bits
;
3489 descr
->cAuxBuffers
= pf
->aux_buffers
;
3490 descr
->iLayerType
= PFD_MAIN_PLANE
;
3492 TRACE("%s\n", debugstr_pf(pf
));
3493 return nb_displayable_formats
;
3496 /***********************************************************************
3497 * macdrv_wglCopyContext
3499 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3503 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3505 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3506 if (err
!= kCGLNoError
)
3507 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3508 return (err
== kCGLNoError
);
3511 /***********************************************************************
3512 * macdrv_wglCreateContext
3514 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3517 struct wgl_context
*context
;
3519 TRACE("hdc %p\n", hdc
);
3521 format
= get_dc_pixel_format(hdc
);
3523 if (!is_valid_pixel_format(format
))
3525 ERR("Invalid pixel format %d, expect problems!\n", format
);
3526 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3530 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3532 context
->format
= format
;
3533 if (!create_context(context
, NULL
))
3535 HeapFree(GetProcessHeap(), 0, context
);
3539 EnterCriticalSection(&context_section
);
3540 list_add_tail(&context_list
, &context
->entry
);
3541 LeaveCriticalSection(&context_section
);
3546 /***********************************************************************
3547 * macdrv_wglDeleteContext
3549 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3551 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3553 EnterCriticalSection(&context_section
);
3554 list_remove(&context
->entry
);
3555 LeaveCriticalSection(&context_section
);
3557 macdrv_dispose_opengl_context(context
->context
);
3558 HeapFree(GetProcessHeap(), 0, context
);
3561 /***********************************************************************
3562 * macdrv_wglGetPixelFormat
3564 static int macdrv_wglGetPixelFormat(HDC hdc
)
3568 format
= get_dc_pixel_format(hdc
);
3570 if (!is_valid_pixel_format(format
)) /* not set yet */
3572 else if (!is_displayable_pixel_format(format
))
3574 /* Non-displayable formats can't be used with traditional WGL calls.
3575 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3579 TRACE(" hdc %p -> %d\n", hdc
, format
);
3583 /***********************************************************************
3584 * macdrv_wglGetProcAddress
3586 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3590 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3591 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3597 if (dladdr(ret
, &info
))
3598 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3600 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3604 WARN("failed to find proc %s\n", debugstr_a(proc
));
3608 /***********************************************************************
3609 * macdrv_wglMakeCurrent
3611 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3613 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3614 (context
? context
->cglcontext
: NULL
));
3616 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3619 /**********************************************************************
3620 * macdrv_wglSetPixelFormat
3622 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3624 return set_pixel_format(hdc
, fmt
, FALSE
);
3627 /***********************************************************************
3628 * macdrv_wglShareLists
3630 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3632 macdrv_opengl_context saved_context
;
3633 CGLContextObj saved_cglcontext
;
3635 TRACE("org %p dest %p\n", org
, dest
);
3637 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3638 * at context creation time but in case of WGL it is done using wglShareLists.
3640 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3641 * and when a program requests sharing we recreate the destination context if it hasn't been made
3642 * current or when it hasn't shared display lists before.
3645 if (dest
->has_been_current
)
3647 WARN("could not share display lists, the destination context has been current already\n");
3650 else if (dest
->sharing
)
3652 WARN("could not share display lists because dest has already shared lists before\n");
3656 /* Re-create the Mac context and share display lists */
3657 saved_context
= dest
->context
;
3658 saved_cglcontext
= dest
->cglcontext
;
3659 dest
->context
= NULL
;
3660 dest
->cglcontext
= NULL
;
3661 if (!create_context(dest
, org
->cglcontext
))
3663 dest
->context
= saved_context
;
3664 dest
->cglcontext
= saved_cglcontext
;
3668 /* Implicitly disposes of saved_cglcontext. */
3669 macdrv_dispose_opengl_context(saved_context
);
3671 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3672 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3674 org
->sharing
= TRUE
;
3675 dest
->sharing
= TRUE
;
3680 /**********************************************************************
3681 * macdrv_wglSwapBuffers
3683 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3685 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3689 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3690 (context
? context
->cglcontext
: NULL
));
3693 sync_swap_interval(context
);
3695 if ((hwnd
= WindowFromDC(hdc
)))
3697 struct macdrv_win_data
*data
;
3699 if (!(data
= get_win_data(hwnd
)))
3701 SetLastError(ERROR_INVALID_HANDLE
);
3705 if (context
&& context
->draw_view
== data
->gl_view
)
3708 release_win_data(data
);
3712 struct wgl_pbuffer
*pbuffer
;
3714 EnterCriticalSection(&dc_pbuffers_section
);
3715 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3716 LeaveCriticalSection(&dc_pbuffers_section
);
3720 SetLastError(ERROR_INVALID_HANDLE
);
3724 if (context
&& context
->draw_pbuffer
== pbuffer
)
3729 macdrv_flush_opengl_context(context
->context
);
3732 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3734 /* If there is a current context, then wglSwapBuffers should do an implicit
3735 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3736 in the other branch, but we have to do it explicitly here. */
3744 static struct opengl_funcs opengl_funcs
=
3747 macdrv_wglCopyContext
, /* p_wglCopyContext */
3748 macdrv_wglCreateContext
, /* p_wglCreateContext */
3749 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3750 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3751 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3752 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3753 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3754 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3755 macdrv_wglShareLists
, /* p_wglShareLists */
3756 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3760 /**********************************************************************
3761 * macdrv_wine_get_wgl_driver
3763 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3765 if (version
!= WINE_WGL_DRIVER_VERSION
)
3767 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3771 if (!init_opengl()) return (void *)-1;
3773 return &opengl_funcs
;