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];
54 unsigned int max_major
, max_minor
;
57 static struct gl_info gl_info
;
64 macdrv_opengl_context context
;
65 CGLContextObj cglcontext
;
67 macdrv_view draw_view
;
68 struct wgl_pbuffer
*draw_pbuffer
;
69 macdrv_view read_view
;
70 struct wgl_pbuffer
*read_pbuffer
;
71 BOOL has_been_current
;
73 LONG update_swap_interval
;
74 DWORD last_flush_time
;
78 static struct list context_list
= LIST_INIT(context_list
);
80 static CRITICAL_SECTION context_section
;
81 static CRITICAL_SECTION_DEBUG critsect_debug
=
83 0, 0, &context_section
,
84 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
85 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
87 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
92 CGLPBufferObj pbuffer
;
100 static CFMutableDictionaryRef dc_pbuffers
;
102 static CRITICAL_SECTION dc_pbuffers_section
;
103 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
105 0, 0, &dc_pbuffers_section
,
106 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
107 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
109 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
112 static struct opengl_funcs opengl_funcs
;
114 #define USE_GL_FUNC(name) #name,
115 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
119 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
121 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
122 static void (*pglFinish
)(void);
123 static void (*pglFlush
)(void);
124 static void (*pglFlushRenderAPPLE
)(void);
125 static const GLubyte
*(*pglGetString
)(GLenum name
);
126 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
127 GLenum format
, GLenum type
, void *pixels
);
128 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
134 GLint color_bits
; /* including alpha_bits */
135 int red_bits
, red_shift
;
136 int green_bits
, green_shift
;
137 int blue_bits
, blue_shift
;
138 GLint alpha_bits
, alpha_shift
;
143 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
144 observations of the behavior of Windows systems, but also subjective judgments
145 about what color formats are more "normal" than others.
147 On at least some Windows systems, integer color formats are listed before
148 floating-point formats. Within the integer formats, higher color bits were
149 usually listed before lower color bits, while for floating-point formats it
150 was the reverse. However, that leads D3D to select 64-bit integer formats in
151 preference to 32-bit formats when the latter would be sufficient. It seems
152 that a 32-bit format is much more likely to be normally used in that case.
154 Also, there are certain odd color formats supported on the Mac which seem like
155 they would be less appropriate than more common ones. For instance, the color
156 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
157 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
160 For two color formats which differ only in whether or not they have alpha bits,
161 we use the same ordering. pixel_format_comparator() gives alpha bits a
162 different weight than color formats.
164 static const struct color_mode color_modes
[] = {
165 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
166 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
167 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
168 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
169 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
170 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
171 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
172 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
173 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
174 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
175 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
176 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
177 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
178 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
179 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
180 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
181 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
182 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
183 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
184 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
185 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
186 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
187 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
188 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
192 static const struct {
195 } depth_stencil_modes
[] = {
223 GLint max_aux_buffers
;
224 GLint max_sample_buffers
;
231 } renderer_properties
;
235 unsigned int window
:1;
236 unsigned int pbuffer
:1;
237 unsigned int accelerated
:1;
238 unsigned int color_mode
:5; /* index into color_modes table */
239 unsigned int aux_buffers
:3;
240 unsigned int depth_bits
:8;
241 unsigned int stencil_bits
:8;
242 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
243 unsigned int double_buffer
:1;
244 unsigned int stereo
:1;
245 unsigned int sample_buffers
:1;
246 unsigned int samples
:5;
247 unsigned int backing_store
:1;
255 } pixel_format_or_code
;
256 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
259 static pixel_format
*pixel_formats
;
260 static int nb_formats
, nb_displayable_formats
;
263 static void *opengl_handle
;
266 static const char* debugstr_attrib(int attrib
, int value
)
268 static const struct {
272 #define ATTRIB(a) { a, #a }
273 ATTRIB(WGL_ACCELERATION_ARB
),
274 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
275 ATTRIB(WGL_ACCUM_BITS_ARB
),
276 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
277 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
278 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
279 ATTRIB(WGL_ALPHA_BITS_ARB
),
280 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
281 ATTRIB(WGL_AUX_BUFFERS_ARB
),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
286 ATTRIB(WGL_BLUE_BITS_ARB
),
287 ATTRIB(WGL_BLUE_SHIFT_ARB
),
288 ATTRIB(WGL_COLOR_BITS_ARB
),
289 ATTRIB(WGL_DEPTH_BITS_ARB
),
290 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
291 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
292 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
293 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
294 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
295 ATTRIB(WGL_GREEN_BITS_ARB
),
296 ATTRIB(WGL_GREEN_SHIFT_ARB
),
297 ATTRIB(WGL_NEED_PALETTE_ARB
),
298 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
299 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
300 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
301 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
302 ATTRIB(WGL_PIXEL_TYPE_ARB
),
303 ATTRIB(WGL_RED_BITS_ARB
),
304 ATTRIB(WGL_RED_SHIFT_ARB
),
305 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
306 ATTRIB(WGL_SAMPLES_ARB
),
307 ATTRIB(WGL_SHARE_ACCUM_ARB
),
308 ATTRIB(WGL_SHARE_DEPTH_ARB
),
309 ATTRIB(WGL_SHARE_STENCIL_ARB
),
310 ATTRIB(WGL_STENCIL_BITS_ARB
),
311 ATTRIB(WGL_STEREO_ARB
),
312 ATTRIB(WGL_SUPPORT_GDI_ARB
),
313 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
314 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
315 ATTRIB(WGL_SWAP_METHOD_ARB
),
316 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
317 ATTRIB(WGL_TRANSPARENT_ARB
),
318 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
319 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
320 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
321 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
325 const char *attrib_name
= NULL
;
326 const char *value_name
= NULL
;
328 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
330 if (attrib_names
[i
].attrib
== attrib
)
332 attrib_name
= attrib_names
[i
].name
;
338 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
342 case WGL_ACCELERATION_ARB
:
345 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
346 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
347 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
350 case WGL_PIXEL_TYPE_ARB
:
353 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
354 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
355 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
356 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
359 case WGL_SWAP_METHOD_ARB
:
362 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
363 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
364 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
370 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
372 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
376 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
377 CGLRendererProperty property
, GLint
*value
)
379 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
380 if (err
!= kCGLNoError
)
381 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
382 return (err
== kCGLNoError
);
386 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
390 memset(properties
, 0, sizeof(*properties
));
392 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
393 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
395 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
396 properties
->buffer_modes
= value
;
398 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
399 properties
->color_modes
= value
;
401 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
402 properties
->accum_modes
= value
;
404 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
405 properties
->depth_modes
= value
;
407 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
408 properties
->stencil_modes
= value
;
410 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
411 properties
->max_aux_buffers
= value
;
413 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
414 properties
->max_sample_buffers
= value
;
416 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
417 properties
->max_samples
= value
;
419 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
420 properties
->offscreen
= (value
!= 0);
422 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
423 properties
->accelerated
= (value
!= 0);
425 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
426 properties
->backing_store
= (value
!= 0);
428 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
429 properties
->window
= (value
!= 0);
431 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
432 properties
->online
= (value
!= 0);
436 static void dump_renderer(const renderer_properties
* renderer
)
440 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
441 TRACE("Buffer modes:\n");
442 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
443 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
444 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
445 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
447 TRACE("Color buffer modes:\n");
448 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
450 if (renderer
->color_modes
& color_modes
[i
].mode
)
452 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
453 if (color_modes
[i
].is_float
)
459 TRACE("Accumulation buffer sizes: { ");
460 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
462 if (renderer
->accum_modes
& color_modes
[i
].mode
)
463 TRACE("%d, ", color_modes
[i
].color_bits
);
467 TRACE("Depth buffer sizes: { ");
468 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
470 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
471 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
475 TRACE("Stencil buffer sizes: { ");
476 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
478 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
479 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
483 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
484 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
485 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
486 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
487 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
488 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
489 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
490 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
494 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
496 pixel_format_or_code pfc
;
499 pfc
.format
= *format
;
504 static inline pixel_format
pixel_format_for_code(UInt64 code
)
506 pixel_format_or_code pfc
;
513 static const char *debugstr_pf(const pixel_format
*pf
)
515 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",
519 color_modes
[pf
->color_mode
].color_bits
,
520 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
521 color_modes
[pf
->color_mode
].alpha_bits
,
524 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
531 code_for_pixel_format(pf
));
535 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
540 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
542 if ((modes
& color_modes
[i
].mode
) &&
543 color_modes
[i
].color_bits
>= color_size
&&
544 color_modes
[i
].alpha_bits
>= alpha_size
&&
545 !color_modes
[i
].is_float
== !color_float
)
547 if (best
< 0) /* no existing best choice */
549 else if (color_modes
[i
].color_bits
== color_size
&&
550 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
552 /* prefer it over a best which isn't exact or which has a higher bpp */
553 if (color_modes
[best
].color_bits
!= color_size
||
554 color_modes
[best
].alpha_bits
!= alpha_size
||
555 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
558 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
559 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
560 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
567 /* Couldn't find a match. Return first one that renderer supports. */
568 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
570 if (modes
& color_modes
[i
].mode
)
579 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
584 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
586 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
588 /* Prefer the fewest color bits, then prefer more alpha bits, then
589 prefer more bits per pixel. */
592 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
594 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
596 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
598 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
599 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
607 /* Couldn't find a match. Return last one that renderer supports. */
608 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
610 if (modes
& color_modes
[i
].mode
)
619 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
620 CFMutableSetRef pixel_format_set
)
622 CGLPixelFormatAttribute attribs
[64] = {
623 kCGLPFAMinimumPolicy
,
624 kCGLPFAClosestPolicy
,
625 kCGLPFARendererID
, renderer
.renderer_id
,
626 kCGLPFASingleRenderer
,
628 int n
= 5, n_stack
[16], n_stack_idx
= -1;
629 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
630 new_pixel_formats
= 0;
631 pixel_format request
;
632 unsigned int double_buffer
;
633 unsigned int accelerated
= renderer
.accelerated
;
637 attribs
[n
++] = kCGLPFAAccelerated
;
638 attribs
[n
++] = kCGLPFANoRecovery
;
640 else if (!allow_software_rendering
)
642 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
646 n_stack
[++n_stack_idx
] = n
;
647 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
651 n
= n_stack
[n_stack_idx
];
653 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
654 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
658 attribs
[n
++] = kCGLPFADoubleBuffer
;
659 memset(&request
, 0, sizeof(request
));
660 request
.accelerated
= accelerated
;
661 request
.double_buffer
= double_buffer
;
663 /* Don't bother with in-between aux buffers values: either 0 or max. */
664 n_stack
[++n_stack_idx
] = n
;
665 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
667 unsigned int color_mode
;
669 n
= n_stack
[n_stack_idx
];
671 attribs
[n
++] = kCGLPFAAuxBuffers
;
673 request
.aux_buffers
= aux
;
675 n_stack
[++n_stack_idx
] = n
;
676 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
678 unsigned int depth_mode
;
680 n
= n_stack
[n_stack_idx
];
682 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
685 attribs
[n
++] = kCGLPFAColorSize
;
686 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
687 attribs
[n
++] = kCGLPFAAlphaSize
;
688 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
689 if (color_modes
[color_mode
].is_float
)
690 attribs
[n
++] = kCGLPFAColorFloat
;
691 request
.color_mode
= color_mode
;
693 n_stack
[++n_stack_idx
] = n
;
694 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
696 unsigned int stencil_mode
;
698 n
= n_stack
[n_stack_idx
];
700 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
703 attribs
[n
++] = kCGLPFADepthSize
;
704 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
705 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
707 n_stack
[++n_stack_idx
] = n
;
708 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
712 n
= n_stack
[n_stack_idx
];
714 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
716 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
719 attribs
[n
++] = kCGLPFAStencilSize
;
720 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
721 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
723 /* FIXME: Could trim search space a bit here depending on GPU.
724 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
725 n_stack
[++n_stack_idx
] = n
;
726 for (stereo
= 0; stereo
<= 1; stereo
++)
730 n
= n_stack
[n_stack_idx
];
732 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
733 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
737 attribs
[n
++] = kCGLPFAStereo
;
738 request
.stereo
= stereo
;
740 /* Starts at -1 for a 0 accum size */
741 n_stack
[++n_stack_idx
] = n
;
742 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
744 unsigned int target_pass
;
746 n
= n_stack
[n_stack_idx
];
750 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
753 attribs
[n
++] = kCGLPFAAccumSize
;
754 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
755 request
.accum_mode
= accum_mode
+ 1;
758 request
.accum_mode
= 0;
760 /* Targets to request are:
761 accelerated: window OR window + pbuffer
762 software: window + pbuffer */
763 n_stack
[++n_stack_idx
] = n
;
764 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
766 unsigned int samples
, max_samples
;
768 n
= n_stack
[n_stack_idx
];
770 attribs
[n
++] = kCGLPFAWindow
;
773 if (!accelerated
|| target_pass
> 0)
775 attribs
[n
++] = kCGLPFAPBuffer
;
781 /* FIXME: Could trim search space a bit here depending on GPU.
782 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
783 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
784 n_stack
[++n_stack_idx
] = n
;
785 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
786 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
788 unsigned int backing_store
, min_backing_store
, max_backing_store
;
790 n
= n_stack
[n_stack_idx
];
794 attribs
[n
++] = kCGLPFASampleBuffers
;
795 attribs
[n
++] = renderer
.max_sample_buffers
;
796 attribs
[n
++] = kCGLPFASamples
;
797 attribs
[n
++] = samples
;
798 request
.sample_buffers
= renderer
.max_sample_buffers
;
799 request
.samples
= samples
;
802 request
.sample_buffers
= request
.samples
= 0;
804 if (renderer
.backing_store
&& double_buffer
)
806 /* The software renderer seems to always preserve the backing store, whether
807 we ask for it or not. So don't bother not asking for it. */
808 min_backing_store
= accelerated
? 0 : 1;
809 max_backing_store
= 1;
812 min_backing_store
= max_backing_store
= 0;
813 n_stack
[++n_stack_idx
] = n
;
814 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
816 CGLPixelFormatObj pix
;
817 GLint virtualScreens
;
820 n
= n_stack
[n_stack_idx
];
823 attribs
[n
++] = kCGLPFABackingStore
;
824 request
.backing_store
= backing_store
;
828 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
829 if (err
== kCGLNoError
&& pix
)
832 GLint value
, color_size
, alpha_size
, color_float
;
834 CFNumberRef code_object
;
837 memset(&pf
, 0, sizeof(pf
));
839 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
840 pf
.accelerated
= value
;
841 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
842 pf
.aux_buffers
= value
;
843 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
844 pf
.depth_bits
= value
;
845 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
846 pf
.double_buffer
= value
;
847 if (pf
.double_buffer
&&
848 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
849 pf
.backing_store
= value
;
850 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
852 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
853 pf
.sample_buffers
= value
;
854 if (pf
.sample_buffers
&&
855 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
857 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
858 pf
.stencil_bits
= value
;
859 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
861 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
864 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
866 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
868 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
870 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
872 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
873 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
875 CGLReleasePixelFormat(pix
);
877 pf_code
= code_for_pixel_format(&pf
);
879 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
880 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
881 dupe_pixel_formats
++;
884 CFSetAddValue(pixel_format_set
, code_object
);
885 CFArrayAppendValue(pixel_format_array
, code_object
);
888 CFRelease(code_object
);
890 if (pf_code
== code_for_pixel_format(&request
))
891 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
894 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
895 dupe
? " (duplicate)" : "");
900 failed_pixel_formats
++;
901 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
904 tried_pixel_formats
++;
936 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
937 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
938 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
939 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
943 /* The docs for WGL_ARB_pixel_format say:
944 Indices are assigned to pixel formats in the following order:
945 1. Accelerated pixel formats that are displayable
946 2. Accelerated pixel formats that are displayable and which have
948 3. Generic pixel formats
949 4. Accelerated pixel formats that are non displayable
951 static int pixel_format_category(pixel_format pf
)
953 /* non-displayable */
957 /* non-accelerated a.k.a. software a.k.a. generic */
961 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
962 if (color_modes
[pf
.color_mode
].is_float
)
965 /* accelerated, displayable, no extended attributes */
970 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
972 CFNumberRef number1
= val1
;
973 CFNumberRef number2
= val2
;
975 pixel_format pf1
, pf2
;
976 int category1
, category2
;
978 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
979 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
980 pf1
= pixel_format_for_code(code1
);
981 pf2
= pixel_format_for_code(code2
);
982 category1
= pixel_format_category(pf1
);
983 category2
= pixel_format_category(pf2
);
985 if (category1
< category2
)
986 return kCFCompareLessThan
;
987 if (category1
> category2
)
988 return kCFCompareGreaterThan
;
990 /* Within a category, sort the "best" formats toward the front since that's
991 what wglChoosePixelFormatARB() has to do. The ordering implemented here
992 matches at least one Windows 7 machine's behavior.
994 /* Accelerated before unaccelerated. */
995 if (pf1
.accelerated
&& !pf2
.accelerated
)
996 return kCFCompareLessThan
;
997 if (!pf1
.accelerated
&& pf2
.accelerated
)
998 return kCFCompareGreaterThan
;
1000 /* Explicit color mode ordering. */
1001 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1002 return kCFCompareLessThan
;
1003 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1004 return kCFCompareGreaterThan
;
1006 /* Non-pbuffer-capable before pbuffer-capable. */
1007 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1008 return kCFCompareLessThan
;
1009 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1010 return kCFCompareGreaterThan
;
1012 /* Fewer samples before more samples. */
1013 if (pf1
.samples
< pf2
.samples
)
1014 return kCFCompareLessThan
;
1015 if (pf1
.samples
> pf2
.samples
)
1016 return kCFCompareGreaterThan
;
1018 /* Monoscopic before stereoscopic. (This is a guess.) */
1019 if (!pf1
.stereo
&& pf2
.stereo
)
1020 return kCFCompareLessThan
;
1021 if (pf1
.stereo
&& !pf2
.stereo
)
1022 return kCFCompareGreaterThan
;
1024 /* Single buffered before double buffered. */
1025 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1026 return kCFCompareLessThan
;
1027 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1028 return kCFCompareGreaterThan
;
1030 /* Possibly-optimized double buffering before backing-store-preserving
1031 double buffering. */
1032 if (!pf1
.backing_store
&& pf2
.backing_store
)
1033 return kCFCompareLessThan
;
1034 if (pf1
.backing_store
&& !pf2
.backing_store
)
1035 return kCFCompareGreaterThan
;
1037 /* Bigger depth buffer before smaller depth buffer. */
1038 if (pf1
.depth_bits
> pf2
.depth_bits
)
1039 return kCFCompareLessThan
;
1040 if (pf1
.depth_bits
< pf2
.depth_bits
)
1041 return kCFCompareGreaterThan
;
1043 /* Smaller stencil buffer before bigger stencil buffer. */
1044 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1045 return kCFCompareLessThan
;
1046 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1047 return kCFCompareGreaterThan
;
1049 /* Smaller alpha bits before larger alpha bits. */
1050 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1051 return kCFCompareLessThan
;
1052 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1053 return kCFCompareGreaterThan
;
1055 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
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 kCFCompareLessThan
;
1063 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1064 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1065 return kCFCompareGreaterThan
;
1067 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1068 return kCFCompareLessThan
;
1069 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1070 return kCFCompareGreaterThan
;
1072 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1073 return kCFCompareLessThan
;
1074 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1075 return kCFCompareGreaterThan
;
1078 return kCFCompareGreaterThan
;
1080 else if (pf2
.accum_mode
)
1081 return kCFCompareLessThan
;
1083 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1084 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1085 return kCFCompareLessThan
;
1086 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1087 return kCFCompareGreaterThan
;
1089 /* If we get here, arbitrarily sort based on code. */
1091 return kCFCompareLessThan
;
1093 return kCFCompareGreaterThan
;
1094 return kCFCompareEqualTo
;
1098 static BOOL
init_pixel_formats(void)
1101 CGLRendererInfoObj renderer_info
;
1102 GLint rendererCount
;
1104 CFMutableSetRef pixel_format_set
;
1105 CFMutableArrayRef pixel_format_array
;
1111 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1114 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1118 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1119 if (!pixel_format_set
)
1121 WARN("CFSetCreateMutable failed\n");
1122 CGLDestroyRendererInfo(renderer_info
);
1126 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1127 if (!pixel_format_array
)
1129 WARN("CFArrayCreateMutable failed\n");
1130 CFRelease(pixel_format_set
);
1131 CGLDestroyRendererInfo(renderer_info
);
1135 for (i
= 0; i
< rendererCount
; i
++)
1137 renderer_properties renderer
;
1139 get_renderer_properties(renderer_info
, i
, &renderer
);
1142 TRACE("renderer_properties %d:\n", i
);
1143 dump_renderer(&renderer
);
1146 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1149 CFRelease(pixel_format_set
);
1150 CGLDestroyRendererInfo(renderer_info
);
1152 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1155 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1158 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1159 for (i
= 0; i
< range
.length
; i
++)
1161 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1164 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1165 pixel_formats
[i
] = pixel_format_for_code(code
);
1166 if (pixel_formats
[i
].window
)
1167 nb_displayable_formats
++;
1170 nb_formats
= range
.length
;
1171 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1175 WARN("failed to allocate pixel format list\n");
1178 WARN("got no pixel formats\n");
1180 CFRelease(pixel_format_array
);
1185 static inline BOOL
is_valid_pixel_format(int format
)
1187 return format
> 0 && format
<= nb_formats
;
1191 static inline BOOL
is_displayable_pixel_format(int format
)
1193 return format
> 0 && format
<= nb_displayable_formats
;
1197 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1199 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1200 * format in case of probing the number of pixel formats.
1202 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1204 TRACE("Returning format %d\n", format
);
1205 return &pixel_formats
[format
- 1];
1211 static BOOL
init_gl_info(void)
1213 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1214 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1216 CGDirectDisplayID display
= CGMainDisplayID();
1217 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1218 CGLPixelFormatAttribute attribs
[] = {
1219 kCGLPFADisplayMask
, displayMask
,
1222 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1223 CGLPixelFormatAttribute core_attribs
[] =
1225 kCGLPFADisplayMask
, displayMask
,
1227 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1231 CGLPixelFormatObj pix
;
1232 GLint virtualScreens
;
1234 CGLContextObj context
;
1235 CGLContextObj old_context
= CGLGetCurrentContext();
1239 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1240 if (err
!= kCGLNoError
|| !pix
)
1242 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1246 err
= CGLCreateContext(pix
, NULL
, &context
);
1247 CGLReleasePixelFormat(pix
);
1248 if (err
!= kCGLNoError
|| !context
)
1250 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1254 err
= CGLSetCurrentContext(context
);
1255 if (err
!= kCGLNoError
)
1257 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1258 CGLReleaseContext(context
);
1262 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1263 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1264 strcpy(gl_info
.glVersion
, str
);
1265 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1266 length
= strlen(str
) + sizeof(legacy_extensions
);
1268 length
+= strlen(legacy_ext_swap_control
);
1269 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1270 strcpy(gl_info
.glExtensions
, str
);
1271 strcat(gl_info
.glExtensions
, legacy_extensions
);
1273 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1275 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1277 TRACE("GL version : %s\n", gl_info
.glVersion
);
1278 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1279 sscanf(gl_info
.glVersion
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1281 CGLSetCurrentContext(old_context
);
1282 CGLReleaseContext(context
);
1284 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1285 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1286 if (err
!= kCGLNoError
|| !pix
)
1288 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1289 err
, CGLErrorString(err
));
1293 err
= CGLCreateContext(pix
, NULL
, &context
);
1294 CGLReleasePixelFormat(pix
);
1295 if (err
!= kCGLNoError
|| !context
)
1297 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1298 err
, CGLErrorString(err
));
1302 err
= CGLSetCurrentContext(context
);
1303 if (err
!= kCGLNoError
)
1305 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1306 err
, CGLErrorString(err
));
1307 CGLReleaseContext(context
);
1311 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1312 TRACE("Core context GL version: %s\n", str
);
1313 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1314 CGLSetCurrentContext(old_context
);
1315 CGLReleaseContext(context
);
1322 static int get_dc_pixel_format(HDC hdc
)
1327 if ((hwnd
= WindowFromDC(hdc
)))
1329 struct macdrv_win_data
*data
;
1331 if (!(data
= get_win_data(hwnd
)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1337 format
= data
->pixel_format
;
1338 release_win_data(data
);
1342 struct wgl_pbuffer
*pbuffer
;
1344 EnterCriticalSection(&dc_pbuffers_section
);
1345 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1347 format
= pbuffer
->format
;
1350 WARN("no window or pbuffer for DC %p\n", hdc
);
1353 LeaveCriticalSection(&dc_pbuffers_section
);
1360 /**********************************************************************
1363 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1365 const pixel_format
*pf
;
1366 CGLPixelFormatAttribute attribs
[64];
1368 CGLPixelFormatObj pix
;
1369 GLint virtualScreens
;
1371 BOOL core
= major
>= 3;
1373 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1376 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1381 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1384 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1385 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1389 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1390 attribs
[n
++] = kCGLPFAClosestPolicy
;
1392 if (pf
->accelerated
)
1394 attribs
[n
++] = kCGLPFAAccelerated
;
1395 attribs
[n
++] = kCGLPFANoRecovery
;
1399 attribs
[n
++] = kCGLPFARendererID
;
1400 attribs
[n
++] = kCGLRendererGenericFloatID
;
1403 if (pf
->double_buffer
)
1404 attribs
[n
++] = kCGLPFADoubleBuffer
;
1408 attribs
[n
++] = kCGLPFAAuxBuffers
;
1409 attribs
[n
++] = pf
->aux_buffers
;
1412 attribs
[n
++] = kCGLPFAColorSize
;
1413 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1414 attribs
[n
++] = kCGLPFAAlphaSize
;
1415 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1416 if (color_modes
[pf
->color_mode
].is_float
)
1417 attribs
[n
++] = kCGLPFAColorFloat
;
1419 attribs
[n
++] = kCGLPFADepthSize
;
1420 attribs
[n
++] = pf
->depth_bits
;
1422 attribs
[n
++] = kCGLPFAStencilSize
;
1423 attribs
[n
++] = pf
->stencil_bits
;
1426 attribs
[n
++] = kCGLPFAStereo
;
1428 if (pf
->accum_mode
&& !core
)
1430 attribs
[n
++] = kCGLPFAAccumSize
;
1431 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1434 if (pf
->pbuffer
&& !core
)
1435 attribs
[n
++] = kCGLPFAPBuffer
;
1437 if (pf
->sample_buffers
&& pf
->samples
)
1439 attribs
[n
++] = kCGLPFASampleBuffers
;
1440 attribs
[n
++] = pf
->sample_buffers
;
1441 attribs
[n
++] = kCGLPFASamples
;
1442 attribs
[n
++] = pf
->samples
;
1445 if (pf
->backing_store
)
1446 attribs
[n
++] = kCGLPFABackingStore
;
1448 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1451 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1452 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1454 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1456 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1458 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1465 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1466 if (err
!= kCGLNoError
|| !pix
)
1468 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1469 SetLastError(ERROR_INVALID_OPERATION
);
1473 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1474 CGLReleasePixelFormat(pix
);
1475 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1477 context
->cglcontext
= NULL
;
1478 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1479 SetLastError(ERROR_INVALID_OPERATION
);
1483 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1484 CGLReleaseContext(context
->cglcontext
);
1485 if (!context
->context
)
1487 WARN("macdrv_create_opengl_context() failed\n");
1488 SetLastError(ERROR_INVALID_OPERATION
);
1491 context
->major
= major
;
1494 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1496 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1502 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1505 *rect
= data
->client_rect
;
1507 if (data
->cocoa_window
)
1510 *window
= data
->cocoa_window
;
1511 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1515 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1516 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1517 struct macdrv_win_data
*top_data
= get_win_data(top
);
1519 if (top_data
&& top_data
->cocoa_window
)
1522 *window
= top_data
->cocoa_window
;
1523 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1524 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1529 release_win_data(top_data
);
1536 /***********************************************************************
1539 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1541 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1545 macdrv_window cocoa_window
;
1547 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1549 ERR("no top-level parent with Cocoa window in this process\n");
1553 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1556 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1560 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1561 wine_dbgstr_rect(&data
->gl_rect
));
1564 data
->pixel_format
= format
;
1570 /**********************************************************************
1573 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1575 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1577 struct macdrv_win_data
*data
;
1578 const pixel_format
*pf
;
1579 HWND hwnd
= WindowFromDC(hdc
);
1582 TRACE("hdc %p format %d\n", hdc
, fmt
);
1584 if (!hwnd
|| hwnd
== GetDesktopWindow())
1586 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1590 if (!(data
= get_win_data(hwnd
)))
1592 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1596 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1598 ret
= (data
->pixel_format
== fmt
);
1602 /* Check if fmt is in our list of supported formats to see if it is supported. */
1603 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1606 ERR("Invalid pixel format: %d\n", fmt
);
1612 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1616 if (!set_win_format(data
, fmt
))
1618 WARN("Couldn't set format of the window, returning failure\n");
1622 TRACE("pixel format:\n");
1623 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1624 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1625 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1626 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1627 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1628 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1629 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1630 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1631 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1632 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1633 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1634 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1635 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1636 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1640 release_win_data(data
);
1641 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1646 /**********************************************************************
1647 * set_gl_view_parent
1649 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1651 struct macdrv_win_data
*data
;
1653 if (!(data
= get_win_data(hwnd
))) return;
1657 macdrv_window cocoa_window
;
1659 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1661 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1663 ERR("no top-level parent with Cocoa window in this process\n");
1664 macdrv_dispose_view(data
->gl_view
);
1665 data
->gl_view
= NULL
;
1666 release_win_data(data
);
1667 __wine_set_pixel_format( hwnd
, 0 );
1671 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1674 release_win_data(data
);
1678 /**********************************************************************
1679 * make_context_current
1681 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1684 struct wgl_pbuffer
*pbuffer
;
1688 view
= context
->read_view
;
1689 pbuffer
= context
->read_pbuffer
;
1693 view
= context
->draw_view
;
1694 pbuffer
= context
->draw_pbuffer
;
1697 if (view
|| !pbuffer
)
1698 macdrv_make_context_current(context
->context
, view
);
1701 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1703 CGLSetCurrentContext(context
->cglcontext
);
1708 /**********************************************************************
1711 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1715 /* In theory, for single-buffered contexts, there's no such thing as a swap
1716 so the swap interval shouldn't matter. But OS X will synchronize flushes
1717 of single-buffered contexts if the interval is set to non-zero. */
1718 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1721 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1722 if (err
!= kCGLNoError
)
1723 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1725 return err
== kCGLNoError
;
1729 /**********************************************************************
1730 * sync_swap_interval
1732 static void sync_swap_interval(struct wgl_context
*context
)
1734 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1738 if (context
->draw_hwnd
)
1740 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1743 interval
= data
->swap_interval
;
1744 release_win_data(data
);
1746 else /* window was destroyed? */
1752 set_swap_interval(context
, interval
);
1757 /**********************************************************************
1758 * macdrv_glCopyColorTable
1760 * Hook into glCopyColorTable as part of the implementation of
1761 * wglMakeContextCurrentARB. If the context has a separate readable,
1762 * temporarily make that current, do glCopyColorTable, and then set it
1763 * back to the drawable. This is modeled after what Mesa GLX's Apple
1764 * implementation does.
1766 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1769 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1771 if (context
->read_view
|| context
->read_pbuffer
)
1772 make_context_current(context
, TRUE
);
1774 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1776 if (context
->read_view
|| context
->read_pbuffer
)
1777 make_context_current(context
, FALSE
);
1781 /**********************************************************************
1782 * macdrv_glCopyPixels
1784 * Hook into glCopyPixels as part of the implementation of
1785 * wglMakeContextCurrentARB. If the context has a separate readable,
1786 * temporarily make that current, do glCopyPixels, and then set it back
1787 * to the drawable. This is modeled after what Mesa GLX's Apple
1788 * implementation does.
1790 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1792 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1794 if (context
->read_view
|| context
->read_pbuffer
)
1795 make_context_current(context
, TRUE
);
1797 pglCopyPixels(x
, y
, width
, height
, type
);
1799 if (context
->read_view
|| context
->read_pbuffer
)
1800 make_context_current(context
, FALSE
);
1804 /**********************************************************************
1807 static void macdrv_glFinish(void)
1809 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1811 sync_swap_interval(context
);
1816 /**********************************************************************
1819 static void macdrv_glFlush(void)
1821 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1823 sync_swap_interval(context
);
1825 if (skip_single_buffer_flushes
)
1827 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1828 DWORD now
= GetTickCount();
1830 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1831 context
->last_flush_time
, now
);
1832 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1834 TRACE("calling glFlushRenderAPPLE()\n");
1835 pglFlushRenderAPPLE();
1840 TRACE("calling glFlush()\n");
1841 context
->last_flush_time
= now
;
1849 /**********************************************************************
1850 * macdrv_glGetString
1852 * Hook into glGetString in order to return some legacy WGL extensions
1853 * that couldn't be advertised via the standard
1854 * WGL_ARB_extensions_string mechanism. Some programs, especially
1855 * older ones, expect to find certain older extensions, such as
1856 * WGL_EXT_extensions_string itself, in the standard GL extensions
1857 * string, and won't query any other WGL extensions unless they find
1858 * that particular extension there.
1860 static const GLubyte
*macdrv_glGetString(GLenum name
)
1862 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1863 return (const GLubyte
*)gl_info
.glExtensions
;
1865 return pglGetString(name
);
1869 /**********************************************************************
1870 * macdrv_glReadPixels
1872 * Hook into glReadPixels as part of the implementation of
1873 * wglMakeContextCurrentARB. If the context has a separate readable,
1874 * temporarily make that current, do glReadPixels, and then set it back
1875 * to the drawable. This is modeled after what Mesa GLX's Apple
1876 * implementation does.
1878 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1879 GLenum format
, GLenum type
, void *pixels
)
1881 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1883 if (context
->read_view
|| context
->read_pbuffer
)
1884 make_context_current(context
, TRUE
);
1886 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1888 if (context
->read_view
|| context
->read_pbuffer
)
1889 make_context_current(context
, FALSE
);
1893 /**********************************************************************
1896 * Hook into glViewport as an opportunity to update the OpenGL context
1897 * if necessary. This is modeled after what Mesa GLX's Apple
1898 * implementation does.
1900 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1902 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1904 macdrv_update_opengl_context(context
->context
);
1905 pglViewport(x
, y
, width
, height
);
1909 /***********************************************************************
1910 * macdrv_wglBindTexImageARB
1912 * WGL_ARB_render_texture: wglBindTexImageARB
1914 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1916 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1920 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1922 if (pbuffer
->no_texture
)
1924 SetLastError(ERROR_INVALID_OPERATION
);
1928 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1929 opengl_funcs
.gl
.p_glFlush();
1933 case WGL_FRONT_LEFT_ARB
:
1934 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1935 source
= GL_FRONT_LEFT
;
1939 case WGL_FRONT_RIGHT_ARB
:
1940 source
= GL_FRONT_RIGHT
;
1942 case WGL_BACK_LEFT_ARB
:
1943 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1944 source
= GL_BACK_LEFT
;
1948 case WGL_BACK_RIGHT_ARB
:
1949 source
= GL_BACK_RIGHT
;
1951 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1952 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1953 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1954 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1962 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1963 SetLastError(ERROR_INVALID_DATA
);
1967 WARN("unknown source buffer 0x%x\n", iBuffer
);
1968 SetLastError(ERROR_INVALID_DATA
);
1972 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1973 if (err
!= kCGLNoError
)
1975 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1976 SetLastError(ERROR_INVALID_OPERATION
);
1984 /***********************************************************************
1985 * macdrv_wglChoosePixelFormatARB
1987 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1989 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1990 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1991 int *piFormats
, UINT
*nNumFormats
)
1993 pixel_format pf
, valid
;
1995 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1996 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2001 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2002 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2004 FIXME("unused pfAttribFList\n");
2006 memset(&pf
, 0, sizeof(pf
));
2007 memset(&valid
, 0, sizeof(valid
));
2008 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2009 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2013 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2016 int value
= iptr
[1];
2018 TRACE("%s\n", debugstr_attrib(attr
, value
));
2022 case WGL_DRAW_TO_WINDOW_ARB
:
2023 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2024 pf
.window
= (value
!= 0);
2028 case WGL_DRAW_TO_BITMAP_ARB
:
2031 case WGL_ACCELERATION_ARB
:
2032 if (value
== WGL_FULL_ACCELERATION_ARB
)
2034 else if (value
== WGL_NO_ACCELERATION_ARB
)
2038 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2039 pf
.accelerated
= value
;
2040 valid
.accelerated
= 1;
2043 case WGL_NEED_PALETTE_ARB
:
2044 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2045 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2046 if (value
) goto cant_match
;
2049 case WGL_SWAP_METHOD_ARB
:
2050 if (value
== WGL_SWAP_COPY_ARB
)
2052 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2056 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2057 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2058 pf
.backing_store
= value
;
2059 valid
.backing_store
= 1;
2062 case WGL_NUMBER_OVERLAYS_ARB
:
2063 case WGL_NUMBER_UNDERLAYS_ARB
:
2064 if (value
) goto cant_match
;
2067 case WGL_SHARE_DEPTH_ARB
:
2068 case WGL_SHARE_STENCIL_ARB
:
2069 case WGL_SHARE_ACCUM_ARB
:
2073 case WGL_SUPPORT_GDI_ARB
:
2074 if (value
) goto cant_match
;
2077 case WGL_SUPPORT_OPENGL_ARB
:
2078 if (!value
) goto cant_match
;
2081 case WGL_DOUBLE_BUFFER_ARB
:
2082 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2083 pf
.double_buffer
= (value
!= 0);
2084 valid
.double_buffer
= 1;
2085 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2088 case WGL_STEREO_ARB
:
2089 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2090 pf
.stereo
= (value
!= 0);
2094 case WGL_PIXEL_TYPE_ARB
:
2095 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2097 else if (value
== WGL_TYPE_RGBA_ARB
)
2101 /* Mac contexts don't support rendering to unsigned floating
2102 point formats, even if GL_EXT_packed_float is supported.
2103 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2106 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2107 if (srgb
&& value
) goto cant_match
;
2108 float_color
= value
;
2111 case WGL_COLOR_BITS_ARB
:
2112 if (color_bits
< value
) color_bits
= value
;
2115 case WGL_RED_BITS_ARB
:
2116 if (srgb
&& value
> 8) goto cant_match
;
2117 if (red_bits
< value
) red_bits
= value
;
2120 case WGL_GREEN_BITS_ARB
:
2121 if (srgb
&& value
> 8) goto cant_match
;
2122 if (green_bits
< value
) green_bits
= value
;
2125 case WGL_BLUE_BITS_ARB
:
2126 if (srgb
&& value
> 8) goto cant_match
;
2127 if (blue_bits
< value
) blue_bits
= value
;
2130 case WGL_ALPHA_BITS_ARB
:
2131 if (alpha_bits
< value
) alpha_bits
= value
;
2134 case WGL_ACCUM_BITS_ARB
:
2135 if (accum_bits
< value
) accum_bits
= value
;
2138 case WGL_ACCUM_RED_BITS_ARB
:
2139 if (accum_red_bits
< value
) accum_red_bits
= value
;
2142 case WGL_ACCUM_GREEN_BITS_ARB
:
2143 if (accum_green_bits
< value
) accum_green_bits
= value
;
2146 case WGL_ACCUM_BLUE_BITS_ARB
:
2147 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2150 case WGL_ACCUM_ALPHA_BITS_ARB
:
2151 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2154 case WGL_DEPTH_BITS_ARB
:
2155 if (value
> 255) goto cant_match
;
2156 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2159 case WGL_STENCIL_BITS_ARB
:
2160 if (value
> 255) goto cant_match
;
2161 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2164 case WGL_AUX_BUFFERS_ARB
:
2165 if (value
> 7) goto cant_match
;
2166 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2169 case WGL_SAMPLE_BUFFERS_ARB
:
2170 if (value
> 1) goto cant_match
;
2171 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2174 case WGL_SAMPLES_ARB
:
2175 if (value
> 31) goto cant_match
;
2176 if (pf
.samples
< value
) pf
.samples
= value
;
2179 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2180 /* sRGB is only supported for 8-bit integer color components */
2181 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2186 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2187 case WGL_RED_SHIFT_ARB
:
2188 case WGL_GREEN_SHIFT_ARB
:
2189 case WGL_BLUE_SHIFT_ARB
:
2190 case WGL_ALPHA_SHIFT_ARB
:
2191 case WGL_TRANSPARENT_ARB
:
2192 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2193 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2194 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2195 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2196 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2200 case WGL_DRAW_TO_PBUFFER_ARB
:
2201 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2202 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2203 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2204 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2205 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2206 pf
.pbuffer
= (value
!= 0);
2208 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2214 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2219 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",
2220 valid
.window
? (pf
.window
? "1" : "0") : "?",
2221 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2222 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2224 float_color
== -1 ? "?" : float_color
? "f" : "",
2238 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2239 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2240 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2244 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2246 const struct color_mode
*mode
;
2248 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2249 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2250 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2251 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2252 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2253 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2255 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2256 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2257 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2258 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2259 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2261 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2262 /* If the mode doesn't have alpha, check requested color bits against
2263 bits per pixel instead of the mode's color bits. On Windows, color
2264 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2265 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2266 expects that to match such a pixel format, we need to accommodate that. */
2267 if (mode
->alpha_bits
)
2269 if (mode
->color_bits
< color_bits
)
2274 if (mode
->bits_per_pixel
< color_bits
)
2277 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2278 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2280 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2281 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2284 if (pixel_formats
[i
].accum_mode
)
2286 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2287 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2288 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2289 mode
->alpha_bits
< accum_alpha_bits
)
2292 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2295 piFormats
[found
++] = i
+ 1;
2296 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2300 *nNumFormats
= found
;
2306 /***********************************************************************
2307 * macdrv_wglCreateContextAttribsARB
2309 * WGL_ARB_create_context: wglCreateContextAttribsARB
2311 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2312 struct wgl_context
*share_context
,
2313 const int *attrib_list
)
2316 struct wgl_context
*context
;
2318 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2321 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2323 format
= get_dc_pixel_format(hdc
);
2325 if (!is_valid_pixel_format(format
))
2327 ERR("Invalid pixel format %d, expect problems!\n", format
);
2328 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2332 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2335 int value
= iptr
[1];
2337 TRACE("%s\n", debugstr_attrib(attr
, value
));
2341 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2345 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2349 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2350 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2353 case WGL_CONTEXT_FLAGS_ARB
:
2355 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2356 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2357 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2360 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2361 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2362 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2364 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2365 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2372 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2373 SetLastError(ERROR_INVALID_PARAMETER
);
2378 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2379 (major
== 4 && (minor
== 0 || minor
== 1)))
2381 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2383 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2384 SetLastError(ERROR_INVALID_VERSION_ARB
);
2387 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2389 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2390 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2393 if (major
> gl_info
.max_major
||
2394 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2396 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2398 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2403 else if (major
>= 3)
2405 WARN("Profile version %u.%u not supported\n", major
, minor
);
2406 SetLastError(ERROR_INVALID_VERSION_ARB
);
2409 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2410 (major
== 2 && (minor
< 0 || minor
> 1)))
2412 WARN("Invalid GL version requested\n");
2413 SetLastError(ERROR_INVALID_VERSION_ARB
);
2416 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2418 WARN("Forward compatible context requested for GL version < 3\n");
2419 SetLastError(ERROR_INVALID_VERSION_ARB
);
2423 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
2425 context
->format
= format
;
2426 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2428 HeapFree(GetProcessHeap(), 0, context
);
2432 EnterCriticalSection(&context_section
);
2433 list_add_tail(&context_list
, &context
->entry
);
2434 LeaveCriticalSection(&context_section
);
2440 /**********************************************************************
2441 * macdrv_wglCreatePbufferARB
2443 * WGL_ARB_pbuffer: wglCreatePbufferARB
2445 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2446 const int *piAttribList
)
2448 struct wgl_pbuffer
* pbuffer
;
2450 GLenum internalFormat
= 0;
2453 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2454 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2456 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2458 WARN("invalid pixel format %d\n", iPixelFormat
);
2459 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2463 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2464 pbuffer
->format
= iPixelFormat
;
2466 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2468 int attr
= piAttribList
[0];
2469 int value
= piAttribList
[1];
2473 case WGL_PBUFFER_LARGEST_ARB
:
2474 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2477 case WGL_TEXTURE_FORMAT_ARB
:
2480 case WGL_TEXTURE_RGBA_ARB
:
2481 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2482 internalFormat
= GL_RGBA
;
2484 case WGL_TEXTURE_RGB_ARB
:
2485 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2486 internalFormat
= GL_RGB
;
2488 case WGL_NO_TEXTURE_ARB
:
2489 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2493 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2494 SetLastError(ERROR_INVALID_DATA
);
2499 case WGL_TEXTURE_TARGET_ARB
:
2503 case WGL_NO_TEXTURE_ARB
:
2504 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2507 case WGL_TEXTURE_CUBE_MAP_ARB
:
2508 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2509 target
= GL_TEXTURE_CUBE_MAP
;
2510 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2512 case WGL_TEXTURE_1D_ARB
:
2513 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2514 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2516 case WGL_TEXTURE_2D_ARB
:
2517 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2518 target
= GL_TEXTURE_2D
;
2520 case WGL_TEXTURE_RECTANGLE_NV
:
2521 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2522 target
= GL_TEXTURE_RECTANGLE
;
2525 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2526 SetLastError(ERROR_INVALID_DATA
);
2531 case WGL_MIPMAP_TEXTURE_ARB
:
2532 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2533 pbuffer
->max_level
= 0;
2536 int size
= min(iWidth
, iHeight
) / 2;
2539 pbuffer
->max_level
++;
2546 WARN("unknown attribute 0x%x\n", attr
);
2547 SetLastError(ERROR_INVALID_DATA
);
2552 if (!target
|| !internalFormat
)
2554 pbuffer
->no_texture
= TRUE
;
2555 /* no actual way to turn off ability to texture; use most permissive target */
2556 target
= GL_TEXTURE_RECTANGLE
;
2557 internalFormat
= GL_RGB
;
2560 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2561 if (err
!= kCGLNoError
)
2563 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2564 pbuffer
->pbuffer
= NULL
;
2565 if (err
== kCGLBadAlloc
)
2566 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2568 SetLastError(ERROR_INVALID_DATA
);
2572 if (!pbuffer
->pbuffer
)
2574 HeapFree(GetProcessHeap(), 0, pbuffer
);
2578 TRACE(" -> %p\n", pbuffer
);
2583 /**********************************************************************
2584 * macdrv_wglDestroyPbufferARB
2586 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2588 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2590 TRACE("pbuffer %p\n", pbuffer
);
2591 if (pbuffer
&& pbuffer
->pbuffer
)
2592 CGLReleasePBuffer(pbuffer
->pbuffer
);
2593 HeapFree(GetProcessHeap(), 0, pbuffer
);
2598 /**********************************************************************
2599 * macdrv_wglGetExtensionsStringARB
2601 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2603 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2605 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2606 this can be specific to the CGL renderer like we're supposed to do. */
2607 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2608 return gl_info
.wglExtensions
;
2612 /**********************************************************************
2613 * macdrv_wglGetExtensionsStringEXT
2615 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2617 static const char *macdrv_wglGetExtensionsStringEXT(void)
2619 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2620 return gl_info
.wglExtensions
;
2624 /**********************************************************************
2625 * macdrv_wglGetPbufferDCARB
2627 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2629 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2632 struct wgl_pbuffer
*prev
;
2634 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2637 EnterCriticalSection(&dc_pbuffers_section
);
2638 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2641 CGLReleasePBuffer(prev
->pbuffer
);
2642 HeapFree(GetProcessHeap(), 0, prev
);
2644 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2645 LeaveCriticalSection(&dc_pbuffers_section
);
2647 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2652 /**********************************************************************
2653 * macdrv_wglGetPixelFormatAttribivARB
2655 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2657 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2658 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2660 const pixel_format
*pf
;
2663 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2664 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2666 if (!nAttributes
) return GL_TRUE
;
2668 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2670 piValues
[0] = nb_formats
;
2671 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2675 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2678 WARN("invalid pixel format %d\n", iPixelFormat
);
2679 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2683 for (i
= 0; i
< nAttributes
; ++i
)
2685 switch (piAttributes
[i
])
2687 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2688 piValues
[i
] = nb_formats
;
2691 case WGL_DRAW_TO_WINDOW_ARB
:
2692 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2695 case WGL_DRAW_TO_BITMAP_ARB
:
2696 piValues
[i
] = GL_FALSE
;
2699 case WGL_ACCELERATION_ARB
:
2700 if (iLayerPlane
) goto invalid_layer
;
2701 if (pf
->accelerated
)
2702 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2704 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2707 case WGL_NEED_PALETTE_ARB
:
2708 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2709 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2710 piValues
[i
] = GL_FALSE
;
2713 case WGL_SWAP_METHOD_ARB
:
2714 if (pf
->double_buffer
&& pf
->backing_store
)
2715 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2717 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2720 case WGL_NUMBER_OVERLAYS_ARB
:
2721 case WGL_NUMBER_UNDERLAYS_ARB
:
2725 case WGL_TRANSPARENT_ARB
:
2726 if (iLayerPlane
) goto invalid_layer
;
2727 piValues
[i
] = GL_FALSE
;
2730 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2731 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2732 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2733 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2734 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2735 if (iLayerPlane
) goto invalid_layer
;
2739 case WGL_SHARE_DEPTH_ARB
:
2740 case WGL_SHARE_STENCIL_ARB
:
2741 case WGL_SHARE_ACCUM_ARB
:
2742 if (iLayerPlane
) goto invalid_layer
;
2743 piValues
[i
] = GL_TRUE
;
2746 case WGL_SUPPORT_GDI_ARB
:
2747 if (iLayerPlane
) goto invalid_layer
;
2748 piValues
[i
] = GL_FALSE
;
2751 case WGL_SUPPORT_OPENGL_ARB
:
2752 if (iLayerPlane
) goto invalid_layer
;
2753 piValues
[i
] = GL_TRUE
;
2756 case WGL_DOUBLE_BUFFER_ARB
:
2757 if (iLayerPlane
) goto invalid_layer
;
2758 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2761 case WGL_STEREO_ARB
:
2762 if (iLayerPlane
) goto invalid_layer
;
2763 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2766 case WGL_PIXEL_TYPE_ARB
:
2767 if (iLayerPlane
) goto invalid_layer
;
2768 if (color_modes
[pf
->color_mode
].is_float
)
2769 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2771 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2772 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2773 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2774 However, Mac contexts don't support rendering to unsigned floating-point
2775 formats, even when GL_EXT_packed_float is supported. */
2778 case WGL_COLOR_BITS_ARB
:
2779 if (iLayerPlane
) goto invalid_layer
;
2780 /* If the mode doesn't have alpha, return bits per pixel instead
2781 of color bits. On Windows, color bits sometimes exceeds r+g+b
2782 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2783 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2784 pixel format, we need to accommodate that. */
2785 if (color_modes
[pf
->color_mode
].alpha_bits
)
2786 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2788 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2791 case WGL_RED_BITS_ARB
:
2792 if (iLayerPlane
) goto invalid_layer
;
2793 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2796 case WGL_RED_SHIFT_ARB
:
2797 if (iLayerPlane
) goto invalid_layer
;
2798 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2801 case WGL_GREEN_BITS_ARB
:
2802 if (iLayerPlane
) goto invalid_layer
;
2803 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2806 case WGL_GREEN_SHIFT_ARB
:
2807 if (iLayerPlane
) goto invalid_layer
;
2808 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2811 case WGL_BLUE_BITS_ARB
:
2812 if (iLayerPlane
) goto invalid_layer
;
2813 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2816 case WGL_BLUE_SHIFT_ARB
:
2817 if (iLayerPlane
) goto invalid_layer
;
2818 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2821 case WGL_ALPHA_BITS_ARB
:
2822 if (iLayerPlane
) goto invalid_layer
;
2823 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2826 case WGL_ALPHA_SHIFT_ARB
:
2827 if (iLayerPlane
) goto invalid_layer
;
2828 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2831 case WGL_ACCUM_BITS_ARB
:
2832 if (iLayerPlane
) goto invalid_layer
;
2834 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2839 case WGL_ACCUM_RED_BITS_ARB
:
2840 if (iLayerPlane
) goto invalid_layer
;
2842 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2847 case WGL_ACCUM_GREEN_BITS_ARB
:
2848 if (iLayerPlane
) goto invalid_layer
;
2850 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2855 case WGL_ACCUM_BLUE_BITS_ARB
:
2856 if (iLayerPlane
) goto invalid_layer
;
2858 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2863 case WGL_ACCUM_ALPHA_BITS_ARB
:
2864 if (iLayerPlane
) goto invalid_layer
;
2866 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2871 case WGL_DEPTH_BITS_ARB
:
2872 if (iLayerPlane
) goto invalid_layer
;
2873 piValues
[i
] = pf
->depth_bits
;
2876 case WGL_STENCIL_BITS_ARB
:
2877 if (iLayerPlane
) goto invalid_layer
;
2878 piValues
[i
] = pf
->stencil_bits
;
2881 case WGL_AUX_BUFFERS_ARB
:
2882 if (iLayerPlane
) goto invalid_layer
;
2883 piValues
[i
] = pf
->aux_buffers
;
2886 case WGL_SAMPLE_BUFFERS_ARB
:
2887 if (iLayerPlane
) goto invalid_layer
;
2888 piValues
[i
] = pf
->sample_buffers
;
2891 case WGL_SAMPLES_ARB
:
2892 if (iLayerPlane
) goto invalid_layer
;
2893 piValues
[i
] = pf
->samples
;
2896 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2897 if (iLayerPlane
) goto invalid_layer
;
2898 /* sRGB is only supported for 8-bit integer color components */
2899 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2900 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2901 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2902 !color_modes
[pf
->color_mode
].is_float
)
2903 piValues
[i
] = GL_TRUE
;
2905 piValues
[i
] = GL_FALSE
;
2908 case WGL_DRAW_TO_PBUFFER_ARB
:
2909 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2910 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2911 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2914 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2915 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2916 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2919 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2920 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2923 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2924 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2927 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2928 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2932 WARN("invalid attribute %x\n", piAttributes
[i
]);
2936 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2942 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2947 /**********************************************************************
2948 * macdrv_wglGetPixelFormatAttribfvARB
2950 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2952 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2953 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2958 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2959 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2961 /* Allocate a temporary array to store integer values */
2962 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2965 ERR("couldn't allocate %d array\n", nAttributes
);
2969 /* Piggy-back on wglGetPixelFormatAttribivARB */
2970 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2975 /* Convert integer values to float. Should also check for attributes
2976 that can give decimal values here */
2977 for (i
= 0; i
< nAttributes
; i
++)
2978 pfValues
[i
] = attr
[i
];
2981 HeapFree(GetProcessHeap(), 0, attr
);
2986 /**********************************************************************
2987 * macdrv_wglGetSwapIntervalEXT
2989 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2991 static int macdrv_wglGetSwapIntervalEXT(void)
2993 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2994 struct macdrv_win_data
*data
;
3000 if ((data
= get_win_data(context
->draw_hwnd
)))
3002 value
= data
->swap_interval
;
3003 release_win_data(data
);
3005 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3006 set_swap_interval(context
, value
);
3010 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3011 if (err
!= kCGLNoError
)
3013 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3014 err
, CGLErrorString(err
));
3023 /***********************************************************************
3024 * macdrv_wglMakeContextCurrentARB
3026 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3028 * This is not supported directly by OpenGL on the Mac. We emulate it
3029 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3030 * temporarily swap the drawable. This follows the technique used in
3031 * the implementation of Mesa GLX for Apple.
3033 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3035 struct macdrv_win_data
*data
;
3038 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3039 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3043 macdrv_make_context_current(NULL
, NULL
);
3044 NtCurrentTeb()->glContext
= NULL
;
3048 if ((hwnd
= WindowFromDC(draw_hdc
)))
3050 if (!(data
= get_win_data(hwnd
)))
3052 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3056 if (!data
->pixel_format
)
3058 WARN("no pixel format set\n");
3059 release_win_data(data
);
3060 SetLastError(ERROR_INVALID_HANDLE
);
3063 if (context
->format
!= data
->pixel_format
)
3065 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3066 release_win_data(data
);
3067 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3071 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
3072 set_swap_interval(context
, data
->swap_interval
);
3074 context
->draw_hwnd
= hwnd
;
3075 context
->draw_view
= data
->gl_view
;
3076 context
->draw_pbuffer
= NULL
;
3077 release_win_data(data
);
3081 struct wgl_pbuffer
*pbuffer
;
3083 EnterCriticalSection(&dc_pbuffers_section
);
3084 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3087 if (context
->format
!= pbuffer
->format
)
3089 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3090 LeaveCriticalSection(&dc_pbuffers_section
);
3091 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3096 (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
))
3097 set_swap_interval(context
, 0);
3101 WARN("no window or pbuffer for DC\n");
3102 LeaveCriticalSection(&dc_pbuffers_section
);
3103 SetLastError(ERROR_INVALID_HANDLE
);
3107 context
->draw_hwnd
= NULL
;
3108 context
->draw_view
= NULL
;
3109 context
->draw_pbuffer
= pbuffer
;
3110 LeaveCriticalSection(&dc_pbuffers_section
);
3113 context
->read_view
= NULL
;
3114 context
->read_pbuffer
= NULL
;
3115 if (read_hdc
&& read_hdc
!= draw_hdc
)
3117 if ((hwnd
= WindowFromDC(read_hdc
)))
3119 if ((data
= get_win_data(hwnd
)))
3121 if (data
->gl_view
!= context
->draw_view
)
3122 context
->read_view
= data
->gl_view
;
3123 release_win_data(data
);
3128 EnterCriticalSection(&dc_pbuffers_section
);
3129 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3130 LeaveCriticalSection(&dc_pbuffers_section
);
3134 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3135 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
3137 make_context_current(context
, FALSE
);
3138 context
->has_been_current
= TRUE
;
3139 NtCurrentTeb()->glContext
= context
;
3145 /**********************************************************************
3146 * macdrv_wglQueryPbufferARB
3148 * WGL_ARB_pbuffer: wglQueryPbufferARB
3150 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3156 GLenum internalFormat
;
3159 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3161 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3162 if (err
!= kCGLNoError
)
3164 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3165 SetLastError(ERROR_INVALID_HANDLE
);
3171 case WGL_PBUFFER_WIDTH_ARB
:
3174 case WGL_PBUFFER_HEIGHT_ARB
:
3177 case WGL_PBUFFER_LOST_ARB
:
3178 /* Mac PBuffers can't be lost */
3179 *piValue
= GL_FALSE
;
3181 case WGL_TEXTURE_FORMAT_ARB
:
3182 if (pbuffer
->no_texture
)
3183 *piValue
= WGL_NO_TEXTURE_ARB
;
3184 else switch (internalFormat
)
3187 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3191 *piValue
= WGL_TEXTURE_RGB_ARB
;
3195 case WGL_TEXTURE_TARGET_ARB
:
3196 if (pbuffer
->no_texture
)
3197 *piValue
= WGL_NO_TEXTURE_ARB
;
3198 else switch (target
)
3200 case GL_TEXTURE_CUBE_MAP
:
3201 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3204 *piValue
= WGL_TEXTURE_2D_ARB
;
3206 case GL_TEXTURE_RECTANGLE
:
3208 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3212 case WGL_MIPMAP_TEXTURE_ARB
:
3213 *piValue
= (pbuffer
->max_level
> 0);
3215 case WGL_MIPMAP_LEVEL_ARB
:
3216 *piValue
= pbuffer
->level
;
3218 case WGL_CUBE_MAP_FACE_ARB
:
3219 switch (pbuffer
->face
)
3221 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3223 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3225 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3226 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3228 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3229 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3231 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3232 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3234 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3235 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3238 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3243 WARN("invalid attribute 0x%x\n", iAttribute
);
3244 SetLastError(ERROR_INVALID_DATA
);
3252 /**********************************************************************
3253 * macdrv_wglReleasePbufferDCARB
3255 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3257 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3259 struct wgl_pbuffer
*prev
;
3261 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3263 EnterCriticalSection(&dc_pbuffers_section
);
3265 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3268 if (prev
!= pbuffer
)
3269 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3270 CGLReleasePBuffer(prev
->pbuffer
);
3271 HeapFree(GetProcessHeap(), 0, prev
);
3272 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3276 LeaveCriticalSection(&dc_pbuffers_section
);
3278 return hdc
&& DeleteDC(hdc
);
3282 /**********************************************************************
3283 * macdrv_wglReleaseTexImageARB
3285 * WGL_ARB_render_texture: wglReleaseTexImageARB
3287 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3289 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3292 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3294 if (pbuffer
->no_texture
)
3296 SetLastError(ERROR_INVALID_OPERATION
);
3300 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3301 if (err
!= kCGLNoError
)
3303 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3304 SetLastError(ERROR_INVALID_OPERATION
);
3312 /**********************************************************************
3313 * macdrv_wglSetPbufferAttribARB
3315 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3317 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
3319 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3321 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
3323 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3325 int attr
= piAttribList
[0];
3326 int value
= piAttribList
[1];
3329 case WGL_MIPMAP_LEVEL_ARB
:
3330 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
3331 pbuffer
->level
= value
;
3333 case WGL_CUBE_MAP_FACE_ARB
:
3336 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3337 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3338 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
3340 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3341 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3342 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
3344 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3345 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3346 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
3348 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3349 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3350 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
3352 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3353 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3354 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
3356 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3357 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3358 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
3361 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
3362 SetLastError(ERROR_INVALID_DATA
);
3367 WARN("invalide attribute 0x%x\n", attr
);
3368 SetLastError(ERROR_INVALID_DATA
);
3373 if (context
&& context
->draw_pbuffer
== pbuffer
)
3374 make_context_current(context
, FALSE
);
3380 /**********************************************************************
3381 * macdrv_wglSetPixelFormatWINE
3383 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3385 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
3387 return set_pixel_format(hdc
, fmt
, TRUE
);
3391 /**********************************************************************
3392 * macdrv_wglSwapIntervalEXT
3394 * WGL_EXT_swap_control: wglSwapIntervalEXT
3396 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
3398 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3399 BOOL changed
= FALSE
;
3401 TRACE("interval %d\n", interval
);
3405 SetLastError(ERROR_INVALID_DATA
);
3411 if (context
->draw_hwnd
)
3413 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
3416 changed
= data
->swap_interval
!= interval
;
3418 data
->swap_interval
= interval
;
3419 release_win_data(data
);
3425 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
3426 if (!set_swap_interval(context
, interval
))
3428 SetLastError(ERROR_GEN_FAILURE
);
3434 struct wgl_context
*ctx
;
3436 EnterCriticalSection(&context_section
);
3437 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
3439 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
3440 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3442 LeaveCriticalSection(&context_section
);
3449 static void register_extension(const char *ext
)
3451 if (gl_info
.wglExtensions
[0])
3452 strcat(gl_info
.wglExtensions
, " ");
3453 strcat(gl_info
.wglExtensions
, ext
);
3455 TRACE("'%s'\n", ext
);
3458 static void load_extensions(void)
3463 register_extension("WGL_ARB_extensions_string");
3464 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
3466 register_extension("WGL_ARB_make_current_read");
3467 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
3468 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
3470 register_extension("WGL_ARB_pixel_format");
3471 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
3472 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
3473 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
3475 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
3477 register_extension("WGL_ARB_pixel_format_float");
3478 register_extension("WGL_ATI_pixel_format_float");
3481 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
3482 register_extension("WGL_ARB_multisample");
3484 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3485 register_extension("WGL_ARB_framebuffer_sRGB");
3487 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
3489 register_extension("WGL_ARB_pbuffer");
3490 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3491 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3492 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3493 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3494 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3496 register_extension("WGL_ARB_render_texture");
3497 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3498 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3499 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3501 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3502 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3503 register_extension("WGL_NV_render_texture_rectangle");
3506 register_extension("WGL_ARB_create_context");
3507 register_extension("WGL_ARB_create_context_profile");
3508 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
3513 register_extension("WGL_EXT_extensions_string");
3514 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3518 register_extension("WGL_EXT_swap_control");
3519 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3520 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3523 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3524 check for either, so register them separately. */
3525 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3526 register_extension("WGL_EXT_framebuffer_sRGB");
3528 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3529 register_extension("WGL_EXT_pixel_format_packed_float");
3532 * WINE-specific WGL Extensions
3535 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3536 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3538 register_extension("WGL_WINE_pixel_format_passthrough");
3539 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3543 static BOOL
init_opengl(void)
3545 static BOOL init_done
= FALSE
;
3549 if (init_done
) return (opengl_handle
!= NULL
);
3554 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3557 WARN("CFDictionaryCreateMutable failed\n");
3561 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3564 ERR("Failed to load OpenGL: %s\n", buffer
);
3565 ERR("OpenGL support is disabled.\n");
3569 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3571 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3573 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3578 /* redirect some standard OpenGL functions */
3579 #define REDIRECT(func) \
3580 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3581 REDIRECT(glCopyPixels
);
3582 REDIRECT(glGetString
);
3583 REDIRECT(glReadPixels
);
3584 REDIRECT(glViewport
);
3585 if (skip_single_buffer_flushes
|| allow_vsync
)
3591 /* redirect some OpenGL extension functions */
3592 #define REDIRECT(func) \
3593 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3594 REDIRECT(glCopyColorTable
);
3597 if (!init_gl_info())
3600 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3601 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3604 if (!init_pixel_formats())
3610 wine_dlclose(opengl_handle
, NULL
, 0);
3611 opengl_handle
= NULL
;
3616 /***********************************************************************
3619 * Synchronize the Mac GL view position with the Windows child window
3622 void sync_gl_view(struct macdrv_win_data
*data
)
3626 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3628 if (!data
->gl_view
) return;
3630 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3632 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3633 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3634 data
->gl_rect
= rect
;
3639 /**********************************************************************
3640 * macdrv_wglDescribePixelFormat
3642 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3644 const pixel_format
*pf
;
3645 const struct color_mode
*mode
;
3647 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3649 if (!descr
) return nb_displayable_formats
;
3650 if (size
< sizeof(*descr
)) return 0;
3652 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3655 memset(descr
, 0, sizeof(*descr
));
3656 descr
->nSize
= sizeof(*descr
);
3657 descr
->nVersion
= 1;
3659 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3660 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3661 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3662 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3663 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3664 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3666 descr
->iPixelType
= PFD_TYPE_RGBA
;
3668 mode
= &color_modes
[pf
->color_mode
];
3669 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3670 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3671 R8G8B8A0 pixel format). If an app depends on that and expects that
3672 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3673 if (mode
->alpha_bits
)
3674 descr
->cColorBits
= mode
->color_bits
;
3676 descr
->cColorBits
= mode
->bits_per_pixel
;
3677 descr
->cRedBits
= mode
->red_bits
;
3678 descr
->cRedShift
= mode
->red_shift
;
3679 descr
->cGreenBits
= mode
->green_bits
;
3680 descr
->cGreenShift
= mode
->green_shift
;
3681 descr
->cBlueBits
= mode
->blue_bits
;
3682 descr
->cBlueShift
= mode
->blue_shift
;
3683 descr
->cAlphaBits
= mode
->alpha_bits
;
3684 descr
->cAlphaShift
= mode
->alpha_shift
;
3688 mode
= &color_modes
[pf
->accum_mode
- 1];
3689 descr
->cAccumBits
= mode
->color_bits
;
3690 descr
->cAccumRedBits
= mode
->red_bits
;
3691 descr
->cAccumGreenBits
= mode
->green_bits
;
3692 descr
->cAccumBlueBits
= mode
->blue_bits
;
3693 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3696 descr
->cDepthBits
= pf
->depth_bits
;
3697 descr
->cStencilBits
= pf
->stencil_bits
;
3698 descr
->cAuxBuffers
= pf
->aux_buffers
;
3699 descr
->iLayerType
= PFD_MAIN_PLANE
;
3701 TRACE("%s\n", debugstr_pf(pf
));
3702 return nb_displayable_formats
;
3705 /***********************************************************************
3706 * macdrv_wglCopyContext
3708 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3712 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3714 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3715 if (err
!= kCGLNoError
)
3716 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3717 return (err
== kCGLNoError
);
3720 /***********************************************************************
3721 * macdrv_wglCreateContext
3723 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3725 struct wgl_context
*context
;
3727 TRACE("hdc %p\n", hdc
);
3729 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
3734 /***********************************************************************
3735 * macdrv_wglDeleteContext
3737 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3739 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3741 EnterCriticalSection(&context_section
);
3742 list_remove(&context
->entry
);
3743 LeaveCriticalSection(&context_section
);
3745 macdrv_dispose_opengl_context(context
->context
);
3746 HeapFree(GetProcessHeap(), 0, context
);
3749 /***********************************************************************
3750 * macdrv_wglGetPixelFormat
3752 static int macdrv_wglGetPixelFormat(HDC hdc
)
3756 format
= get_dc_pixel_format(hdc
);
3758 if (!is_valid_pixel_format(format
)) /* not set yet */
3760 else if (!is_displayable_pixel_format(format
))
3762 /* Non-displayable formats can't be used with traditional WGL calls.
3763 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3767 TRACE(" hdc %p -> %d\n", hdc
, format
);
3771 /***********************************************************************
3772 * macdrv_wglGetProcAddress
3774 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3778 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3779 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3785 if (dladdr(ret
, &info
))
3786 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3788 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3792 WARN("failed to find proc %s\n", debugstr_a(proc
));
3796 /***********************************************************************
3797 * macdrv_wglMakeCurrent
3799 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3801 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3802 (context
? context
->cglcontext
: NULL
));
3804 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3807 /**********************************************************************
3808 * macdrv_wglSetPixelFormat
3810 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3812 return set_pixel_format(hdc
, fmt
, FALSE
);
3815 /***********************************************************************
3816 * macdrv_wglShareLists
3818 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3820 macdrv_opengl_context saved_context
;
3821 CGLContextObj saved_cglcontext
;
3823 TRACE("org %p dest %p\n", org
, dest
);
3825 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3826 * at context creation time but in case of WGL it is done using wglShareLists.
3828 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3829 * and when a program requests sharing we recreate the destination context if it hasn't been made
3830 * current or when it hasn't shared display lists before.
3833 if (dest
->has_been_current
)
3835 WARN("could not share display lists, the destination context has been current already\n");
3838 else if (dest
->sharing
)
3840 WARN("could not share display lists because dest has already shared lists before\n");
3844 /* Re-create the Mac context and share display lists */
3845 saved_context
= dest
->context
;
3846 saved_cglcontext
= dest
->cglcontext
;
3847 dest
->context
= NULL
;
3848 dest
->cglcontext
= NULL
;
3849 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
3851 dest
->context
= saved_context
;
3852 dest
->cglcontext
= saved_cglcontext
;
3856 /* Implicitly disposes of saved_cglcontext. */
3857 macdrv_dispose_opengl_context(saved_context
);
3859 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3860 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3862 org
->sharing
= TRUE
;
3863 dest
->sharing
= TRUE
;
3868 /**********************************************************************
3869 * macdrv_wglSwapBuffers
3871 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3873 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3877 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3878 (context
? context
->cglcontext
: NULL
));
3881 sync_swap_interval(context
);
3883 if ((hwnd
= WindowFromDC(hdc
)))
3885 struct macdrv_win_data
*data
;
3887 if (!(data
= get_win_data(hwnd
)))
3889 SetLastError(ERROR_INVALID_HANDLE
);
3893 if (context
&& context
->draw_view
== data
->gl_view
)
3896 release_win_data(data
);
3900 struct wgl_pbuffer
*pbuffer
;
3902 EnterCriticalSection(&dc_pbuffers_section
);
3903 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3904 LeaveCriticalSection(&dc_pbuffers_section
);
3908 SetLastError(ERROR_INVALID_HANDLE
);
3912 if (context
&& context
->draw_pbuffer
== pbuffer
)
3917 macdrv_flush_opengl_context(context
->context
);
3920 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3922 /* If there is a current context, then wglSwapBuffers should do an implicit
3923 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3924 in the other branch, but we have to do it explicitly here. */
3932 static struct opengl_funcs opengl_funcs
=
3935 macdrv_wglCopyContext
, /* p_wglCopyContext */
3936 macdrv_wglCreateContext
, /* p_wglCreateContext */
3937 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3938 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3939 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3940 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3941 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3942 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3943 macdrv_wglShareLists
, /* p_wglShareLists */
3944 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3948 /**********************************************************************
3949 * macdrv_wine_get_wgl_driver
3951 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3953 if (version
!= WINE_WGL_DRIVER_VERSION
)
3955 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3959 if (!init_opengl()) return (void *)-1;
3961 return &opengl_funcs
;