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
);
49 char wglExtensions
[4096];
51 GLint max_viewport_dims
[2];
53 unsigned int max_major
, max_minor
;
56 static struct gl_info gl_info
;
63 macdrv_opengl_context context
;
64 CGLContextObj cglcontext
;
66 macdrv_view draw_view
;
67 struct wgl_pbuffer
*draw_pbuffer
;
68 macdrv_view read_view
;
69 struct wgl_pbuffer
*read_pbuffer
;
70 BOOL has_been_current
;
72 LONG update_swap_interval
;
73 DWORD last_flush_time
;
77 static struct list context_list
= LIST_INIT(context_list
);
79 static CRITICAL_SECTION context_section
;
80 static CRITICAL_SECTION_DEBUG critsect_debug
=
82 0, 0, &context_section
,
83 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
84 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
86 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
91 CGLPBufferObj pbuffer
;
99 static CFMutableDictionaryRef dc_pbuffers
;
101 static CRITICAL_SECTION dc_pbuffers_section
;
102 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
104 0, 0, &dc_pbuffers_section
,
105 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
106 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
108 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
111 static struct opengl_funcs opengl_funcs
;
113 #define USE_GL_FUNC(name) #name,
114 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
118 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
120 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
121 static void (*pglFinish
)(void);
122 static void (*pglFlush
)(void);
123 static void (*pglFlushRenderAPPLE
)(void);
124 static const GLubyte
*(*pglGetString
)(GLenum name
);
125 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
126 GLenum format
, GLenum type
, void *pixels
);
127 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
133 GLint color_bits
; /* including alpha_bits */
134 int red_bits
, red_shift
;
135 int green_bits
, green_shift
;
136 int blue_bits
, blue_shift
;
137 GLint alpha_bits
, alpha_shift
;
142 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
143 observations of the behavior of Windows systems, but also subjective judgments
144 about what color formats are more "normal" than others.
146 On at least some Windows systems, integer color formats are listed before
147 floating-point formats. Within the integer formats, higher color bits were
148 usually listed before lower color bits, while for floating-point formats it
149 was the reverse. However, that leads D3D to select 64-bit integer formats in
150 preference to 32-bit formats when the latter would be sufficient. It seems
151 that a 32-bit format is much more likely to be normally used in that case.
153 Also, there are certain odd color formats supported on the Mac which seem like
154 they would be less appropriate than more common ones. For instance, the color
155 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
156 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
159 For two color formats which differ only in whether or not they have alpha bits,
160 we use the same ordering. pixel_format_comparator() gives alpha bits a
161 different weight than color formats.
163 static const struct color_mode color_modes
[] = {
164 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
165 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
166 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
167 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
168 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
169 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
170 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
171 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
172 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
173 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
174 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
175 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
176 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
177 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
178 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
179 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
180 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
181 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
182 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
183 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
184 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
185 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
186 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
187 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
191 static const struct {
194 } depth_stencil_modes
[] = {
222 GLint max_aux_buffers
;
223 GLint max_sample_buffers
;
230 } renderer_properties
;
234 unsigned int window
:1;
235 unsigned int pbuffer
:1;
236 unsigned int accelerated
:1;
237 unsigned int color_mode
:5; /* index into color_modes table */
238 unsigned int aux_buffers
:3;
239 unsigned int depth_bits
:8;
240 unsigned int stencil_bits
:8;
241 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
242 unsigned int double_buffer
:1;
243 unsigned int stereo
:1;
244 unsigned int sample_buffers
:1;
245 unsigned int samples
:5;
246 unsigned int backing_store
:1;
254 } pixel_format_or_code
;
255 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
258 static pixel_format
*pixel_formats
;
259 static int nb_formats
, nb_displayable_formats
;
262 static void *opengl_handle
;
265 static const char* debugstr_attrib(int attrib
, int value
)
267 static const struct {
271 #define ATTRIB(a) { a, #a }
272 ATTRIB(WGL_ACCELERATION_ARB
),
273 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
274 ATTRIB(WGL_ACCUM_BITS_ARB
),
275 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
276 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
277 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
278 ATTRIB(WGL_ALPHA_BITS_ARB
),
279 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
280 ATTRIB(WGL_AUX_BUFFERS_ARB
),
281 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
285 ATTRIB(WGL_BLUE_BITS_ARB
),
286 ATTRIB(WGL_BLUE_SHIFT_ARB
),
287 ATTRIB(WGL_COLOR_BITS_ARB
),
288 ATTRIB(WGL_DEPTH_BITS_ARB
),
289 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
290 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
291 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
292 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
293 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
294 ATTRIB(WGL_GREEN_BITS_ARB
),
295 ATTRIB(WGL_GREEN_SHIFT_ARB
),
296 ATTRIB(WGL_NEED_PALETTE_ARB
),
297 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
298 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
299 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
300 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
301 ATTRIB(WGL_PIXEL_TYPE_ARB
),
302 ATTRIB(WGL_RED_BITS_ARB
),
303 ATTRIB(WGL_RED_SHIFT_ARB
),
304 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
305 ATTRIB(WGL_SAMPLES_ARB
),
306 ATTRIB(WGL_SHARE_ACCUM_ARB
),
307 ATTRIB(WGL_SHARE_DEPTH_ARB
),
308 ATTRIB(WGL_SHARE_STENCIL_ARB
),
309 ATTRIB(WGL_STENCIL_BITS_ARB
),
310 ATTRIB(WGL_STEREO_ARB
),
311 ATTRIB(WGL_SUPPORT_GDI_ARB
),
312 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
313 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
314 ATTRIB(WGL_SWAP_METHOD_ARB
),
315 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
316 ATTRIB(WGL_TRANSPARENT_ARB
),
317 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
318 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
319 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
320 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
324 const char *attrib_name
= NULL
;
325 const char *value_name
= NULL
;
327 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
329 if (attrib_names
[i
].attrib
== attrib
)
331 attrib_name
= attrib_names
[i
].name
;
337 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
341 case WGL_ACCELERATION_ARB
:
344 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
345 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
346 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
349 case WGL_PIXEL_TYPE_ARB
:
352 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
353 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
354 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
355 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
358 case WGL_SWAP_METHOD_ARB
:
361 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
362 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
363 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
369 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
371 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
375 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
376 CGLRendererProperty property
, GLint
*value
)
378 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
379 if (err
!= kCGLNoError
)
380 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
381 return (err
== kCGLNoError
);
385 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
389 memset(properties
, 0, sizeof(*properties
));
391 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
392 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
394 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
395 properties
->buffer_modes
= value
;
397 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
398 properties
->color_modes
= value
;
400 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
401 properties
->accum_modes
= value
;
403 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
404 properties
->depth_modes
= value
;
406 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
407 properties
->stencil_modes
= value
;
409 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
410 properties
->max_aux_buffers
= value
;
412 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
413 properties
->max_sample_buffers
= value
;
415 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
416 properties
->max_samples
= value
;
418 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
419 properties
->offscreen
= (value
!= 0);
421 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
422 properties
->accelerated
= (value
!= 0);
424 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
425 properties
->backing_store
= (value
!= 0);
427 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
428 properties
->window
= (value
!= 0);
430 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
431 properties
->online
= (value
!= 0);
435 static void dump_renderer(const renderer_properties
* renderer
)
439 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
440 TRACE("Buffer modes:\n");
441 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
442 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
443 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
444 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
446 TRACE("Color buffer modes:\n");
447 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
449 if (renderer
->color_modes
& color_modes
[i
].mode
)
451 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
452 if (color_modes
[i
].is_float
)
458 TRACE("Accumulation buffer sizes: { ");
459 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
461 if (renderer
->accum_modes
& color_modes
[i
].mode
)
462 TRACE("%d, ", color_modes
[i
].color_bits
);
466 TRACE("Depth buffer sizes: { ");
467 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
469 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
470 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
474 TRACE("Stencil buffer sizes: { ");
475 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
477 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
478 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
482 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
483 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
484 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
485 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
486 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
487 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
488 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
489 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
493 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
495 pixel_format_or_code pfc
;
498 pfc
.format
= *format
;
503 static inline pixel_format
pixel_format_for_code(UInt64 code
)
505 pixel_format_or_code pfc
;
512 static const char *debugstr_pf(const pixel_format
*pf
)
514 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",
518 color_modes
[pf
->color_mode
].color_bits
,
519 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
520 color_modes
[pf
->color_mode
].alpha_bits
,
523 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
530 code_for_pixel_format(pf
));
534 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
539 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
541 if ((modes
& color_modes
[i
].mode
) &&
542 color_modes
[i
].color_bits
>= color_size
&&
543 color_modes
[i
].alpha_bits
>= alpha_size
&&
544 !color_modes
[i
].is_float
== !color_float
)
546 if (best
< 0) /* no existing best choice */
548 else if (color_modes
[i
].color_bits
== color_size
&&
549 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
551 /* prefer it over a best which isn't exact or which has a higher bpp */
552 if (color_modes
[best
].color_bits
!= color_size
||
553 color_modes
[best
].alpha_bits
!= alpha_size
||
554 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
557 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
558 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
559 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
566 /* Couldn't find a match. Return first one that renderer supports. */
567 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
569 if (modes
& color_modes
[i
].mode
)
578 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
583 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
585 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
587 /* Prefer the fewest color bits, then prefer more alpha bits, then
588 prefer more bits per pixel. */
591 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
593 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
595 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
597 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
598 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
606 /* Couldn't find a match. Return last one that renderer supports. */
607 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
609 if (modes
& color_modes
[i
].mode
)
618 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
619 CFMutableSetRef pixel_format_set
)
621 CGLPixelFormatAttribute attribs
[64] = {
622 kCGLPFAMinimumPolicy
,
623 kCGLPFAClosestPolicy
,
624 kCGLPFARendererID
, renderer
.renderer_id
,
625 kCGLPFASingleRenderer
,
627 int n
= 5, n_stack
[16], n_stack_idx
= -1;
628 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
629 new_pixel_formats
= 0;
630 pixel_format request
;
631 unsigned int double_buffer
;
632 unsigned int accelerated
= renderer
.accelerated
;
636 attribs
[n
++] = kCGLPFAAccelerated
;
637 attribs
[n
++] = kCGLPFANoRecovery
;
639 else if (!allow_software_rendering
)
641 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
645 n_stack
[++n_stack_idx
] = n
;
646 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
650 n
= n_stack
[n_stack_idx
];
652 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
653 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
657 attribs
[n
++] = kCGLPFADoubleBuffer
;
658 memset(&request
, 0, sizeof(request
));
659 request
.accelerated
= accelerated
;
660 request
.double_buffer
= double_buffer
;
662 /* Don't bother with in-between aux buffers values: either 0 or max. */
663 n_stack
[++n_stack_idx
] = n
;
664 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
666 unsigned int color_mode
;
668 n
= n_stack
[n_stack_idx
];
670 attribs
[n
++] = kCGLPFAAuxBuffers
;
672 request
.aux_buffers
= aux
;
674 n_stack
[++n_stack_idx
] = n
;
675 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
677 unsigned int depth_mode
;
679 n
= n_stack
[n_stack_idx
];
681 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
684 attribs
[n
++] = kCGLPFAColorSize
;
685 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
686 attribs
[n
++] = kCGLPFAAlphaSize
;
687 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
688 if (color_modes
[color_mode
].is_float
)
689 attribs
[n
++] = kCGLPFAColorFloat
;
690 request
.color_mode
= color_mode
;
692 n_stack
[++n_stack_idx
] = n
;
693 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
695 unsigned int stencil_mode
;
697 n
= n_stack
[n_stack_idx
];
699 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
702 attribs
[n
++] = kCGLPFADepthSize
;
703 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
704 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
706 n_stack
[++n_stack_idx
] = n
;
707 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
711 n
= n_stack
[n_stack_idx
];
713 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
715 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
718 attribs
[n
++] = kCGLPFAStencilSize
;
719 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
720 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
722 /* FIXME: Could trim search space a bit here depending on GPU.
723 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
724 n_stack
[++n_stack_idx
] = n
;
725 for (stereo
= 0; stereo
<= 1; stereo
++)
729 n
= n_stack
[n_stack_idx
];
731 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
732 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
736 attribs
[n
++] = kCGLPFAStereo
;
737 request
.stereo
= stereo
;
739 /* Starts at -1 for a 0 accum size */
740 n_stack
[++n_stack_idx
] = n
;
741 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
743 unsigned int target_pass
;
745 n
= n_stack
[n_stack_idx
];
749 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
752 attribs
[n
++] = kCGLPFAAccumSize
;
753 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
754 request
.accum_mode
= accum_mode
+ 1;
757 request
.accum_mode
= 0;
759 /* Targets to request are:
760 accelerated: window OR window + pbuffer
761 software: window + pbuffer */
762 n_stack
[++n_stack_idx
] = n
;
763 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
765 unsigned int samples
, max_samples
;
767 n
= n_stack
[n_stack_idx
];
769 attribs
[n
++] = kCGLPFAWindow
;
772 if (!accelerated
|| target_pass
> 0)
774 attribs
[n
++] = kCGLPFAPBuffer
;
780 /* FIXME: Could trim search space a bit here depending on GPU.
781 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
782 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
783 n_stack
[++n_stack_idx
] = n
;
784 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
785 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
787 unsigned int backing_store
, min_backing_store
, max_backing_store
;
789 n
= n_stack
[n_stack_idx
];
793 attribs
[n
++] = kCGLPFASampleBuffers
;
794 attribs
[n
++] = renderer
.max_sample_buffers
;
795 attribs
[n
++] = kCGLPFASamples
;
796 attribs
[n
++] = samples
;
797 request
.sample_buffers
= renderer
.max_sample_buffers
;
798 request
.samples
= samples
;
801 request
.sample_buffers
= request
.samples
= 0;
803 if (renderer
.backing_store
&& double_buffer
)
805 /* The software renderer seems to always preserve the backing store, whether
806 we ask for it or not. So don't bother not asking for it. */
807 min_backing_store
= accelerated
? 0 : 1;
808 max_backing_store
= 1;
811 min_backing_store
= max_backing_store
= 0;
812 n_stack
[++n_stack_idx
] = n
;
813 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
815 CGLPixelFormatObj pix
;
816 GLint virtualScreens
;
819 n
= n_stack
[n_stack_idx
];
822 attribs
[n
++] = kCGLPFABackingStore
;
823 request
.backing_store
= backing_store
;
827 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
828 if (err
== kCGLNoError
&& pix
)
831 GLint value
, color_size
, alpha_size
, color_float
;
833 CFNumberRef code_object
;
836 memset(&pf
, 0, sizeof(pf
));
838 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
839 pf
.accelerated
= value
;
840 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
841 pf
.aux_buffers
= value
;
842 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
843 pf
.depth_bits
= value
;
844 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
845 pf
.double_buffer
= value
;
846 if (pf
.double_buffer
&&
847 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
848 pf
.backing_store
= value
;
849 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
851 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
852 pf
.sample_buffers
= value
;
853 if (pf
.sample_buffers
&&
854 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
856 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
857 pf
.stencil_bits
= value
;
858 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
860 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
863 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
865 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
867 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
869 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
871 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
872 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
874 CGLReleasePixelFormat(pix
);
876 pf_code
= code_for_pixel_format(&pf
);
878 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
879 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
880 dupe_pixel_formats
++;
883 CFSetAddValue(pixel_format_set
, code_object
);
884 CFArrayAppendValue(pixel_format_array
, code_object
);
887 CFRelease(code_object
);
889 if (pf_code
== code_for_pixel_format(&request
))
890 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
893 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
894 dupe
? " (duplicate)" : "");
899 failed_pixel_formats
++;
900 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
903 tried_pixel_formats
++;
935 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
936 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
937 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
938 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
942 /* The docs for WGL_ARB_pixel_format say:
943 Indices are assigned to pixel formats in the following order:
944 1. Accelerated pixel formats that are displayable
945 2. Accelerated pixel formats that are displayable and which have
947 3. Generic pixel formats
948 4. Accelerated pixel formats that are non displayable
950 static int pixel_format_category(pixel_format pf
)
952 /* non-displayable */
956 /* non-accelerated a.k.a. software a.k.a. generic */
960 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
961 if (color_modes
[pf
.color_mode
].is_float
)
964 /* accelerated, displayable, no extended attributes */
969 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
971 CFNumberRef number1
= val1
;
972 CFNumberRef number2
= val2
;
974 pixel_format pf1
, pf2
;
975 int category1
, category2
;
977 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
978 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
979 pf1
= pixel_format_for_code(code1
);
980 pf2
= pixel_format_for_code(code2
);
981 category1
= pixel_format_category(pf1
);
982 category2
= pixel_format_category(pf2
);
984 if (category1
< category2
)
985 return kCFCompareLessThan
;
986 if (category1
> category2
)
987 return kCFCompareGreaterThan
;
989 /* Within a category, sort the "best" formats toward the front since that's
990 what wglChoosePixelFormatARB() has to do. The ordering implemented here
991 matches at least one Windows 7 machine's behavior.
993 /* Accelerated before unaccelerated. */
994 if (pf1
.accelerated
&& !pf2
.accelerated
)
995 return kCFCompareLessThan
;
996 if (!pf1
.accelerated
&& pf2
.accelerated
)
997 return kCFCompareGreaterThan
;
999 /* Explicit color mode ordering. */
1000 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1001 return kCFCompareLessThan
;
1002 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1003 return kCFCompareGreaterThan
;
1005 /* Non-pbuffer-capable before pbuffer-capable. */
1006 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1007 return kCFCompareLessThan
;
1008 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1009 return kCFCompareGreaterThan
;
1011 /* Fewer samples before more samples. */
1012 if (pf1
.samples
< pf2
.samples
)
1013 return kCFCompareLessThan
;
1014 if (pf1
.samples
> pf2
.samples
)
1015 return kCFCompareGreaterThan
;
1017 /* Monoscopic before stereoscopic. (This is a guess.) */
1018 if (!pf1
.stereo
&& pf2
.stereo
)
1019 return kCFCompareLessThan
;
1020 if (pf1
.stereo
&& !pf2
.stereo
)
1021 return kCFCompareGreaterThan
;
1023 /* Single buffered before double buffered. */
1024 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1025 return kCFCompareLessThan
;
1026 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1027 return kCFCompareGreaterThan
;
1029 /* Possibly-optimized double buffering before backing-store-preserving
1030 double buffering. */
1031 if (!pf1
.backing_store
&& pf2
.backing_store
)
1032 return kCFCompareLessThan
;
1033 if (pf1
.backing_store
&& !pf2
.backing_store
)
1034 return kCFCompareGreaterThan
;
1036 /* Bigger depth buffer before smaller depth buffer. */
1037 if (pf1
.depth_bits
> pf2
.depth_bits
)
1038 return kCFCompareLessThan
;
1039 if (pf1
.depth_bits
< pf2
.depth_bits
)
1040 return kCFCompareGreaterThan
;
1042 /* Smaller stencil buffer before bigger stencil buffer. */
1043 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1044 return kCFCompareLessThan
;
1045 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1046 return kCFCompareGreaterThan
;
1048 /* Smaller alpha bits before larger alpha bits. */
1049 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1050 return kCFCompareLessThan
;
1051 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1052 return kCFCompareGreaterThan
;
1054 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1059 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1060 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1061 return kCFCompareLessThan
;
1062 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1063 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1064 return kCFCompareGreaterThan
;
1066 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1067 return kCFCompareLessThan
;
1068 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1069 return kCFCompareGreaterThan
;
1071 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1072 return kCFCompareLessThan
;
1073 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1074 return kCFCompareGreaterThan
;
1077 return kCFCompareGreaterThan
;
1079 else if (pf2
.accum_mode
)
1080 return kCFCompareLessThan
;
1082 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1083 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1084 return kCFCompareLessThan
;
1085 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1086 return kCFCompareGreaterThan
;
1088 /* If we get here, arbitrarily sort based on code. */
1090 return kCFCompareLessThan
;
1092 return kCFCompareGreaterThan
;
1093 return kCFCompareEqualTo
;
1097 static BOOL
init_pixel_formats(void)
1100 CGLRendererInfoObj renderer_info
;
1101 GLint rendererCount
;
1103 CFMutableSetRef pixel_format_set
;
1104 CFMutableArrayRef pixel_format_array
;
1110 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1113 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1117 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1118 if (!pixel_format_set
)
1120 WARN("CFSetCreateMutable failed\n");
1121 CGLDestroyRendererInfo(renderer_info
);
1125 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1126 if (!pixel_format_array
)
1128 WARN("CFArrayCreateMutable failed\n");
1129 CFRelease(pixel_format_set
);
1130 CGLDestroyRendererInfo(renderer_info
);
1134 for (i
= 0; i
< rendererCount
; i
++)
1136 renderer_properties renderer
;
1138 get_renderer_properties(renderer_info
, i
, &renderer
);
1141 TRACE("renderer_properties %d:\n", i
);
1142 dump_renderer(&renderer
);
1145 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1148 CFRelease(pixel_format_set
);
1149 CGLDestroyRendererInfo(renderer_info
);
1151 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1154 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1157 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1158 for (i
= 0; i
< range
.length
; i
++)
1160 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1163 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1164 pixel_formats
[i
] = pixel_format_for_code(code
);
1165 if (pixel_formats
[i
].window
)
1166 nb_displayable_formats
++;
1169 nb_formats
= range
.length
;
1170 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1174 WARN("failed to allocate pixel format list\n");
1177 WARN("got no pixel formats\n");
1179 CFRelease(pixel_format_array
);
1184 static inline BOOL
is_valid_pixel_format(int format
)
1186 return format
> 0 && format
<= nb_formats
;
1190 static inline BOOL
is_displayable_pixel_format(int format
)
1192 return format
> 0 && format
<= nb_displayable_formats
;
1196 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1198 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1199 * format in case of probing the number of pixel formats.
1201 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1203 TRACE("Returning format %d\n", format
);
1204 return &pixel_formats
[format
- 1];
1210 static BOOL
init_gl_info(void)
1212 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1213 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1215 CGDirectDisplayID display
= CGMainDisplayID();
1216 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1217 CGLPixelFormatAttribute attribs
[] = {
1218 kCGLPFADisplayMask
, displayMask
,
1221 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1222 CGLPixelFormatAttribute core_attribs
[] =
1224 kCGLPFADisplayMask
, displayMask
,
1226 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1230 CGLPixelFormatObj pix
;
1231 GLint virtualScreens
;
1233 CGLContextObj context
;
1234 CGLContextObj old_context
= CGLGetCurrentContext();
1238 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1239 if (err
!= kCGLNoError
|| !pix
)
1241 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1245 err
= CGLCreateContext(pix
, NULL
, &context
);
1246 CGLReleasePixelFormat(pix
);
1247 if (err
!= kCGLNoError
|| !context
)
1249 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1253 err
= CGLSetCurrentContext(context
);
1254 if (err
!= kCGLNoError
)
1256 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1257 CGLReleaseContext(context
);
1261 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1262 length
= strlen(str
) + sizeof(legacy_extensions
);
1264 length
+= strlen(legacy_ext_swap_control
);
1265 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1266 strcpy(gl_info
.glExtensions
, str
);
1267 strcat(gl_info
.glExtensions
, legacy_extensions
);
1269 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1271 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1273 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1274 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1275 TRACE("GL version : %s\n", str
);
1276 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1278 CGLSetCurrentContext(old_context
);
1279 CGLReleaseContext(context
);
1281 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1282 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1283 if (err
!= kCGLNoError
|| !pix
)
1285 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1286 err
, CGLErrorString(err
));
1290 err
= CGLCreateContext(pix
, NULL
, &context
);
1291 CGLReleasePixelFormat(pix
);
1292 if (err
!= kCGLNoError
|| !context
)
1294 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1295 err
, CGLErrorString(err
));
1299 err
= CGLSetCurrentContext(context
);
1300 if (err
!= kCGLNoError
)
1302 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1303 err
, CGLErrorString(err
));
1304 CGLReleaseContext(context
);
1308 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1309 TRACE("Core context GL version: %s\n", str
);
1310 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1311 CGLSetCurrentContext(old_context
);
1312 CGLReleaseContext(context
);
1319 static int get_dc_pixel_format(HDC hdc
)
1324 if ((hwnd
= WindowFromDC(hdc
)))
1326 struct macdrv_win_data
*data
;
1328 if (!(data
= get_win_data(hwnd
)))
1330 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1334 format
= data
->pixel_format
;
1335 release_win_data(data
);
1339 struct wgl_pbuffer
*pbuffer
;
1341 EnterCriticalSection(&dc_pbuffers_section
);
1342 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1344 format
= pbuffer
->format
;
1347 WARN("no window or pbuffer for DC %p\n", hdc
);
1350 LeaveCriticalSection(&dc_pbuffers_section
);
1357 /**********************************************************************
1360 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1362 const pixel_format
*pf
;
1363 CGLPixelFormatAttribute attribs
[64];
1365 CGLPixelFormatObj pix
;
1366 GLint virtualScreens
;
1368 BOOL core
= major
>= 3;
1370 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1373 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1378 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1381 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1382 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1386 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1387 attribs
[n
++] = kCGLPFAClosestPolicy
;
1389 if (pf
->accelerated
)
1391 attribs
[n
++] = kCGLPFAAccelerated
;
1392 attribs
[n
++] = kCGLPFANoRecovery
;
1396 attribs
[n
++] = kCGLPFARendererID
;
1397 attribs
[n
++] = kCGLRendererGenericFloatID
;
1400 if (pf
->double_buffer
)
1401 attribs
[n
++] = kCGLPFADoubleBuffer
;
1405 attribs
[n
++] = kCGLPFAAuxBuffers
;
1406 attribs
[n
++] = pf
->aux_buffers
;
1409 attribs
[n
++] = kCGLPFAColorSize
;
1410 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1411 attribs
[n
++] = kCGLPFAAlphaSize
;
1412 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1413 if (color_modes
[pf
->color_mode
].is_float
)
1414 attribs
[n
++] = kCGLPFAColorFloat
;
1416 attribs
[n
++] = kCGLPFADepthSize
;
1417 attribs
[n
++] = pf
->depth_bits
;
1419 attribs
[n
++] = kCGLPFAStencilSize
;
1420 attribs
[n
++] = pf
->stencil_bits
;
1423 attribs
[n
++] = kCGLPFAStereo
;
1425 if (pf
->accum_mode
&& !core
)
1427 attribs
[n
++] = kCGLPFAAccumSize
;
1428 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1431 if (pf
->pbuffer
&& !core
)
1432 attribs
[n
++] = kCGLPFAPBuffer
;
1434 if (pf
->sample_buffers
&& pf
->samples
)
1436 attribs
[n
++] = kCGLPFASampleBuffers
;
1437 attribs
[n
++] = pf
->sample_buffers
;
1438 attribs
[n
++] = kCGLPFASamples
;
1439 attribs
[n
++] = pf
->samples
;
1442 if (pf
->backing_store
)
1443 attribs
[n
++] = kCGLPFABackingStore
;
1445 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1448 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1449 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1451 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1453 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1455 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1462 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1463 if (err
!= kCGLNoError
|| !pix
)
1465 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1466 SetLastError(ERROR_INVALID_OPERATION
);
1470 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1471 CGLReleasePixelFormat(pix
);
1472 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1474 context
->cglcontext
= NULL
;
1475 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1476 SetLastError(ERROR_INVALID_OPERATION
);
1480 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1483 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1484 if (err
!= kCGLNoError
)
1485 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1487 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1490 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1491 if (err
!= kCGLNoError
)
1492 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1495 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1496 CGLReleaseContext(context
->cglcontext
);
1497 if (!context
->context
)
1499 WARN("macdrv_create_opengl_context() failed\n");
1500 SetLastError(ERROR_INVALID_OPERATION
);
1503 context
->major
= major
;
1506 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1508 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1514 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1517 *rect
= data
->client_rect
;
1519 if (data
->cocoa_window
)
1522 *window
= data
->cocoa_window
;
1523 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1527 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1528 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1529 struct macdrv_win_data
*top_data
= get_win_data(top
);
1531 if (top_data
&& top_data
->cocoa_window
)
1534 *window
= top_data
->cocoa_window
;
1535 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1536 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1541 release_win_data(top_data
);
1548 /***********************************************************************
1551 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1553 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1557 macdrv_window cocoa_window
;
1559 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1561 ERR("no top-level parent with Cocoa window in this process\n");
1565 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1568 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1572 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1573 wine_dbgstr_rect(&data
->gl_rect
));
1576 data
->pixel_format
= format
;
1582 /**********************************************************************
1585 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1587 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1589 struct macdrv_win_data
*data
;
1590 const pixel_format
*pf
;
1591 HWND hwnd
= WindowFromDC(hdc
);
1594 TRACE("hdc %p format %d\n", hdc
, fmt
);
1596 if (!hwnd
|| hwnd
== GetDesktopWindow())
1598 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1602 if (!(data
= get_win_data(hwnd
)))
1604 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1608 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1610 ret
= (data
->pixel_format
== fmt
);
1614 /* Check if fmt is in our list of supported formats to see if it is supported. */
1615 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1618 ERR("Invalid pixel format: %d\n", fmt
);
1624 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1628 if (!set_win_format(data
, fmt
))
1630 WARN("Couldn't set format of the window, returning failure\n");
1634 TRACE("pixel format:\n");
1635 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1636 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1637 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1638 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1639 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1640 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1641 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1642 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1643 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1644 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1645 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1646 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1647 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1648 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1652 release_win_data(data
);
1653 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) __wine_set_pixel_format(hwnd
, fmt
);
1658 /**********************************************************************
1659 * set_gl_view_parent
1661 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1663 struct macdrv_win_data
*data
;
1665 if (!(data
= get_win_data(hwnd
))) return;
1669 macdrv_window cocoa_window
;
1671 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1673 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1675 ERR("no top-level parent with Cocoa window in this process\n");
1676 macdrv_dispose_view(data
->gl_view
);
1677 data
->gl_view
= NULL
;
1678 release_win_data(data
);
1679 __wine_set_pixel_format( hwnd
, 0 );
1683 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1686 release_win_data(data
);
1690 /**********************************************************************
1691 * make_context_current
1693 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1696 struct wgl_pbuffer
*pbuffer
;
1700 view
= context
->read_view
;
1701 pbuffer
= context
->read_pbuffer
;
1705 view
= context
->draw_view
;
1706 pbuffer
= context
->draw_pbuffer
;
1709 if (view
|| !pbuffer
)
1710 macdrv_make_context_current(context
->context
, view
);
1713 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1715 CGLSetCurrentContext(context
->cglcontext
);
1720 /**********************************************************************
1723 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1727 /* In theory, for single-buffered contexts, there's no such thing as a swap
1728 so the swap interval shouldn't matter. But OS X will synchronize flushes
1729 of single-buffered contexts if the interval is set to non-zero. */
1730 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1733 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1734 if (err
!= kCGLNoError
)
1735 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1737 return err
== kCGLNoError
;
1741 /**********************************************************************
1742 * sync_swap_interval
1744 static void sync_swap_interval(struct wgl_context
*context
)
1746 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1750 if (context
->draw_hwnd
)
1752 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1755 interval
= data
->swap_interval
;
1756 release_win_data(data
);
1758 else /* window was destroyed? */
1764 set_swap_interval(context
, interval
);
1769 /**********************************************************************
1770 * macdrv_glCopyColorTable
1772 * Hook into glCopyColorTable as part of the implementation of
1773 * wglMakeContextCurrentARB. If the context has a separate readable,
1774 * temporarily make that current, do glCopyColorTable, and then set it
1775 * back to the drawable. This is modeled after what Mesa GLX's Apple
1776 * implementation does.
1778 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1781 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1783 if (context
->read_view
|| context
->read_pbuffer
)
1784 make_context_current(context
, TRUE
);
1786 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1788 if (context
->read_view
|| context
->read_pbuffer
)
1789 make_context_current(context
, FALSE
);
1793 /**********************************************************************
1794 * macdrv_glCopyPixels
1796 * Hook into glCopyPixels as part of the implementation of
1797 * wglMakeContextCurrentARB. If the context has a separate readable,
1798 * temporarily make that current, do glCopyPixels, and then set it back
1799 * to the drawable. This is modeled after what Mesa GLX's Apple
1800 * implementation does.
1802 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1804 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1806 if (context
->read_view
|| context
->read_pbuffer
)
1807 make_context_current(context
, TRUE
);
1809 pglCopyPixels(x
, y
, width
, height
, type
);
1811 if (context
->read_view
|| context
->read_pbuffer
)
1812 make_context_current(context
, FALSE
);
1816 /**********************************************************************
1819 static void macdrv_glFinish(void)
1821 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1823 sync_swap_interval(context
);
1828 /**********************************************************************
1831 static void macdrv_glFlush(void)
1833 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1835 sync_swap_interval(context
);
1837 if (skip_single_buffer_flushes
)
1839 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1840 DWORD now
= GetTickCount();
1842 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1843 context
->last_flush_time
, now
);
1844 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1846 TRACE("calling glFlushRenderAPPLE()\n");
1847 pglFlushRenderAPPLE();
1852 TRACE("calling glFlush()\n");
1853 context
->last_flush_time
= now
;
1861 /**********************************************************************
1862 * macdrv_glGetString
1864 * Hook into glGetString in order to return some legacy WGL extensions
1865 * that couldn't be advertised via the standard
1866 * WGL_ARB_extensions_string mechanism. Some programs, especially
1867 * older ones, expect to find certain older extensions, such as
1868 * WGL_EXT_extensions_string itself, in the standard GL extensions
1869 * string, and won't query any other WGL extensions unless they find
1870 * that particular extension there.
1872 static const GLubyte
*macdrv_glGetString(GLenum name
)
1874 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1875 return (const GLubyte
*)gl_info
.glExtensions
;
1877 return pglGetString(name
);
1881 /**********************************************************************
1882 * macdrv_glReadPixels
1884 * Hook into glReadPixels as part of the implementation of
1885 * wglMakeContextCurrentARB. If the context has a separate readable,
1886 * temporarily make that current, do glReadPixels, and then set it back
1887 * to the drawable. This is modeled after what Mesa GLX's Apple
1888 * implementation does.
1890 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1891 GLenum format
, GLenum type
, void *pixels
)
1893 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1895 if (context
->read_view
|| context
->read_pbuffer
)
1896 make_context_current(context
, TRUE
);
1898 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1900 if (context
->read_view
|| context
->read_pbuffer
)
1901 make_context_current(context
, FALSE
);
1905 /**********************************************************************
1908 * Hook into glViewport as an opportunity to update the OpenGL context
1909 * if necessary. This is modeled after what Mesa GLX's Apple
1910 * implementation does.
1912 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1914 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1916 macdrv_update_opengl_context(context
->context
);
1917 pglViewport(x
, y
, width
, height
);
1921 /***********************************************************************
1922 * macdrv_wglBindTexImageARB
1924 * WGL_ARB_render_texture: wglBindTexImageARB
1926 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1928 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1932 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1934 if (pbuffer
->no_texture
)
1936 SetLastError(ERROR_INVALID_OPERATION
);
1940 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1941 opengl_funcs
.gl
.p_glFlush();
1945 case WGL_FRONT_LEFT_ARB
:
1946 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1947 source
= GL_FRONT_LEFT
;
1951 case WGL_FRONT_RIGHT_ARB
:
1952 source
= GL_FRONT_RIGHT
;
1954 case WGL_BACK_LEFT_ARB
:
1955 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1956 source
= GL_BACK_LEFT
;
1960 case WGL_BACK_RIGHT_ARB
:
1961 source
= GL_BACK_RIGHT
;
1963 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1964 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1965 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1966 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1974 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1975 SetLastError(ERROR_INVALID_DATA
);
1979 WARN("unknown source buffer 0x%x\n", iBuffer
);
1980 SetLastError(ERROR_INVALID_DATA
);
1984 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1985 if (err
!= kCGLNoError
)
1987 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1988 SetLastError(ERROR_INVALID_OPERATION
);
1996 /***********************************************************************
1997 * macdrv_wglChoosePixelFormatARB
1999 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2001 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2002 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2003 int *piFormats
, UINT
*nNumFormats
)
2005 pixel_format pf
, valid
;
2007 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2008 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2013 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2014 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2016 FIXME("unused pfAttribFList\n");
2018 memset(&pf
, 0, sizeof(pf
));
2019 memset(&valid
, 0, sizeof(valid
));
2020 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2021 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2025 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2028 int value
= iptr
[1];
2030 TRACE("%s\n", debugstr_attrib(attr
, value
));
2034 case WGL_DRAW_TO_WINDOW_ARB
:
2035 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2036 pf
.window
= (value
!= 0);
2040 case WGL_DRAW_TO_BITMAP_ARB
:
2043 case WGL_ACCELERATION_ARB
:
2044 if (value
== WGL_FULL_ACCELERATION_ARB
)
2046 else if (value
== WGL_NO_ACCELERATION_ARB
)
2050 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2051 pf
.accelerated
= value
;
2052 valid
.accelerated
= 1;
2055 case WGL_NEED_PALETTE_ARB
:
2056 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2057 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2058 if (value
) goto cant_match
;
2061 case WGL_SWAP_METHOD_ARB
:
2062 if (value
== WGL_SWAP_COPY_ARB
)
2064 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2068 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2069 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2070 pf
.backing_store
= value
;
2071 valid
.backing_store
= 1;
2074 case WGL_NUMBER_OVERLAYS_ARB
:
2075 case WGL_NUMBER_UNDERLAYS_ARB
:
2076 if (value
) goto cant_match
;
2079 case WGL_SHARE_DEPTH_ARB
:
2080 case WGL_SHARE_STENCIL_ARB
:
2081 case WGL_SHARE_ACCUM_ARB
:
2085 case WGL_SUPPORT_GDI_ARB
:
2086 if (value
) goto cant_match
;
2089 case WGL_SUPPORT_OPENGL_ARB
:
2090 if (!value
) goto cant_match
;
2093 case WGL_DOUBLE_BUFFER_ARB
:
2094 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2095 pf
.double_buffer
= (value
!= 0);
2096 valid
.double_buffer
= 1;
2097 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2100 case WGL_STEREO_ARB
:
2101 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2102 pf
.stereo
= (value
!= 0);
2106 case WGL_PIXEL_TYPE_ARB
:
2107 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2109 else if (value
== WGL_TYPE_RGBA_ARB
)
2113 /* Mac contexts don't support rendering to unsigned floating
2114 point formats, even if GL_EXT_packed_float is supported.
2115 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2118 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2119 if (srgb
&& value
) goto cant_match
;
2120 float_color
= value
;
2123 case WGL_COLOR_BITS_ARB
:
2124 if (color_bits
< value
) color_bits
= value
;
2127 case WGL_RED_BITS_ARB
:
2128 if (srgb
&& value
> 8) goto cant_match
;
2129 if (red_bits
< value
) red_bits
= value
;
2132 case WGL_GREEN_BITS_ARB
:
2133 if (srgb
&& value
> 8) goto cant_match
;
2134 if (green_bits
< value
) green_bits
= value
;
2137 case WGL_BLUE_BITS_ARB
:
2138 if (srgb
&& value
> 8) goto cant_match
;
2139 if (blue_bits
< value
) blue_bits
= value
;
2142 case WGL_ALPHA_BITS_ARB
:
2143 if (alpha_bits
< value
) alpha_bits
= value
;
2146 case WGL_ACCUM_BITS_ARB
:
2147 if (accum_bits
< value
) accum_bits
= value
;
2150 case WGL_ACCUM_RED_BITS_ARB
:
2151 if (accum_red_bits
< value
) accum_red_bits
= value
;
2154 case WGL_ACCUM_GREEN_BITS_ARB
:
2155 if (accum_green_bits
< value
) accum_green_bits
= value
;
2158 case WGL_ACCUM_BLUE_BITS_ARB
:
2159 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2162 case WGL_ACCUM_ALPHA_BITS_ARB
:
2163 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2166 case WGL_DEPTH_BITS_ARB
:
2167 if (value
> 255) goto cant_match
;
2168 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2171 case WGL_STENCIL_BITS_ARB
:
2172 if (value
> 255) goto cant_match
;
2173 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2176 case WGL_AUX_BUFFERS_ARB
:
2177 if (value
> 7) goto cant_match
;
2178 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2181 case WGL_SAMPLE_BUFFERS_ARB
:
2182 if (value
> 1) goto cant_match
;
2183 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2186 case WGL_SAMPLES_ARB
:
2187 if (value
> 31) goto cant_match
;
2188 if (pf
.samples
< value
) pf
.samples
= value
;
2191 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2192 /* sRGB is only supported for 8-bit integer color components */
2193 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2198 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2199 case WGL_RED_SHIFT_ARB
:
2200 case WGL_GREEN_SHIFT_ARB
:
2201 case WGL_BLUE_SHIFT_ARB
:
2202 case WGL_ALPHA_SHIFT_ARB
:
2203 case WGL_TRANSPARENT_ARB
:
2204 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2205 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2206 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2207 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2208 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2212 case WGL_DRAW_TO_PBUFFER_ARB
:
2213 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2214 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2215 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2216 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2217 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2218 pf
.pbuffer
= (value
!= 0);
2220 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2226 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2231 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",
2232 valid
.window
? (pf
.window
? "1" : "0") : "?",
2233 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2234 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2236 float_color
== -1 ? "?" : float_color
? "f" : "",
2250 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2251 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2252 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2256 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2258 const struct color_mode
*mode
;
2260 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2261 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2262 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2263 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2264 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2265 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2267 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2268 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2269 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2270 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2271 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2273 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2274 /* If the mode doesn't have alpha, check requested color bits against
2275 bits per pixel instead of the mode's color bits. On Windows, color
2276 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2277 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2278 expects that to match such a pixel format, we need to accommodate that. */
2279 if (mode
->alpha_bits
)
2281 if (mode
->color_bits
< color_bits
)
2286 if (mode
->bits_per_pixel
< color_bits
)
2289 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2290 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2292 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2293 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2296 if (pixel_formats
[i
].accum_mode
)
2298 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2299 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2300 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2301 mode
->alpha_bits
< accum_alpha_bits
)
2304 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2307 piFormats
[found
++] = i
+ 1;
2308 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2312 *nNumFormats
= found
;
2318 /***********************************************************************
2319 * macdrv_wglCreateContextAttribsARB
2321 * WGL_ARB_create_context: wglCreateContextAttribsARB
2323 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2324 struct wgl_context
*share_context
,
2325 const int *attrib_list
)
2328 struct wgl_context
*context
;
2330 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2333 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2335 format
= get_dc_pixel_format(hdc
);
2337 if (!is_valid_pixel_format(format
))
2339 ERR("Invalid pixel format %d, expect problems!\n", format
);
2340 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2344 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2347 int value
= iptr
[1];
2349 TRACE("%s\n", debugstr_attrib(attr
, value
));
2353 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2357 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2361 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2362 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2365 case WGL_CONTEXT_FLAGS_ARB
:
2367 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2368 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2369 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2372 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2373 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2374 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2376 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2377 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2384 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2385 SetLastError(ERROR_INVALID_PARAMETER
);
2390 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2391 (major
== 4 && (minor
== 0 || minor
== 1)))
2393 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2395 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2396 SetLastError(ERROR_INVALID_VERSION_ARB
);
2399 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2401 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2402 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2405 if (major
> gl_info
.max_major
||
2406 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2408 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2410 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2415 else if (major
>= 3)
2417 WARN("Profile version %u.%u not supported\n", major
, minor
);
2418 SetLastError(ERROR_INVALID_VERSION_ARB
);
2421 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2422 (major
== 2 && (minor
< 0 || minor
> 1)))
2424 WARN("Invalid GL version requested\n");
2425 SetLastError(ERROR_INVALID_VERSION_ARB
);
2428 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2430 WARN("Forward compatible context requested for GL version < 3\n");
2431 SetLastError(ERROR_INVALID_VERSION_ARB
);
2435 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
2437 context
->format
= format
;
2438 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2440 HeapFree(GetProcessHeap(), 0, context
);
2444 EnterCriticalSection(&context_section
);
2445 list_add_tail(&context_list
, &context
->entry
);
2446 LeaveCriticalSection(&context_section
);
2452 /**********************************************************************
2453 * macdrv_wglCreatePbufferARB
2455 * WGL_ARB_pbuffer: wglCreatePbufferARB
2457 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2458 const int *piAttribList
)
2460 struct wgl_pbuffer
* pbuffer
;
2462 GLenum internalFormat
= 0;
2465 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2466 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2468 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2470 WARN("invalid pixel format %d\n", iPixelFormat
);
2471 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2475 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2476 pbuffer
->format
= iPixelFormat
;
2478 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2480 int attr
= piAttribList
[0];
2481 int value
= piAttribList
[1];
2485 case WGL_PBUFFER_LARGEST_ARB
:
2486 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2489 case WGL_TEXTURE_FORMAT_ARB
:
2492 case WGL_TEXTURE_RGBA_ARB
:
2493 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2494 internalFormat
= GL_RGBA
;
2496 case WGL_TEXTURE_RGB_ARB
:
2497 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2498 internalFormat
= GL_RGB
;
2500 case WGL_NO_TEXTURE_ARB
:
2501 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2505 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2506 SetLastError(ERROR_INVALID_DATA
);
2511 case WGL_TEXTURE_TARGET_ARB
:
2515 case WGL_NO_TEXTURE_ARB
:
2516 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2519 case WGL_TEXTURE_CUBE_MAP_ARB
:
2520 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2521 target
= GL_TEXTURE_CUBE_MAP
;
2522 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2524 case WGL_TEXTURE_1D_ARB
:
2525 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2526 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2528 case WGL_TEXTURE_2D_ARB
:
2529 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2530 target
= GL_TEXTURE_2D
;
2532 case WGL_TEXTURE_RECTANGLE_NV
:
2533 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2534 target
= GL_TEXTURE_RECTANGLE
;
2537 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2538 SetLastError(ERROR_INVALID_DATA
);
2543 case WGL_MIPMAP_TEXTURE_ARB
:
2544 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2545 pbuffer
->max_level
= 0;
2548 int size
= min(iWidth
, iHeight
) / 2;
2551 pbuffer
->max_level
++;
2558 WARN("unknown attribute 0x%x\n", attr
);
2559 SetLastError(ERROR_INVALID_DATA
);
2564 if (!target
|| !internalFormat
)
2566 pbuffer
->no_texture
= TRUE
;
2567 /* no actual way to turn off ability to texture; use most permissive target */
2568 target
= GL_TEXTURE_RECTANGLE
;
2569 internalFormat
= GL_RGB
;
2572 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2573 if (err
!= kCGLNoError
)
2575 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2576 pbuffer
->pbuffer
= NULL
;
2577 if (err
== kCGLBadAlloc
)
2578 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2580 SetLastError(ERROR_INVALID_DATA
);
2584 if (!pbuffer
->pbuffer
)
2586 HeapFree(GetProcessHeap(), 0, pbuffer
);
2590 TRACE(" -> %p\n", pbuffer
);
2595 /**********************************************************************
2596 * macdrv_wglDestroyPbufferARB
2598 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2600 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2602 TRACE("pbuffer %p\n", pbuffer
);
2603 if (pbuffer
&& pbuffer
->pbuffer
)
2604 CGLReleasePBuffer(pbuffer
->pbuffer
);
2605 HeapFree(GetProcessHeap(), 0, pbuffer
);
2610 /**********************************************************************
2611 * macdrv_wglGetExtensionsStringARB
2613 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2615 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2617 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2618 this can be specific to the CGL renderer like we're supposed to do. */
2619 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2620 return gl_info
.wglExtensions
;
2624 /**********************************************************************
2625 * macdrv_wglGetExtensionsStringEXT
2627 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2629 static const char *macdrv_wglGetExtensionsStringEXT(void)
2631 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2632 return gl_info
.wglExtensions
;
2636 /**********************************************************************
2637 * macdrv_wglGetPbufferDCARB
2639 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2641 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2644 struct wgl_pbuffer
*prev
;
2646 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2649 EnterCriticalSection(&dc_pbuffers_section
);
2650 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2653 CGLReleasePBuffer(prev
->pbuffer
);
2654 HeapFree(GetProcessHeap(), 0, prev
);
2656 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2657 LeaveCriticalSection(&dc_pbuffers_section
);
2659 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2664 /**********************************************************************
2665 * macdrv_wglGetPixelFormatAttribivARB
2667 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2669 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2670 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2672 const pixel_format
*pf
;
2675 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2676 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2678 if (!nAttributes
) return GL_TRUE
;
2680 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2682 piValues
[0] = nb_formats
;
2683 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2687 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2690 WARN("invalid pixel format %d\n", iPixelFormat
);
2691 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2695 for (i
= 0; i
< nAttributes
; ++i
)
2697 switch (piAttributes
[i
])
2699 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2700 piValues
[i
] = nb_formats
;
2703 case WGL_DRAW_TO_WINDOW_ARB
:
2704 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2707 case WGL_DRAW_TO_BITMAP_ARB
:
2708 piValues
[i
] = GL_FALSE
;
2711 case WGL_ACCELERATION_ARB
:
2712 if (iLayerPlane
) goto invalid_layer
;
2713 if (pf
->accelerated
)
2714 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2716 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2719 case WGL_NEED_PALETTE_ARB
:
2720 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2721 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2722 piValues
[i
] = GL_FALSE
;
2725 case WGL_SWAP_METHOD_ARB
:
2726 if (pf
->double_buffer
&& pf
->backing_store
)
2727 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2729 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2732 case WGL_NUMBER_OVERLAYS_ARB
:
2733 case WGL_NUMBER_UNDERLAYS_ARB
:
2737 case WGL_TRANSPARENT_ARB
:
2738 if (iLayerPlane
) goto invalid_layer
;
2739 piValues
[i
] = GL_FALSE
;
2742 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2743 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2744 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2745 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2746 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2747 if (iLayerPlane
) goto invalid_layer
;
2751 case WGL_SHARE_DEPTH_ARB
:
2752 case WGL_SHARE_STENCIL_ARB
:
2753 case WGL_SHARE_ACCUM_ARB
:
2754 if (iLayerPlane
) goto invalid_layer
;
2755 piValues
[i
] = GL_TRUE
;
2758 case WGL_SUPPORT_GDI_ARB
:
2759 if (iLayerPlane
) goto invalid_layer
;
2760 piValues
[i
] = GL_FALSE
;
2763 case WGL_SUPPORT_OPENGL_ARB
:
2764 if (iLayerPlane
) goto invalid_layer
;
2765 piValues
[i
] = GL_TRUE
;
2768 case WGL_DOUBLE_BUFFER_ARB
:
2769 if (iLayerPlane
) goto invalid_layer
;
2770 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2773 case WGL_STEREO_ARB
:
2774 if (iLayerPlane
) goto invalid_layer
;
2775 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2778 case WGL_PIXEL_TYPE_ARB
:
2779 if (iLayerPlane
) goto invalid_layer
;
2780 if (color_modes
[pf
->color_mode
].is_float
)
2781 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2783 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2784 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2785 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2786 However, Mac contexts don't support rendering to unsigned floating-point
2787 formats, even when GL_EXT_packed_float is supported. */
2790 case WGL_COLOR_BITS_ARB
:
2791 if (iLayerPlane
) goto invalid_layer
;
2792 /* If the mode doesn't have alpha, return bits per pixel instead
2793 of color bits. On Windows, color bits sometimes exceeds r+g+b
2794 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2795 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2796 pixel format, we need to accommodate that. */
2797 if (color_modes
[pf
->color_mode
].alpha_bits
)
2798 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2800 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2803 case WGL_RED_BITS_ARB
:
2804 if (iLayerPlane
) goto invalid_layer
;
2805 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2808 case WGL_RED_SHIFT_ARB
:
2809 if (iLayerPlane
) goto invalid_layer
;
2810 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2813 case WGL_GREEN_BITS_ARB
:
2814 if (iLayerPlane
) goto invalid_layer
;
2815 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2818 case WGL_GREEN_SHIFT_ARB
:
2819 if (iLayerPlane
) goto invalid_layer
;
2820 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2823 case WGL_BLUE_BITS_ARB
:
2824 if (iLayerPlane
) goto invalid_layer
;
2825 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2828 case WGL_BLUE_SHIFT_ARB
:
2829 if (iLayerPlane
) goto invalid_layer
;
2830 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2833 case WGL_ALPHA_BITS_ARB
:
2834 if (iLayerPlane
) goto invalid_layer
;
2835 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2838 case WGL_ALPHA_SHIFT_ARB
:
2839 if (iLayerPlane
) goto invalid_layer
;
2840 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2843 case WGL_ACCUM_BITS_ARB
:
2844 if (iLayerPlane
) goto invalid_layer
;
2846 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2851 case WGL_ACCUM_RED_BITS_ARB
:
2852 if (iLayerPlane
) goto invalid_layer
;
2854 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2859 case WGL_ACCUM_GREEN_BITS_ARB
:
2860 if (iLayerPlane
) goto invalid_layer
;
2862 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2867 case WGL_ACCUM_BLUE_BITS_ARB
:
2868 if (iLayerPlane
) goto invalid_layer
;
2870 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2875 case WGL_ACCUM_ALPHA_BITS_ARB
:
2876 if (iLayerPlane
) goto invalid_layer
;
2878 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2883 case WGL_DEPTH_BITS_ARB
:
2884 if (iLayerPlane
) goto invalid_layer
;
2885 piValues
[i
] = pf
->depth_bits
;
2888 case WGL_STENCIL_BITS_ARB
:
2889 if (iLayerPlane
) goto invalid_layer
;
2890 piValues
[i
] = pf
->stencil_bits
;
2893 case WGL_AUX_BUFFERS_ARB
:
2894 if (iLayerPlane
) goto invalid_layer
;
2895 piValues
[i
] = pf
->aux_buffers
;
2898 case WGL_SAMPLE_BUFFERS_ARB
:
2899 if (iLayerPlane
) goto invalid_layer
;
2900 piValues
[i
] = pf
->sample_buffers
;
2903 case WGL_SAMPLES_ARB
:
2904 if (iLayerPlane
) goto invalid_layer
;
2905 piValues
[i
] = pf
->samples
;
2908 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2909 if (iLayerPlane
) goto invalid_layer
;
2910 /* sRGB is only supported for 8-bit integer color components */
2911 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2912 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2913 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2914 !color_modes
[pf
->color_mode
].is_float
)
2915 piValues
[i
] = GL_TRUE
;
2917 piValues
[i
] = GL_FALSE
;
2920 case WGL_DRAW_TO_PBUFFER_ARB
:
2921 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2922 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2923 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2926 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2927 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2928 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2931 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2932 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2935 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2936 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2939 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2940 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2944 WARN("invalid attribute %x\n", piAttributes
[i
]);
2948 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2954 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2959 /**********************************************************************
2960 * macdrv_wglGetPixelFormatAttribfvARB
2962 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2964 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2965 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2970 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2971 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2973 /* Allocate a temporary array to store integer values */
2974 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2977 ERR("couldn't allocate %d array\n", nAttributes
);
2981 /* Piggy-back on wglGetPixelFormatAttribivARB */
2982 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2987 /* Convert integer values to float. Should also check for attributes
2988 that can give decimal values here */
2989 for (i
= 0; i
< nAttributes
; i
++)
2990 pfValues
[i
] = attr
[i
];
2993 HeapFree(GetProcessHeap(), 0, attr
);
2998 /**********************************************************************
2999 * macdrv_wglGetSwapIntervalEXT
3001 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3003 static int macdrv_wglGetSwapIntervalEXT(void)
3005 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3006 struct macdrv_win_data
*data
;
3012 if ((data
= get_win_data(context
->draw_hwnd
)))
3014 value
= data
->swap_interval
;
3015 release_win_data(data
);
3017 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3018 set_swap_interval(context
, value
);
3022 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3023 if (err
!= kCGLNoError
)
3025 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3026 err
, CGLErrorString(err
));
3035 /***********************************************************************
3036 * macdrv_wglMakeContextCurrentARB
3038 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3040 * This is not supported directly by OpenGL on the Mac. We emulate it
3041 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3042 * temporarily swap the drawable. This follows the technique used in
3043 * the implementation of Mesa GLX for Apple.
3045 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3047 struct macdrv_win_data
*data
;
3050 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3051 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3055 macdrv_make_context_current(NULL
, NULL
);
3056 NtCurrentTeb()->glContext
= NULL
;
3060 if ((hwnd
= WindowFromDC(draw_hdc
)))
3062 if (!(data
= get_win_data(hwnd
)))
3064 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3068 if (!data
->pixel_format
)
3070 WARN("no pixel format set\n");
3071 release_win_data(data
);
3072 SetLastError(ERROR_INVALID_HANDLE
);
3075 if (context
->format
!= data
->pixel_format
)
3077 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3078 release_win_data(data
);
3079 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3083 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
3084 set_swap_interval(context
, data
->swap_interval
);
3086 context
->draw_hwnd
= hwnd
;
3087 context
->draw_view
= data
->gl_view
;
3088 context
->draw_pbuffer
= NULL
;
3089 release_win_data(data
);
3093 struct wgl_pbuffer
*pbuffer
;
3095 EnterCriticalSection(&dc_pbuffers_section
);
3096 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3099 if (context
->format
!= pbuffer
->format
)
3101 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3102 LeaveCriticalSection(&dc_pbuffers_section
);
3103 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3108 (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
))
3109 set_swap_interval(context
, 0);
3113 WARN("no window or pbuffer for DC\n");
3114 LeaveCriticalSection(&dc_pbuffers_section
);
3115 SetLastError(ERROR_INVALID_HANDLE
);
3119 context
->draw_hwnd
= NULL
;
3120 context
->draw_view
= NULL
;
3121 context
->draw_pbuffer
= pbuffer
;
3122 LeaveCriticalSection(&dc_pbuffers_section
);
3125 context
->read_view
= NULL
;
3126 context
->read_pbuffer
= NULL
;
3127 if (read_hdc
&& read_hdc
!= draw_hdc
)
3129 if ((hwnd
= WindowFromDC(read_hdc
)))
3131 if ((data
= get_win_data(hwnd
)))
3133 if (data
->gl_view
!= context
->draw_view
)
3134 context
->read_view
= data
->gl_view
;
3135 release_win_data(data
);
3140 EnterCriticalSection(&dc_pbuffers_section
);
3141 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3142 LeaveCriticalSection(&dc_pbuffers_section
);
3146 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3147 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
3149 make_context_current(context
, FALSE
);
3150 context
->has_been_current
= TRUE
;
3151 NtCurrentTeb()->glContext
= context
;
3157 /**********************************************************************
3158 * macdrv_wglQueryPbufferARB
3160 * WGL_ARB_pbuffer: wglQueryPbufferARB
3162 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3168 GLenum internalFormat
;
3171 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3173 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3174 if (err
!= kCGLNoError
)
3176 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3177 SetLastError(ERROR_INVALID_HANDLE
);
3183 case WGL_PBUFFER_WIDTH_ARB
:
3186 case WGL_PBUFFER_HEIGHT_ARB
:
3189 case WGL_PBUFFER_LOST_ARB
:
3190 /* Mac PBuffers can't be lost */
3191 *piValue
= GL_FALSE
;
3193 case WGL_TEXTURE_FORMAT_ARB
:
3194 if (pbuffer
->no_texture
)
3195 *piValue
= WGL_NO_TEXTURE_ARB
;
3196 else switch (internalFormat
)
3199 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3203 *piValue
= WGL_TEXTURE_RGB_ARB
;
3207 case WGL_TEXTURE_TARGET_ARB
:
3208 if (pbuffer
->no_texture
)
3209 *piValue
= WGL_NO_TEXTURE_ARB
;
3210 else switch (target
)
3212 case GL_TEXTURE_CUBE_MAP
:
3213 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3216 *piValue
= WGL_TEXTURE_2D_ARB
;
3218 case GL_TEXTURE_RECTANGLE
:
3220 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3224 case WGL_MIPMAP_TEXTURE_ARB
:
3225 *piValue
= (pbuffer
->max_level
> 0);
3227 case WGL_MIPMAP_LEVEL_ARB
:
3228 *piValue
= pbuffer
->level
;
3230 case WGL_CUBE_MAP_FACE_ARB
:
3231 switch (pbuffer
->face
)
3233 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3235 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3238 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3240 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3241 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3243 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3244 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3246 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3247 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3250 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3255 WARN("invalid attribute 0x%x\n", iAttribute
);
3256 SetLastError(ERROR_INVALID_DATA
);
3264 /**********************************************************************
3265 * macdrv_wglReleasePbufferDCARB
3267 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3269 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3271 struct wgl_pbuffer
*prev
;
3273 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3275 EnterCriticalSection(&dc_pbuffers_section
);
3277 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3280 if (prev
!= pbuffer
)
3281 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3282 CGLReleasePBuffer(prev
->pbuffer
);
3283 HeapFree(GetProcessHeap(), 0, prev
);
3284 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3288 LeaveCriticalSection(&dc_pbuffers_section
);
3290 return hdc
&& DeleteDC(hdc
);
3294 /**********************************************************************
3295 * macdrv_wglReleaseTexImageARB
3297 * WGL_ARB_render_texture: wglReleaseTexImageARB
3299 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3301 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3304 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3306 if (pbuffer
->no_texture
)
3308 SetLastError(ERROR_INVALID_OPERATION
);
3312 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3313 if (err
!= kCGLNoError
)
3315 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3316 SetLastError(ERROR_INVALID_OPERATION
);
3324 /**********************************************************************
3325 * macdrv_wglSetPbufferAttribARB
3327 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3329 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
3331 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3333 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
3335 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3337 int attr
= piAttribList
[0];
3338 int value
= piAttribList
[1];
3341 case WGL_MIPMAP_LEVEL_ARB
:
3342 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
3343 pbuffer
->level
= value
;
3345 case WGL_CUBE_MAP_FACE_ARB
:
3348 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3349 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3350 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
3352 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3353 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3354 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
3356 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3357 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3358 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
3360 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3361 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3362 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
3364 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3365 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3366 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
3368 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3369 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3370 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
3373 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
3374 SetLastError(ERROR_INVALID_DATA
);
3379 WARN("invalide attribute 0x%x\n", attr
);
3380 SetLastError(ERROR_INVALID_DATA
);
3385 if (context
&& context
->draw_pbuffer
== pbuffer
)
3386 make_context_current(context
, FALSE
);
3392 /**********************************************************************
3393 * macdrv_wglSetPixelFormatWINE
3395 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3397 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
3399 return set_pixel_format(hdc
, fmt
, TRUE
);
3403 /**********************************************************************
3404 * macdrv_wglSwapIntervalEXT
3406 * WGL_EXT_swap_control: wglSwapIntervalEXT
3408 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
3410 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3411 BOOL changed
= FALSE
;
3413 TRACE("interval %d\n", interval
);
3417 SetLastError(ERROR_INVALID_DATA
);
3423 if (context
->draw_hwnd
)
3425 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
3428 changed
= data
->swap_interval
!= interval
;
3430 data
->swap_interval
= interval
;
3431 release_win_data(data
);
3437 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
3438 if (!set_swap_interval(context
, interval
))
3440 SetLastError(ERROR_GEN_FAILURE
);
3446 struct wgl_context
*ctx
;
3448 EnterCriticalSection(&context_section
);
3449 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
3451 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
3452 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3454 LeaveCriticalSection(&context_section
);
3461 static void register_extension(const char *ext
)
3463 if (gl_info
.wglExtensions
[0])
3464 strcat(gl_info
.wglExtensions
, " ");
3465 strcat(gl_info
.wglExtensions
, ext
);
3467 TRACE("'%s'\n", ext
);
3470 static void load_extensions(void)
3475 register_extension("WGL_ARB_extensions_string");
3476 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
3478 register_extension("WGL_ARB_make_current_read");
3479 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
3480 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
3482 register_extension("WGL_ARB_pixel_format");
3483 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
3484 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
3485 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
3487 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
3489 register_extension("WGL_ARB_pixel_format_float");
3490 register_extension("WGL_ATI_pixel_format_float");
3493 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
3494 register_extension("WGL_ARB_multisample");
3496 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3497 register_extension("WGL_ARB_framebuffer_sRGB");
3499 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
3501 register_extension("WGL_ARB_pbuffer");
3502 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3503 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3504 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3505 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3506 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3508 register_extension("WGL_ARB_render_texture");
3509 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3510 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3511 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3513 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3514 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3515 register_extension("WGL_NV_render_texture_rectangle");
3518 register_extension("WGL_ARB_create_context");
3519 register_extension("WGL_ARB_create_context_profile");
3520 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
3525 register_extension("WGL_EXT_extensions_string");
3526 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3530 register_extension("WGL_EXT_swap_control");
3531 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3532 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3535 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3536 check for either, so register them separately. */
3537 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3538 register_extension("WGL_EXT_framebuffer_sRGB");
3540 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3541 register_extension("WGL_EXT_pixel_format_packed_float");
3544 * WINE-specific WGL Extensions
3547 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3548 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3550 register_extension("WGL_WINE_pixel_format_passthrough");
3551 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3555 static BOOL
init_opengl(void)
3557 static BOOL init_done
= FALSE
;
3561 if (init_done
) return (opengl_handle
!= NULL
);
3566 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3569 WARN("CFDictionaryCreateMutable failed\n");
3573 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3576 ERR("Failed to load OpenGL: %s\n", buffer
);
3577 ERR("OpenGL support is disabled.\n");
3581 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3583 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3585 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3590 /* redirect some standard OpenGL functions */
3591 #define REDIRECT(func) \
3592 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3593 REDIRECT(glCopyPixels
);
3594 REDIRECT(glGetString
);
3595 REDIRECT(glReadPixels
);
3596 REDIRECT(glViewport
);
3597 if (skip_single_buffer_flushes
|| allow_vsync
)
3603 /* redirect some OpenGL extension functions */
3604 #define REDIRECT(func) \
3605 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3606 REDIRECT(glCopyColorTable
);
3609 if (!init_gl_info())
3612 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3613 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3616 if (!init_pixel_formats())
3622 wine_dlclose(opengl_handle
, NULL
, 0);
3623 opengl_handle
= NULL
;
3628 /***********************************************************************
3631 * Synchronize the Mac GL view position with the Windows child window
3634 void sync_gl_view(struct macdrv_win_data
*data
)
3638 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3640 if (!data
->gl_view
) return;
3642 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3644 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3645 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3646 data
->gl_rect
= rect
;
3651 /**********************************************************************
3652 * macdrv_wglDescribePixelFormat
3654 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3656 const pixel_format
*pf
;
3657 const struct color_mode
*mode
;
3659 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3661 if (!descr
) return nb_displayable_formats
;
3662 if (size
< sizeof(*descr
)) return 0;
3664 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3667 memset(descr
, 0, sizeof(*descr
));
3668 descr
->nSize
= sizeof(*descr
);
3669 descr
->nVersion
= 1;
3671 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3672 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3673 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3674 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3675 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3676 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3678 descr
->iPixelType
= PFD_TYPE_RGBA
;
3680 mode
= &color_modes
[pf
->color_mode
];
3681 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3682 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3683 R8G8B8A0 pixel format). If an app depends on that and expects that
3684 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3685 if (mode
->alpha_bits
)
3686 descr
->cColorBits
= mode
->color_bits
;
3688 descr
->cColorBits
= mode
->bits_per_pixel
;
3689 descr
->cRedBits
= mode
->red_bits
;
3690 descr
->cRedShift
= mode
->red_shift
;
3691 descr
->cGreenBits
= mode
->green_bits
;
3692 descr
->cGreenShift
= mode
->green_shift
;
3693 descr
->cBlueBits
= mode
->blue_bits
;
3694 descr
->cBlueShift
= mode
->blue_shift
;
3695 descr
->cAlphaBits
= mode
->alpha_bits
;
3696 descr
->cAlphaShift
= mode
->alpha_shift
;
3700 mode
= &color_modes
[pf
->accum_mode
- 1];
3701 descr
->cAccumBits
= mode
->color_bits
;
3702 descr
->cAccumRedBits
= mode
->red_bits
;
3703 descr
->cAccumGreenBits
= mode
->green_bits
;
3704 descr
->cAccumBlueBits
= mode
->blue_bits
;
3705 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3708 descr
->cDepthBits
= pf
->depth_bits
;
3709 descr
->cStencilBits
= pf
->stencil_bits
;
3710 descr
->cAuxBuffers
= pf
->aux_buffers
;
3711 descr
->iLayerType
= PFD_MAIN_PLANE
;
3713 TRACE("%s\n", debugstr_pf(pf
));
3714 return nb_displayable_formats
;
3717 /***********************************************************************
3718 * macdrv_wglCopyContext
3720 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3724 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3726 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3727 if (err
!= kCGLNoError
)
3728 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3729 return (err
== kCGLNoError
);
3732 /***********************************************************************
3733 * macdrv_wglCreateContext
3735 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3737 struct wgl_context
*context
;
3739 TRACE("hdc %p\n", hdc
);
3741 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
3746 /***********************************************************************
3747 * macdrv_wglDeleteContext
3749 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3751 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3753 EnterCriticalSection(&context_section
);
3754 list_remove(&context
->entry
);
3755 LeaveCriticalSection(&context_section
);
3757 macdrv_dispose_opengl_context(context
->context
);
3758 HeapFree(GetProcessHeap(), 0, context
);
3761 /***********************************************************************
3762 * macdrv_wglGetPixelFormat
3764 static int macdrv_wglGetPixelFormat(HDC hdc
)
3768 format
= get_dc_pixel_format(hdc
);
3770 if (!is_valid_pixel_format(format
)) /* not set yet */
3772 else if (!is_displayable_pixel_format(format
))
3774 /* Non-displayable formats can't be used with traditional WGL calls.
3775 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3779 TRACE(" hdc %p -> %d\n", hdc
, format
);
3783 /***********************************************************************
3784 * macdrv_wglGetProcAddress
3786 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3790 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3791 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3797 if (dladdr(ret
, &info
))
3798 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3800 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3804 WARN("failed to find proc %s\n", debugstr_a(proc
));
3808 /***********************************************************************
3809 * macdrv_wglMakeCurrent
3811 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3813 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3814 (context
? context
->cglcontext
: NULL
));
3816 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3819 /**********************************************************************
3820 * macdrv_wglSetPixelFormat
3822 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3824 return set_pixel_format(hdc
, fmt
, FALSE
);
3827 /***********************************************************************
3828 * macdrv_wglShareLists
3830 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3832 macdrv_opengl_context saved_context
;
3833 CGLContextObj saved_cglcontext
;
3835 TRACE("org %p dest %p\n", org
, dest
);
3837 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3838 * at context creation time but in case of WGL it is done using wglShareLists.
3840 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3841 * and when a program requests sharing we recreate the destination context if it hasn't been made
3842 * current or when it hasn't shared display lists before.
3845 if (dest
->has_been_current
)
3847 WARN("could not share display lists, the destination context has been current already\n");
3850 else if (dest
->sharing
)
3852 WARN("could not share display lists because dest has already shared lists before\n");
3856 /* Re-create the Mac context and share display lists */
3857 saved_context
= dest
->context
;
3858 saved_cglcontext
= dest
->cglcontext
;
3859 dest
->context
= NULL
;
3860 dest
->cglcontext
= NULL
;
3861 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
3863 dest
->context
= saved_context
;
3864 dest
->cglcontext
= saved_cglcontext
;
3868 /* Implicitly disposes of saved_cglcontext. */
3869 macdrv_dispose_opengl_context(saved_context
);
3871 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3872 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3874 org
->sharing
= TRUE
;
3875 dest
->sharing
= TRUE
;
3880 /**********************************************************************
3881 * macdrv_wglSwapBuffers
3883 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3885 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3889 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3890 (context
? context
->cglcontext
: NULL
));
3893 sync_swap_interval(context
);
3895 if ((hwnd
= WindowFromDC(hdc
)))
3897 struct macdrv_win_data
*data
;
3899 if (!(data
= get_win_data(hwnd
)))
3901 SetLastError(ERROR_INVALID_HANDLE
);
3905 if (context
&& context
->draw_view
== data
->gl_view
)
3908 release_win_data(data
);
3912 struct wgl_pbuffer
*pbuffer
;
3914 EnterCriticalSection(&dc_pbuffers_section
);
3915 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3916 LeaveCriticalSection(&dc_pbuffers_section
);
3920 SetLastError(ERROR_INVALID_HANDLE
);
3924 if (context
&& context
->draw_pbuffer
== pbuffer
)
3929 macdrv_flush_opengl_context(context
->context
);
3932 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3934 /* If there is a current context, then wglSwapBuffers should do an implicit
3935 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3936 in the other branch, but we have to do it explicitly here. */
3944 static struct opengl_funcs opengl_funcs
=
3947 macdrv_wglCopyContext
, /* p_wglCopyContext */
3948 macdrv_wglCreateContext
, /* p_wglCreateContext */
3949 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3950 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3951 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3952 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3953 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3954 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3955 macdrv_wglShareLists
, /* p_wglShareLists */
3956 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3960 /**********************************************************************
3961 * macdrv_wine_get_wgl_driver
3963 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3965 if (version
!= WINE_WGL_DRIVER_VERSION
)
3967 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3971 if (!init_opengl()) return (void *)-1;
3973 return &opengl_funcs
;