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 macdrv_window cocoa_window
;
1316 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1318 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1320 ERR("no top-level parent with Cocoa window in this process\n");
1324 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
1325 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
));
1336 data
->pixel_format
= format
;
1342 /**********************************************************************
1345 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1347 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1349 struct macdrv_win_data
*data
;
1350 const pixel_format
*pf
;
1351 HWND hwnd
= WindowFromDC(hdc
);
1354 TRACE("hdc %p format %d\n", hdc
, fmt
);
1356 if (!hwnd
|| hwnd
== GetDesktopWindow())
1358 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1362 if (!(data
= get_win_data(hwnd
)))
1364 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1368 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1370 ret
= (data
->pixel_format
== fmt
);
1374 /* Check if fmt is in our list of supported formats to see if it is supported. */
1375 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1378 ERR("Invalid pixel format: %d\n", fmt
);
1384 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1388 if (!set_win_format(data
, fmt
))
1390 WARN("Couldn't set format of the window, returning failure\n");
1394 TRACE("pixel format:\n");
1395 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1396 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1397 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1398 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1399 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1400 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1401 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1402 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1403 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1404 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1405 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1406 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1407 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1408 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1412 release_win_data(data
);
1413 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1418 /**********************************************************************
1419 * set_gl_view_parent
1421 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1423 struct macdrv_win_data
*data
;
1425 if (!(data
= get_win_data(hwnd
))) return;
1429 macdrv_window cocoa_window
;
1431 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1433 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1435 ERR("no top-level parent with Cocoa window in this process\n");
1436 macdrv_dispose_view(data
->gl_view
);
1437 data
->gl_view
= NULL
;
1438 release_win_data(data
);
1439 __wine_set_pixel_format( hwnd
, 0 );
1443 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1446 release_win_data(data
);
1450 /**********************************************************************
1451 * make_context_current
1453 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1456 struct wgl_pbuffer
*pbuffer
;
1460 view
= context
->read_view
;
1461 pbuffer
= context
->read_pbuffer
;
1465 view
= context
->draw_view
;
1466 pbuffer
= context
->draw_pbuffer
;
1469 if (view
|| !pbuffer
)
1470 macdrv_make_context_current(context
->context
, view
);
1473 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1475 CGLSetCurrentContext(context
->cglcontext
);
1480 /**********************************************************************
1483 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1487 /* In theory, for single-buffered contexts, there's no such thing as a swap
1488 so the swap interval shouldn't matter. But OS X will synchronize flushes
1489 of single-buffered contexts if the interval is set to non-zero. */
1490 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1493 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1494 if (err
!= kCGLNoError
)
1495 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1497 return err
== kCGLNoError
;
1501 /**********************************************************************
1502 * sync_swap_interval
1504 static void sync_swap_interval(struct wgl_context
*context
)
1506 struct macdrv_win_data
*data
;
1508 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) &&
1509 (data
= get_win_data(context
->draw_hwnd
)))
1511 set_swap_interval(context
, data
->swap_interval
);
1512 release_win_data(data
);
1517 /**********************************************************************
1518 * macdrv_glCopyColorTable
1520 * Hook into glCopyColorTable as part of the implementation of
1521 * wglMakeContextCurrentARB. If the context has a separate readable,
1522 * temporarily make that current, do glCopyColorTable, and then set it
1523 * back to the drawable. This is modeled after what Mesa GLX's Apple
1524 * implementation does.
1526 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1529 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1531 if (context
->read_view
|| context
->read_pbuffer
)
1532 make_context_current(context
, TRUE
);
1534 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1536 if (context
->read_view
|| context
->read_pbuffer
)
1537 make_context_current(context
, FALSE
);
1541 /**********************************************************************
1542 * macdrv_glCopyPixels
1544 * Hook into glCopyPixels as part of the implementation of
1545 * wglMakeContextCurrentARB. If the context has a separate readable,
1546 * temporarily make that current, do glCopyPixels, and then set it back
1547 * to the drawable. This is modeled after what Mesa GLX's Apple
1548 * implementation does.
1550 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1552 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1554 if (context
->read_view
|| context
->read_pbuffer
)
1555 make_context_current(context
, TRUE
);
1557 pglCopyPixels(x
, y
, width
, height
, type
);
1559 if (context
->read_view
|| context
->read_pbuffer
)
1560 make_context_current(context
, FALSE
);
1564 /**********************************************************************
1567 static void macdrv_glFinish(void)
1569 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1571 sync_swap_interval(context
);
1576 /**********************************************************************
1579 static void macdrv_glFlush(void)
1581 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1583 sync_swap_interval(context
);
1585 if (skip_single_buffer_flushes
)
1587 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1588 DWORD now
= GetTickCount();
1590 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1591 context
->last_flush_time
, now
);
1592 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1594 TRACE("calling glFlushRenderAPPLE()\n");
1595 pglFlushRenderAPPLE();
1600 TRACE("calling glFlush()\n");
1601 context
->last_flush_time
= now
;
1609 /**********************************************************************
1610 * macdrv_glGetString
1612 * Hook into glGetString in order to return some legacy WGL extensions
1613 * that couldn't be advertised via the standard
1614 * WGL_ARB_extensions_string mechanism. Some programs, especially
1615 * older ones, expect to find certain older extensions, such as
1616 * WGL_EXT_extensions_string itself, in the standard GL extensions
1617 * string, and won't query any other WGL extensions unless they find
1618 * that particular extension there.
1620 static const GLubyte
*macdrv_glGetString(GLenum name
)
1622 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1623 return (const GLubyte
*)gl_info
.glExtensions
;
1625 return pglGetString(name
);
1629 /**********************************************************************
1630 * macdrv_glReadPixels
1632 * Hook into glReadPixels as part of the implementation of
1633 * wglMakeContextCurrentARB. If the context has a separate readable,
1634 * temporarily make that current, do glReadPixels, and then set it back
1635 * to the drawable. This is modeled after what Mesa GLX's Apple
1636 * implementation does.
1638 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1639 GLenum format
, GLenum type
, void *pixels
)
1641 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1643 if (context
->read_view
|| context
->read_pbuffer
)
1644 make_context_current(context
, TRUE
);
1646 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1648 if (context
->read_view
|| context
->read_pbuffer
)
1649 make_context_current(context
, FALSE
);
1653 /**********************************************************************
1656 * Hook into glViewport as an opportunity to update the OpenGL context
1657 * if necessary. This is modeled after what Mesa GLX's Apple
1658 * implementation does.
1660 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1662 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1664 macdrv_update_opengl_context(context
->context
);
1665 pglViewport(x
, y
, width
, height
);
1669 /***********************************************************************
1670 * macdrv_wglBindTexImageARB
1672 * WGL_ARB_render_texture: wglBindTexImageARB
1674 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1676 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1680 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1682 if (pbuffer
->no_texture
)
1684 SetLastError(ERROR_INVALID_OPERATION
);
1688 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1689 opengl_funcs
.gl
.p_glFlush();
1693 case WGL_FRONT_LEFT_ARB
:
1694 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1695 source
= GL_FRONT_LEFT
;
1699 case WGL_FRONT_RIGHT_ARB
:
1700 source
= GL_FRONT_RIGHT
;
1702 case WGL_BACK_LEFT_ARB
:
1703 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1704 source
= GL_BACK_LEFT
;
1708 case WGL_BACK_RIGHT_ARB
:
1709 source
= GL_BACK_RIGHT
;
1711 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1712 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1713 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1714 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1722 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1723 SetLastError(ERROR_INVALID_DATA
);
1727 WARN("unknown source buffer 0x%x\n", iBuffer
);
1728 SetLastError(ERROR_INVALID_DATA
);
1732 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1733 if (err
!= kCGLNoError
)
1735 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1736 SetLastError(ERROR_INVALID_OPERATION
);
1744 /***********************************************************************
1745 * macdrv_wglChoosePixelFormatARB
1747 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1749 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1750 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1751 int *piFormats
, UINT
*nNumFormats
)
1753 pixel_format pf
, valid
;
1755 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1756 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
1761 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1762 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
1764 FIXME("unused pfAttribFList\n");
1766 memset(&pf
, 0, sizeof(pf
));
1767 memset(&valid
, 0, sizeof(valid
));
1768 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
1769 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
1773 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
1776 int value
= iptr
[1];
1778 TRACE("%s\n", debugstr_attrib(attr
, value
));
1782 case WGL_DRAW_TO_WINDOW_ARB
:
1783 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
1784 pf
.window
= (value
!= 0);
1788 case WGL_DRAW_TO_BITMAP_ARB
:
1791 case WGL_ACCELERATION_ARB
:
1792 if (value
== WGL_FULL_ACCELERATION_ARB
)
1794 else if (value
== WGL_NO_ACCELERATION_ARB
)
1798 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
1799 pf
.accelerated
= value
;
1800 valid
.accelerated
= 1;
1803 case WGL_NEED_PALETTE_ARB
:
1804 case WGL_NEED_SYSTEM_PALETTE_ARB
:
1805 case WGL_SWAP_LAYER_BUFFERS_ARB
:
1806 if (value
) goto cant_match
;
1809 case WGL_SWAP_METHOD_ARB
:
1810 if (value
== WGL_SWAP_COPY_ARB
)
1812 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
1816 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
1817 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
1818 pf
.backing_store
= value
;
1819 valid
.backing_store
= 1;
1822 case WGL_NUMBER_OVERLAYS_ARB
:
1823 case WGL_NUMBER_UNDERLAYS_ARB
:
1824 if (value
) goto cant_match
;
1827 case WGL_SHARE_DEPTH_ARB
:
1828 case WGL_SHARE_STENCIL_ARB
:
1829 case WGL_SHARE_ACCUM_ARB
:
1833 case WGL_SUPPORT_GDI_ARB
:
1834 if (value
) goto cant_match
;
1837 case WGL_SUPPORT_OPENGL_ARB
:
1838 if (!value
) goto cant_match
;
1841 case WGL_DOUBLE_BUFFER_ARB
:
1842 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
1843 pf
.double_buffer
= (value
!= 0);
1844 valid
.double_buffer
= 1;
1845 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
1848 case WGL_STEREO_ARB
:
1849 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
1850 pf
.stereo
= (value
!= 0);
1854 case WGL_PIXEL_TYPE_ARB
:
1855 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
1857 else if (value
== WGL_TYPE_RGBA_ARB
)
1861 /* Mac contexts don't support rendering to unsigned floating
1862 point formats, even if GL_EXT_packed_float is supported.
1863 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1866 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
1867 if (srgb
&& value
) goto cant_match
;
1868 float_color
= value
;
1871 case WGL_COLOR_BITS_ARB
:
1872 if (color_bits
< value
) color_bits
= value
;
1875 case WGL_RED_BITS_ARB
:
1876 if (srgb
&& value
> 8) goto cant_match
;
1877 if (red_bits
< value
) red_bits
= value
;
1880 case WGL_GREEN_BITS_ARB
:
1881 if (srgb
&& value
> 8) goto cant_match
;
1882 if (green_bits
< value
) green_bits
= value
;
1885 case WGL_BLUE_BITS_ARB
:
1886 if (srgb
&& value
> 8) goto cant_match
;
1887 if (blue_bits
< value
) blue_bits
= value
;
1890 case WGL_ALPHA_BITS_ARB
:
1891 if (alpha_bits
< value
) alpha_bits
= value
;
1894 case WGL_ACCUM_BITS_ARB
:
1895 if (accum_bits
< value
) accum_bits
= value
;
1898 case WGL_ACCUM_RED_BITS_ARB
:
1899 if (accum_red_bits
< value
) accum_red_bits
= value
;
1902 case WGL_ACCUM_GREEN_BITS_ARB
:
1903 if (accum_green_bits
< value
) accum_green_bits
= value
;
1906 case WGL_ACCUM_BLUE_BITS_ARB
:
1907 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
1910 case WGL_ACCUM_ALPHA_BITS_ARB
:
1911 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
1914 case WGL_DEPTH_BITS_ARB
:
1915 if (value
> 255) goto cant_match
;
1916 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
1919 case WGL_STENCIL_BITS_ARB
:
1920 if (value
> 255) goto cant_match
;
1921 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
1924 case WGL_AUX_BUFFERS_ARB
:
1925 if (value
> 7) goto cant_match
;
1926 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
1929 case WGL_SAMPLE_BUFFERS_ARB
:
1930 if (value
> 1) goto cant_match
;
1931 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
1934 case WGL_SAMPLES_ARB
:
1935 if (value
> 31) goto cant_match
;
1936 if (pf
.samples
< value
) pf
.samples
= value
;
1939 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1940 /* sRGB is only supported for 8-bit integer color components */
1941 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
1946 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
1947 case WGL_RED_SHIFT_ARB
:
1948 case WGL_GREEN_SHIFT_ARB
:
1949 case WGL_BLUE_SHIFT_ARB
:
1950 case WGL_ALPHA_SHIFT_ARB
:
1951 case WGL_TRANSPARENT_ARB
:
1952 case WGL_TRANSPARENT_RED_VALUE_ARB
:
1953 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
1954 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
1955 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
1956 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
1960 case WGL_DRAW_TO_PBUFFER_ARB
:
1961 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
1962 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
1963 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
1964 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
1965 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
1966 pf
.pbuffer
= (value
!= 0);
1968 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
1974 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
1979 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",
1980 valid
.window
? (pf
.window
? "1" : "0") : "?",
1981 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
1982 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
1984 float_color
== -1 ? "?" : float_color
? "f" : "",
1998 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
1999 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2000 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2004 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2006 const struct color_mode
*mode
;
2008 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2009 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2010 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2011 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2012 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2013 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2015 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2016 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2017 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2018 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2019 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2021 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2022 /* If the mode doesn't have alpha, check requested color bits against
2023 bits per pixel instead of the mode's color bits. On Windows, color
2024 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2025 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2026 expects that to match such a pixel format, we need to accommodate that. */
2027 if (mode
->alpha_bits
)
2029 if (mode
->color_bits
< color_bits
)
2034 if (mode
->bits_per_pixel
< color_bits
)
2037 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2038 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2040 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2041 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2044 if (pixel_formats
[i
].accum_mode
)
2046 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2047 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2048 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2049 mode
->alpha_bits
< accum_alpha_bits
)
2052 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2055 piFormats
[found
++] = i
+ 1;
2056 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2060 *nNumFormats
= found
;
2066 /**********************************************************************
2067 * macdrv_wglCreatePbufferARB
2069 * WGL_ARB_pbuffer: wglCreatePbufferARB
2071 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2072 const int *piAttribList
)
2074 struct wgl_pbuffer
* pbuffer
;
2076 GLenum internalFormat
= 0;
2079 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2080 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2082 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2084 WARN("invalid pixel format %d\n", iPixelFormat
);
2085 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2089 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2090 pbuffer
->format
= iPixelFormat
;
2092 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2094 int attr
= piAttribList
[0];
2095 int value
= piAttribList
[1];
2099 case WGL_PBUFFER_LARGEST_ARB
:
2100 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2103 case WGL_TEXTURE_FORMAT_ARB
:
2106 case WGL_TEXTURE_RGBA_ARB
:
2107 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2108 internalFormat
= GL_RGBA
;
2110 case WGL_TEXTURE_RGB_ARB
:
2111 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2112 internalFormat
= GL_RGB
;
2114 case WGL_NO_TEXTURE_ARB
:
2115 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2119 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2120 SetLastError(ERROR_INVALID_DATA
);
2125 case WGL_TEXTURE_TARGET_ARB
:
2129 case WGL_NO_TEXTURE_ARB
:
2130 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2133 case WGL_TEXTURE_CUBE_MAP_ARB
:
2134 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2135 target
= GL_TEXTURE_CUBE_MAP
;
2136 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2138 case WGL_TEXTURE_1D_ARB
:
2139 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2140 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2142 case WGL_TEXTURE_2D_ARB
:
2143 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2144 target
= GL_TEXTURE_2D
;
2146 case WGL_TEXTURE_RECTANGLE_NV
:
2147 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2148 target
= GL_TEXTURE_RECTANGLE
;
2151 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2152 SetLastError(ERROR_INVALID_DATA
);
2157 case WGL_MIPMAP_TEXTURE_ARB
:
2158 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2159 pbuffer
->max_level
= 0;
2162 int size
= min(iWidth
, iHeight
) / 2;
2165 pbuffer
->max_level
++;
2172 WARN("unknown attribute 0x%x\n", attr
);
2173 SetLastError(ERROR_INVALID_DATA
);
2178 if (!target
|| !internalFormat
)
2180 pbuffer
->no_texture
= TRUE
;
2181 /* no actual way to turn off ability to texture; use most permissive target */
2182 target
= GL_TEXTURE_RECTANGLE
;
2183 internalFormat
= GL_RGB
;
2186 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2187 if (err
!= kCGLNoError
)
2189 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2190 pbuffer
->pbuffer
= NULL
;
2191 if (err
== kCGLBadAlloc
)
2192 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2194 SetLastError(ERROR_INVALID_DATA
);
2198 if (!pbuffer
->pbuffer
)
2200 HeapFree(GetProcessHeap(), 0, pbuffer
);
2204 TRACE(" -> %p\n", pbuffer
);
2209 /**********************************************************************
2210 * macdrv_wglDestroyPbufferARB
2212 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2214 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2216 TRACE("pbuffer %p\n", pbuffer
);
2217 if (pbuffer
&& pbuffer
->pbuffer
)
2218 CGLReleasePBuffer(pbuffer
->pbuffer
);
2219 HeapFree(GetProcessHeap(), 0, pbuffer
);
2224 /**********************************************************************
2225 * macdrv_wglGetExtensionsStringARB
2227 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2229 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2231 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2232 this can be specific to the CGL renderer like we're supposed to do. */
2233 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2234 return gl_info
.wglExtensions
;
2238 /**********************************************************************
2239 * macdrv_wglGetExtensionsStringEXT
2241 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2243 static const char *macdrv_wglGetExtensionsStringEXT(void)
2245 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2246 return gl_info
.wglExtensions
;
2250 /**********************************************************************
2251 * macdrv_wglGetPbufferDCARB
2253 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2255 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2258 struct wgl_pbuffer
*prev
;
2260 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2263 EnterCriticalSection(&dc_pbuffers_section
);
2264 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2267 CGLReleasePBuffer(prev
->pbuffer
);
2268 HeapFree(GetProcessHeap(), 0, prev
);
2270 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2271 LeaveCriticalSection(&dc_pbuffers_section
);
2273 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2278 /**********************************************************************
2279 * macdrv_wglGetPixelFormatAttribivARB
2281 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2283 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2284 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2286 const pixel_format
*pf
;
2289 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2290 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2292 if (!nAttributes
) return GL_TRUE
;
2294 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2296 piValues
[0] = nb_formats
;
2297 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2301 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2304 WARN("invalid pixel format %d\n", iPixelFormat
);
2305 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2309 for (i
= 0; i
< nAttributes
; ++i
)
2311 switch (piAttributes
[i
])
2313 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2314 piValues
[i
] = nb_formats
;
2317 case WGL_DRAW_TO_WINDOW_ARB
:
2318 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2321 case WGL_DRAW_TO_BITMAP_ARB
:
2322 piValues
[i
] = GL_FALSE
;
2325 case WGL_ACCELERATION_ARB
:
2326 if (iLayerPlane
) goto invalid_layer
;
2327 if (pf
->accelerated
)
2328 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2330 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2333 case WGL_NEED_PALETTE_ARB
:
2334 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2335 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2336 piValues
[i
] = GL_FALSE
;
2339 case WGL_SWAP_METHOD_ARB
:
2340 if (pf
->double_buffer
&& pf
->backing_store
)
2341 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2343 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2346 case WGL_NUMBER_OVERLAYS_ARB
:
2347 case WGL_NUMBER_UNDERLAYS_ARB
:
2351 case WGL_TRANSPARENT_ARB
:
2352 if (iLayerPlane
) goto invalid_layer
;
2353 piValues
[i
] = GL_FALSE
;
2356 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2357 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2358 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2359 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2360 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2361 if (iLayerPlane
) goto invalid_layer
;
2365 case WGL_SHARE_DEPTH_ARB
:
2366 case WGL_SHARE_STENCIL_ARB
:
2367 case WGL_SHARE_ACCUM_ARB
:
2368 if (iLayerPlane
) goto invalid_layer
;
2369 piValues
[i
] = GL_TRUE
;
2372 case WGL_SUPPORT_GDI_ARB
:
2373 if (iLayerPlane
) goto invalid_layer
;
2374 piValues
[i
] = GL_FALSE
;
2377 case WGL_SUPPORT_OPENGL_ARB
:
2378 if (iLayerPlane
) goto invalid_layer
;
2379 piValues
[i
] = GL_TRUE
;
2382 case WGL_DOUBLE_BUFFER_ARB
:
2383 if (iLayerPlane
) goto invalid_layer
;
2384 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2387 case WGL_STEREO_ARB
:
2388 if (iLayerPlane
) goto invalid_layer
;
2389 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2392 case WGL_PIXEL_TYPE_ARB
:
2393 if (iLayerPlane
) goto invalid_layer
;
2394 if (color_modes
[pf
->color_mode
].is_float
)
2395 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2397 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2398 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2399 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2400 However, Mac contexts don't support rendering to unsigned floating-point
2401 formats, even when GL_EXT_packed_float is supported. */
2404 case WGL_COLOR_BITS_ARB
:
2405 if (iLayerPlane
) goto invalid_layer
;
2406 /* If the mode doesn't have alpha, return bits per pixel instead
2407 of color bits. On Windows, color bits sometimes exceeds r+g+b
2408 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2409 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2410 pixel format, we need to accommodate that. */
2411 if (color_modes
[pf
->color_mode
].alpha_bits
)
2412 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2414 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2417 case WGL_RED_BITS_ARB
:
2418 if (iLayerPlane
) goto invalid_layer
;
2419 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2422 case WGL_RED_SHIFT_ARB
:
2423 if (iLayerPlane
) goto invalid_layer
;
2424 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2427 case WGL_GREEN_BITS_ARB
:
2428 if (iLayerPlane
) goto invalid_layer
;
2429 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2432 case WGL_GREEN_SHIFT_ARB
:
2433 if (iLayerPlane
) goto invalid_layer
;
2434 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2437 case WGL_BLUE_BITS_ARB
:
2438 if (iLayerPlane
) goto invalid_layer
;
2439 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2442 case WGL_BLUE_SHIFT_ARB
:
2443 if (iLayerPlane
) goto invalid_layer
;
2444 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2447 case WGL_ALPHA_BITS_ARB
:
2448 if (iLayerPlane
) goto invalid_layer
;
2449 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2452 case WGL_ALPHA_SHIFT_ARB
:
2453 if (iLayerPlane
) goto invalid_layer
;
2454 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2457 case WGL_ACCUM_BITS_ARB
:
2458 if (iLayerPlane
) goto invalid_layer
;
2460 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2465 case WGL_ACCUM_RED_BITS_ARB
:
2466 if (iLayerPlane
) goto invalid_layer
;
2468 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2473 case WGL_ACCUM_GREEN_BITS_ARB
:
2474 if (iLayerPlane
) goto invalid_layer
;
2476 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2481 case WGL_ACCUM_BLUE_BITS_ARB
:
2482 if (iLayerPlane
) goto invalid_layer
;
2484 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2489 case WGL_ACCUM_ALPHA_BITS_ARB
:
2490 if (iLayerPlane
) goto invalid_layer
;
2492 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2497 case WGL_DEPTH_BITS_ARB
:
2498 if (iLayerPlane
) goto invalid_layer
;
2499 piValues
[i
] = pf
->depth_bits
;
2502 case WGL_STENCIL_BITS_ARB
:
2503 if (iLayerPlane
) goto invalid_layer
;
2504 piValues
[i
] = pf
->stencil_bits
;
2507 case WGL_AUX_BUFFERS_ARB
:
2508 if (iLayerPlane
) goto invalid_layer
;
2509 piValues
[i
] = pf
->aux_buffers
;
2512 case WGL_SAMPLE_BUFFERS_ARB
:
2513 if (iLayerPlane
) goto invalid_layer
;
2514 piValues
[i
] = pf
->sample_buffers
;
2517 case WGL_SAMPLES_ARB
:
2518 if (iLayerPlane
) goto invalid_layer
;
2519 piValues
[i
] = pf
->samples
;
2522 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2523 if (iLayerPlane
) goto invalid_layer
;
2524 /* sRGB is only supported for 8-bit integer color components */
2525 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2526 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2527 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2528 !color_modes
[pf
->color_mode
].is_float
)
2529 piValues
[i
] = GL_TRUE
;
2531 piValues
[i
] = GL_FALSE
;
2534 case WGL_DRAW_TO_PBUFFER_ARB
:
2535 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2536 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2537 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2540 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2541 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2542 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2545 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2546 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2549 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2550 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2553 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2554 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2558 WARN("invalid attribute %x\n", piAttributes
[i
]);
2562 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2568 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2573 /**********************************************************************
2574 * macdrv_wglGetPixelFormatAttribfvARB
2576 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2578 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2579 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2584 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2585 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2587 /* Allocate a temporary array to store integer values */
2588 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2591 ERR("couldn't allocate %d array\n", nAttributes
);
2595 /* Piggy-back on wglGetPixelFormatAttribivARB */
2596 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2601 /* Convert integer values to float. Should also check for attributes
2602 that can give decimal values here */
2603 for (i
= 0; i
< nAttributes
; i
++)
2604 pfValues
[i
] = attr
[i
];
2607 HeapFree(GetProcessHeap(), 0, attr
);
2612 /**********************************************************************
2613 * macdrv_wglGetSwapIntervalEXT
2615 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2617 static int macdrv_wglGetSwapIntervalEXT(void)
2619 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2620 struct macdrv_win_data
*data
;
2626 if ((data
= get_win_data(context
->draw_hwnd
)))
2628 value
= data
->swap_interval
;
2629 release_win_data(data
);
2631 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
2632 set_swap_interval(context
, value
);
2636 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2637 if (err
!= kCGLNoError
)
2639 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2640 err
, CGLErrorString(err
));
2649 /***********************************************************************
2650 * macdrv_wglMakeContextCurrentARB
2652 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2654 * This is not supported directly by OpenGL on the Mac. We emulate it
2655 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2656 * temporarily swap the drawable. This follows the technique used in
2657 * the implementation of Mesa GLX for Apple.
2659 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
2661 struct macdrv_win_data
*data
;
2664 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
2665 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
2669 macdrv_make_context_current(NULL
, NULL
);
2670 NtCurrentTeb()->glContext
= NULL
;
2674 if ((hwnd
= WindowFromDC(draw_hdc
)))
2676 if (!(data
= get_win_data(hwnd
)))
2678 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
2682 if (!data
->pixel_format
)
2684 WARN("no pixel format set\n");
2685 release_win_data(data
);
2686 SetLastError(ERROR_INVALID_HANDLE
);
2689 if (context
->format
!= data
->pixel_format
)
2691 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
2692 release_win_data(data
);
2693 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2697 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
2698 set_swap_interval(context
, data
->swap_interval
);
2700 context
->draw_hwnd
= hwnd
;
2701 context
->draw_view
= data
->gl_view
;
2702 context
->draw_pbuffer
= NULL
;
2703 release_win_data(data
);
2707 struct wgl_pbuffer
*pbuffer
;
2709 EnterCriticalSection(&dc_pbuffers_section
);
2710 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
2713 if (context
->format
!= pbuffer
->format
)
2715 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
2716 LeaveCriticalSection(&dc_pbuffers_section
);
2717 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2723 WARN("no window or pbuffer for DC\n");
2724 LeaveCriticalSection(&dc_pbuffers_section
);
2725 SetLastError(ERROR_INVALID_HANDLE
);
2729 context
->draw_hwnd
= NULL
;
2730 context
->draw_view
= NULL
;
2731 context
->draw_pbuffer
= pbuffer
;
2732 LeaveCriticalSection(&dc_pbuffers_section
);
2735 context
->read_view
= NULL
;
2736 context
->read_pbuffer
= NULL
;
2737 if (read_hdc
&& read_hdc
!= draw_hdc
)
2739 if ((hwnd
= WindowFromDC(read_hdc
)))
2741 if ((data
= get_win_data(hwnd
)))
2743 if (data
->gl_view
!= context
->draw_view
)
2744 context
->read_view
= data
->gl_view
;
2745 release_win_data(data
);
2750 EnterCriticalSection(&dc_pbuffers_section
);
2751 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
2752 LeaveCriticalSection(&dc_pbuffers_section
);
2756 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2757 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
2759 make_context_current(context
, FALSE
);
2760 context
->has_been_current
= TRUE
;
2761 NtCurrentTeb()->glContext
= context
;
2767 /**********************************************************************
2768 * macdrv_wglQueryPbufferARB
2770 * WGL_ARB_pbuffer: wglQueryPbufferARB
2772 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
2778 GLenum internalFormat
;
2781 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
2783 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
2784 if (err
!= kCGLNoError
)
2786 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
2787 SetLastError(ERROR_INVALID_HANDLE
);
2793 case WGL_PBUFFER_WIDTH_ARB
:
2796 case WGL_PBUFFER_HEIGHT_ARB
:
2799 case WGL_PBUFFER_LOST_ARB
:
2800 /* Mac PBuffers can't be lost */
2801 *piValue
= GL_FALSE
;
2803 case WGL_TEXTURE_FORMAT_ARB
:
2804 if (pbuffer
->no_texture
)
2805 *piValue
= WGL_NO_TEXTURE_ARB
;
2806 else switch (internalFormat
)
2809 *piValue
= WGL_TEXTURE_RGBA_ARB
;
2813 *piValue
= WGL_TEXTURE_RGB_ARB
;
2817 case WGL_TEXTURE_TARGET_ARB
:
2818 if (pbuffer
->no_texture
)
2819 *piValue
= WGL_NO_TEXTURE_ARB
;
2820 else switch (target
)
2822 case GL_TEXTURE_CUBE_MAP
:
2823 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
2826 *piValue
= WGL_TEXTURE_2D_ARB
;
2828 case GL_TEXTURE_RECTANGLE
:
2830 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
2834 case WGL_MIPMAP_TEXTURE_ARB
:
2835 *piValue
= (pbuffer
->max_level
> 0);
2837 case WGL_MIPMAP_LEVEL_ARB
:
2838 *piValue
= pbuffer
->level
;
2840 case WGL_CUBE_MAP_FACE_ARB
:
2841 switch (pbuffer
->face
)
2843 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
2845 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
2847 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
2848 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
2850 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
2851 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
2853 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
2854 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
2856 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
2857 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
2859 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
2860 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
2865 WARN("invalid attribute 0x%x\n", iAttribute
);
2866 SetLastError(ERROR_INVALID_DATA
);
2874 /**********************************************************************
2875 * macdrv_wglReleasePbufferDCARB
2877 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2879 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
2881 struct wgl_pbuffer
*prev
;
2883 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
2885 EnterCriticalSection(&dc_pbuffers_section
);
2887 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2890 if (prev
!= pbuffer
)
2891 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
2892 CGLReleasePBuffer(prev
->pbuffer
);
2893 HeapFree(GetProcessHeap(), 0, prev
);
2894 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
2898 LeaveCriticalSection(&dc_pbuffers_section
);
2900 return hdc
&& DeleteDC(hdc
);
2904 /**********************************************************************
2905 * macdrv_wglReleaseTexImageARB
2907 * WGL_ARB_render_texture: wglReleaseTexImageARB
2909 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2911 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2914 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
2916 if (pbuffer
->no_texture
)
2918 SetLastError(ERROR_INVALID_OPERATION
);
2922 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
2923 if (err
!= kCGLNoError
)
2925 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2926 SetLastError(ERROR_INVALID_OPERATION
);
2934 /**********************************************************************
2935 * macdrv_wglSetPbufferAttribARB
2937 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2939 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
2941 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2943 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
2945 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2947 int attr
= piAttribList
[0];
2948 int value
= piAttribList
[1];
2951 case WGL_MIPMAP_LEVEL_ARB
:
2952 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
2953 pbuffer
->level
= value
;
2955 case WGL_CUBE_MAP_FACE_ARB
:
2958 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
2959 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2960 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2962 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
2963 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2964 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
2966 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
2967 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2968 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
2970 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
2971 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2972 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
2974 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
2975 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2976 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
2978 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
2979 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2980 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
2983 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
2984 SetLastError(ERROR_INVALID_DATA
);
2989 WARN("invalide attribute 0x%x\n", attr
);
2990 SetLastError(ERROR_INVALID_DATA
);
2995 if (context
&& context
->draw_pbuffer
== pbuffer
)
2996 make_context_current(context
, FALSE
);
3002 /**********************************************************************
3003 * macdrv_wglSetPixelFormatWINE
3005 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3007 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
3009 return set_pixel_format(hdc
, fmt
, TRUE
);
3013 /**********************************************************************
3014 * macdrv_wglSwapIntervalEXT
3016 * WGL_EXT_swap_control: wglSwapIntervalEXT
3018 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
3020 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3021 struct macdrv_win_data
*data
;
3023 TRACE("interval %d\n", interval
);
3027 SetLastError(ERROR_INVALID_DATA
);
3033 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
3034 if (!set_swap_interval(context
, interval
))
3036 SetLastError(ERROR_GEN_FAILURE
);
3040 if ((data
= get_win_data(context
->draw_hwnd
)))
3042 BOOL changed
= data
->swap_interval
!= interval
;
3044 data
->swap_interval
= interval
;
3045 release_win_data(data
);
3049 struct wgl_context
*ctx
;
3051 EnterCriticalSection(&context_section
);
3052 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
3054 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
3055 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3057 LeaveCriticalSection(&context_section
);
3065 static void register_extension(const char *ext
)
3067 if (gl_info
.wglExtensions
[0])
3068 strcat(gl_info
.wglExtensions
, " ");
3069 strcat(gl_info
.wglExtensions
, ext
);
3071 TRACE("'%s'\n", ext
);
3074 static void load_extensions(void)
3079 register_extension("WGL_ARB_extensions_string");
3080 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
3082 register_extension("WGL_ARB_make_current_read");
3083 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
3084 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
3086 register_extension("WGL_ARB_pixel_format");
3087 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
3088 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
3089 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
3091 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
3093 register_extension("WGL_ARB_pixel_format_float");
3094 register_extension("WGL_ATI_pixel_format_float");
3097 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
3098 register_extension("WGL_ARB_multisample");
3100 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3101 register_extension("WGL_ARB_framebuffer_sRGB");
3103 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
3105 register_extension("WGL_ARB_pbuffer");
3106 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3107 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3108 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3109 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3110 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3112 register_extension("WGL_ARB_render_texture");
3113 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3114 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3115 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3117 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3118 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3119 register_extension("WGL_NV_render_texture_rectangle");
3123 WGL_ARB_create_context: wglCreateContextAttribsARB
3124 WGL_ARB_create_context_profile
3130 register_extension("WGL_EXT_extensions_string");
3131 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3135 register_extension("WGL_EXT_swap_control");
3136 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3137 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3140 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3141 check for either, so register them separately. */
3142 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3143 register_extension("WGL_EXT_framebuffer_sRGB");
3145 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3146 register_extension("WGL_EXT_pixel_format_packed_float");
3149 * WINE-specific WGL Extensions
3152 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3153 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3155 register_extension("WGL_WINE_pixel_format_passthrough");
3156 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3160 static BOOL
init_opengl(void)
3162 static BOOL init_done
= FALSE
;
3166 if (init_done
) return (opengl_handle
!= NULL
);
3171 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3174 WARN("CFDictionaryCreateMutable failed\n");
3178 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3181 ERR("Failed to load OpenGL: %s\n", buffer
);
3182 ERR("OpenGL support is disabled.\n");
3186 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3188 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3190 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3195 /* redirect some standard OpenGL functions */
3196 #define REDIRECT(func) \
3197 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3198 REDIRECT(glCopyPixels
);
3199 REDIRECT(glGetString
);
3200 REDIRECT(glReadPixels
);
3201 REDIRECT(glViewport
);
3202 if (skip_single_buffer_flushes
|| allow_vsync
)
3208 /* redirect some OpenGL extension functions */
3209 #define REDIRECT(func) \
3210 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3211 REDIRECT(glCopyColorTable
);
3214 if (!init_gl_info())
3217 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3218 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3221 if (!init_pixel_formats())
3227 wine_dlclose(opengl_handle
, NULL
, 0);
3228 opengl_handle
= NULL
;
3233 /***********************************************************************
3236 * Synchronize the Mac GL view position with the Windows child window
3239 void sync_gl_view(struct macdrv_win_data
*data
)
3243 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3245 if (!data
->gl_view
) return;
3247 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3249 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3250 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3251 data
->gl_rect
= rect
;
3256 static int get_dc_pixel_format(HDC hdc
)
3261 if ((hwnd
= WindowFromDC(hdc
)))
3263 struct macdrv_win_data
*data
;
3265 if (!(data
= get_win_data(hwnd
)))
3267 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
3271 format
= data
->pixel_format
;
3272 release_win_data(data
);
3276 struct wgl_pbuffer
*pbuffer
;
3278 EnterCriticalSection(&dc_pbuffers_section
);
3279 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3281 format
= pbuffer
->format
;
3284 WARN("no window or pbuffer for DC %p\n", hdc
);
3287 LeaveCriticalSection(&dc_pbuffers_section
);
3294 /**********************************************************************
3297 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
)
3299 const pixel_format
*pf
;
3300 CGLPixelFormatAttribute attribs
[64];
3302 CGLPixelFormatObj pix
;
3303 GLint virtualScreens
;
3306 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
3309 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
3310 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3314 attribs
[n
++] = kCGLPFAMinimumPolicy
;
3315 attribs
[n
++] = kCGLPFAClosestPolicy
;
3317 if (pf
->accelerated
)
3319 attribs
[n
++] = kCGLPFAAccelerated
;
3320 attribs
[n
++] = kCGLPFANoRecovery
;
3324 attribs
[n
++] = kCGLPFARendererID
;
3325 attribs
[n
++] = kCGLRendererGenericFloatID
;
3328 if (pf
->double_buffer
)
3329 attribs
[n
++] = kCGLPFADoubleBuffer
;
3331 attribs
[n
++] = kCGLPFAAuxBuffers
;
3332 attribs
[n
++] = pf
->aux_buffers
;
3334 attribs
[n
++] = kCGLPFAColorSize
;
3335 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
3336 attribs
[n
++] = kCGLPFAAlphaSize
;
3337 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
3338 if (color_modes
[pf
->color_mode
].is_float
)
3339 attribs
[n
++] = kCGLPFAColorFloat
;
3341 attribs
[n
++] = kCGLPFADepthSize
;
3342 attribs
[n
++] = pf
->depth_bits
;
3344 attribs
[n
++] = kCGLPFAStencilSize
;
3345 attribs
[n
++] = pf
->stencil_bits
;
3348 attribs
[n
++] = kCGLPFAStereo
;
3352 attribs
[n
++] = kCGLPFAAccumSize
;
3353 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3357 attribs
[n
++] = kCGLPFAWindow
;
3359 attribs
[n
++] = kCGLPFAPBuffer
;
3361 if (pf
->sample_buffers
&& pf
->samples
)
3363 attribs
[n
++] = kCGLPFASampleBuffers
;
3364 attribs
[n
++] = pf
->sample_buffers
;
3365 attribs
[n
++] = kCGLPFASamples
;
3366 attribs
[n
++] = pf
->samples
;
3369 if (pf
->backing_store
)
3370 attribs
[n
++] = kCGLPFABackingStore
;
3374 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
3375 if (err
!= kCGLNoError
|| !pix
)
3377 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
3381 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
3382 CGLReleasePixelFormat(pix
);
3383 if (err
!= kCGLNoError
|| !context
->cglcontext
)
3385 context
->cglcontext
= NULL
;
3386 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
3390 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
3391 CGLReleaseContext(context
->cglcontext
);
3392 if (!context
->context
)
3394 WARN("macdrv_create_opengl_context() failed\n");
3399 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3401 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3407 /**********************************************************************
3408 * macdrv_wglDescribePixelFormat
3410 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3412 const pixel_format
*pf
;
3413 const struct color_mode
*mode
;
3415 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3417 if (!descr
) return nb_displayable_formats
;
3418 if (size
< sizeof(*descr
)) return 0;
3420 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3423 memset(descr
, 0, sizeof(*descr
));
3424 descr
->nSize
= sizeof(*descr
);
3425 descr
->nVersion
= 1;
3427 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3428 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3429 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3430 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3431 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3432 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3434 descr
->iPixelType
= PFD_TYPE_RGBA
;
3436 mode
= &color_modes
[pf
->color_mode
];
3437 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3438 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3439 R8G8B8A0 pixel format). If an app depends on that and expects that
3440 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3441 if (mode
->alpha_bits
)
3442 descr
->cColorBits
= mode
->color_bits
;
3444 descr
->cColorBits
= mode
->bits_per_pixel
;
3445 descr
->cRedBits
= mode
->red_bits
;
3446 descr
->cRedShift
= mode
->red_shift
;
3447 descr
->cGreenBits
= mode
->green_bits
;
3448 descr
->cGreenShift
= mode
->green_shift
;
3449 descr
->cBlueBits
= mode
->blue_bits
;
3450 descr
->cBlueShift
= mode
->blue_shift
;
3451 descr
->cAlphaBits
= mode
->alpha_bits
;
3452 descr
->cAlphaShift
= mode
->alpha_shift
;
3456 mode
= &color_modes
[pf
->accum_mode
- 1];
3457 descr
->cAccumBits
= mode
->color_bits
;
3458 descr
->cAccumRedBits
= mode
->red_bits
;
3459 descr
->cAccumGreenBits
= mode
->green_bits
;
3460 descr
->cAccumBlueBits
= mode
->blue_bits
;
3461 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3464 descr
->cDepthBits
= pf
->depth_bits
;
3465 descr
->cStencilBits
= pf
->stencil_bits
;
3466 descr
->cAuxBuffers
= pf
->aux_buffers
;
3467 descr
->iLayerType
= PFD_MAIN_PLANE
;
3469 TRACE("%s\n", debugstr_pf(pf
));
3470 return nb_displayable_formats
;
3473 /***********************************************************************
3474 * macdrv_wglCopyContext
3476 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3480 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3482 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3483 if (err
!= kCGLNoError
)
3484 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3485 return (err
== kCGLNoError
);
3488 /***********************************************************************
3489 * macdrv_wglCreateContext
3491 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3494 struct wgl_context
*context
;
3496 TRACE("hdc %p\n", hdc
);
3498 format
= get_dc_pixel_format(hdc
);
3500 if (!is_valid_pixel_format(format
))
3502 ERR("Invalid pixel format %d, expect problems!\n", format
);
3503 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3507 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3509 context
->format
= format
;
3510 if (!create_context(context
, NULL
))
3512 HeapFree(GetProcessHeap(), 0, context
);
3516 EnterCriticalSection(&context_section
);
3517 list_add_tail(&context_list
, &context
->entry
);
3518 LeaveCriticalSection(&context_section
);
3523 /***********************************************************************
3524 * macdrv_wglDeleteContext
3526 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3528 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3530 EnterCriticalSection(&context_section
);
3531 list_remove(&context
->entry
);
3532 LeaveCriticalSection(&context_section
);
3534 macdrv_dispose_opengl_context(context
->context
);
3535 HeapFree(GetProcessHeap(), 0, context
);
3538 /***********************************************************************
3539 * macdrv_wglGetPixelFormat
3541 static int macdrv_wglGetPixelFormat(HDC hdc
)
3545 format
= get_dc_pixel_format(hdc
);
3547 if (!is_valid_pixel_format(format
)) /* not set yet */
3549 else if (!is_displayable_pixel_format(format
))
3551 /* Non-displayable formats can't be used with traditional WGL calls.
3552 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3556 TRACE(" hdc %p -> %d\n", hdc
, format
);
3560 /***********************************************************************
3561 * macdrv_wglGetProcAddress
3563 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3567 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3568 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3574 if (dladdr(ret
, &info
))
3575 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3577 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3581 WARN("failed to find proc %s\n", debugstr_a(proc
));
3585 /***********************************************************************
3586 * macdrv_wglMakeCurrent
3588 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3590 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3591 (context
? context
->cglcontext
: NULL
));
3593 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3596 /**********************************************************************
3597 * macdrv_wglSetPixelFormat
3599 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3601 return set_pixel_format(hdc
, fmt
, FALSE
);
3604 /***********************************************************************
3605 * macdrv_wglShareLists
3607 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3609 macdrv_opengl_context saved_context
;
3610 CGLContextObj saved_cglcontext
;
3612 TRACE("org %p dest %p\n", org
, dest
);
3614 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3615 * at context creation time but in case of WGL it is done using wglShareLists.
3617 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3618 * and when a program requests sharing we recreate the destination context if it hasn't been made
3619 * current or when it hasn't shared display lists before.
3622 if (dest
->has_been_current
)
3624 WARN("could not share display lists, the destination context has been current already\n");
3627 else if (dest
->sharing
)
3629 WARN("could not share display lists because dest has already shared lists before\n");
3633 /* Re-create the Mac context and share display lists */
3634 saved_context
= dest
->context
;
3635 saved_cglcontext
= dest
->cglcontext
;
3636 dest
->context
= NULL
;
3637 dest
->cglcontext
= NULL
;
3638 if (!create_context(dest
, org
->cglcontext
))
3640 dest
->context
= saved_context
;
3641 dest
->cglcontext
= saved_cglcontext
;
3645 /* Implicitly disposes of saved_cglcontext. */
3646 macdrv_dispose_opengl_context(saved_context
);
3648 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3649 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3651 org
->sharing
= TRUE
;
3652 dest
->sharing
= TRUE
;
3657 /**********************************************************************
3658 * macdrv_wglSwapBuffers
3660 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3662 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3666 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3667 (context
? context
->cglcontext
: NULL
));
3670 sync_swap_interval(context
);
3672 if ((hwnd
= WindowFromDC(hdc
)))
3674 struct macdrv_win_data
*data
;
3676 if (!(data
= get_win_data(hwnd
)))
3678 SetLastError(ERROR_INVALID_HANDLE
);
3682 if (context
&& context
->draw_view
== data
->gl_view
)
3685 release_win_data(data
);
3689 struct wgl_pbuffer
*pbuffer
;
3691 EnterCriticalSection(&dc_pbuffers_section
);
3692 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3693 LeaveCriticalSection(&dc_pbuffers_section
);
3697 SetLastError(ERROR_INVALID_HANDLE
);
3701 if (context
&& context
->draw_pbuffer
== pbuffer
)
3706 macdrv_flush_opengl_context(context
->context
);
3709 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3711 /* If there is a current context, then wglSwapBuffers should do an implicit
3712 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3713 in the other branch, but we have to do it explicitly here. */
3721 static struct opengl_funcs opengl_funcs
=
3724 macdrv_wglCopyContext
, /* p_wglCopyContext */
3725 macdrv_wglCreateContext
, /* p_wglCreateContext */
3726 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3727 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3728 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3729 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3730 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3731 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3732 macdrv_wglShareLists
, /* p_wglShareLists */
3733 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3737 /**********************************************************************
3738 * macdrv_wine_get_wgl_driver
3740 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3742 if (version
!= WINE_WGL_DRIVER_VERSION
)
3744 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3748 if (!init_opengl()) return (void *)-1;
3750 return &opengl_funcs
;