2 * Mac driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
5 * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
33 #include "wine/wgl_driver.h"
34 #include "wine/wglext.h"
38 #include <OpenGL/OpenGL.h>
39 #include <OpenGL/glu.h>
40 #include <OpenGL/CGLRenderers.h>
43 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
50 char wglExtensions
[4096];
52 GLint max_viewport_dims
[2];
54 unsigned int max_major
, max_minor
;
57 static struct gl_info gl_info
;
64 macdrv_opengl_context context
;
65 CGLContextObj cglcontext
;
67 macdrv_view draw_view
;
68 struct wgl_pbuffer
*draw_pbuffer
;
69 macdrv_view read_view
;
70 struct wgl_pbuffer
*read_pbuffer
;
71 BOOL has_been_current
;
73 LONG update_swap_interval
;
74 DWORD last_flush_time
;
78 static struct list context_list
= LIST_INIT(context_list
);
80 static CRITICAL_SECTION context_section
;
81 static CRITICAL_SECTION_DEBUG critsect_debug
=
83 0, 0, &context_section
,
84 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
85 0, 0, { (DWORD_PTR
)(__FILE__
": context_section") }
87 static CRITICAL_SECTION context_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
92 CGLPBufferObj pbuffer
;
100 static CFMutableDictionaryRef dc_pbuffers
;
102 static CRITICAL_SECTION dc_pbuffers_section
;
103 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
105 0, 0, &dc_pbuffers_section
,
106 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
107 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
109 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
112 static struct opengl_funcs opengl_funcs
;
114 #define USE_GL_FUNC(name) #name,
115 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
119 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
121 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
122 static void (*pglFinish
)(void);
123 static void (*pglFlush
)(void);
124 static void (*pglFlushRenderAPPLE
)(void);
125 static const GLubyte
*(*pglGetString
)(GLenum name
);
126 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
127 GLenum format
, GLenum type
, void *pixels
);
128 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
134 GLint color_bits
; /* including alpha_bits */
135 int red_bits
, red_shift
;
136 int green_bits
, green_shift
;
137 int blue_bits
, blue_shift
;
138 GLint alpha_bits
, alpha_shift
;
143 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
144 observations of the behavior of Windows systems, but also subjective judgments
145 about what color formats are more "normal" than others.
147 On at least some Windows systems, integer color formats are listed before
148 floating-point formats. Within the integer formats, higher color bits were
149 usually listed before lower color bits, while for floating-point formats it
150 was the reverse. However, that leads D3D to select 64-bit integer formats in
151 preference to 32-bit formats when the latter would be sufficient. It seems
152 that a 32-bit format is much more likely to be normally used in that case.
154 Also, there are certain odd color formats supported on the Mac which seem like
155 they would be less appropriate than more common ones. For instance, the color
156 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
157 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
160 For two color formats which differ only in whether or not they have alpha bits,
161 we use the same ordering. pixel_format_comparator() gives alpha bits a
162 different weight than color formats.
164 static const struct color_mode color_modes
[] = {
165 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
166 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
167 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
168 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
169 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
170 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
171 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
172 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
173 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
174 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
175 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
176 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
177 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
178 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
179 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
180 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
181 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
182 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
183 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
184 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
185 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
186 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
187 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
188 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
192 static const struct {
195 } depth_stencil_modes
[] = {
223 GLint max_aux_buffers
;
224 GLint max_sample_buffers
;
231 } renderer_properties
;
235 unsigned int window
:1;
236 unsigned int pbuffer
:1;
237 unsigned int accelerated
:1;
238 unsigned int color_mode
:5; /* index into color_modes table */
239 unsigned int aux_buffers
:3;
240 unsigned int depth_bits
:8;
241 unsigned int stencil_bits
:8;
242 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
243 unsigned int double_buffer
:1;
244 unsigned int stereo
:1;
245 unsigned int sample_buffers
:1;
246 unsigned int samples
:5;
247 unsigned int backing_store
:1;
255 } pixel_format_or_code
;
256 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
259 static pixel_format
*pixel_formats
;
260 static int nb_formats
, nb_displayable_formats
;
263 static void *opengl_handle
;
266 static const char* debugstr_attrib(int attrib
, int value
)
268 static const struct {
272 #define ATTRIB(a) { a, #a }
273 ATTRIB(WGL_ACCELERATION_ARB
),
274 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
275 ATTRIB(WGL_ACCUM_BITS_ARB
),
276 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
277 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
278 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
279 ATTRIB(WGL_ALPHA_BITS_ARB
),
280 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
281 ATTRIB(WGL_AUX_BUFFERS_ARB
),
282 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
283 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
284 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
285 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
286 ATTRIB(WGL_BLUE_BITS_ARB
),
287 ATTRIB(WGL_BLUE_SHIFT_ARB
),
288 ATTRIB(WGL_COLOR_BITS_ARB
),
289 ATTRIB(WGL_DEPTH_BITS_ARB
),
290 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
291 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
292 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
293 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
294 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
295 ATTRIB(WGL_GREEN_BITS_ARB
),
296 ATTRIB(WGL_GREEN_SHIFT_ARB
),
297 ATTRIB(WGL_NEED_PALETTE_ARB
),
298 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
299 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
300 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
301 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
302 ATTRIB(WGL_PIXEL_TYPE_ARB
),
303 ATTRIB(WGL_RED_BITS_ARB
),
304 ATTRIB(WGL_RED_SHIFT_ARB
),
305 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
306 ATTRIB(WGL_SAMPLES_ARB
),
307 ATTRIB(WGL_SHARE_ACCUM_ARB
),
308 ATTRIB(WGL_SHARE_DEPTH_ARB
),
309 ATTRIB(WGL_SHARE_STENCIL_ARB
),
310 ATTRIB(WGL_STENCIL_BITS_ARB
),
311 ATTRIB(WGL_STEREO_ARB
),
312 ATTRIB(WGL_SUPPORT_GDI_ARB
),
313 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
314 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
315 ATTRIB(WGL_SWAP_METHOD_ARB
),
316 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
317 ATTRIB(WGL_TRANSPARENT_ARB
),
318 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
319 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
320 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
321 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
325 const char *attrib_name
= NULL
;
326 const char *value_name
= NULL
;
328 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
330 if (attrib_names
[i
].attrib
== attrib
)
332 attrib_name
= attrib_names
[i
].name
;
338 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
342 case WGL_ACCELERATION_ARB
:
345 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
346 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
347 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
350 case WGL_PIXEL_TYPE_ARB
:
353 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
354 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
355 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
356 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
359 case WGL_SWAP_METHOD_ARB
:
362 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
363 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
364 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
370 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
372 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
376 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
377 CGLRendererProperty property
, GLint
*value
)
379 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
380 if (err
!= kCGLNoError
)
381 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
382 return (err
== kCGLNoError
);
386 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
390 memset(properties
, 0, sizeof(*properties
));
392 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
393 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
395 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
396 properties
->buffer_modes
= value
;
398 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
399 properties
->color_modes
= value
;
401 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
402 properties
->accum_modes
= value
;
404 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
405 properties
->depth_modes
= value
;
407 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
408 properties
->stencil_modes
= value
;
410 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
411 properties
->max_aux_buffers
= value
;
413 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
414 properties
->max_sample_buffers
= value
;
416 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
417 properties
->max_samples
= value
;
419 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
420 properties
->offscreen
= (value
!= 0);
422 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
423 properties
->accelerated
= (value
!= 0);
425 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
426 properties
->backing_store
= (value
!= 0);
428 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
429 properties
->window
= (value
!= 0);
431 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
432 properties
->online
= (value
!= 0);
436 static void dump_renderer(const renderer_properties
* renderer
)
440 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
441 TRACE("Buffer modes:\n");
442 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
443 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
444 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
445 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
447 TRACE("Color buffer modes:\n");
448 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
450 if (renderer
->color_modes
& color_modes
[i
].mode
)
452 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
453 if (color_modes
[i
].is_float
)
459 TRACE("Accumulation buffer sizes: { ");
460 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
462 if (renderer
->accum_modes
& color_modes
[i
].mode
)
463 TRACE("%d, ", color_modes
[i
].color_bits
);
467 TRACE("Depth buffer sizes: { ");
468 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
470 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
471 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
475 TRACE("Stencil buffer sizes: { ");
476 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
478 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
479 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
483 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
484 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
485 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
486 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
487 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
488 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
489 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
490 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
494 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
496 pixel_format_or_code pfc
;
499 pfc
.format
= *format
;
504 static inline pixel_format
pixel_format_for_code(UInt64 code
)
506 pixel_format_or_code pfc
;
513 static const char *debugstr_pf(const pixel_format
*pf
)
515 return wine_dbg_sprintf("w/p/a %u/%u/%u col %u%s/%u dp/stn/ac/ax/b/db/str %u/%u/%u/%u/%u/%u/%u samp %u/%u %017llx",
519 color_modes
[pf
->color_mode
].color_bits
,
520 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
521 color_modes
[pf
->color_mode
].alpha_bits
,
524 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
531 code_for_pixel_format(pf
));
535 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
540 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
542 if ((modes
& color_modes
[i
].mode
) &&
543 color_modes
[i
].color_bits
>= color_size
&&
544 color_modes
[i
].alpha_bits
>= alpha_size
&&
545 !color_modes
[i
].is_float
== !color_float
)
547 if (best
< 0) /* no existing best choice */
549 else if (color_modes
[i
].color_bits
== color_size
&&
550 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
552 /* prefer it over a best which isn't exact or which has a higher bpp */
553 if (color_modes
[best
].color_bits
!= color_size
||
554 color_modes
[best
].alpha_bits
!= alpha_size
||
555 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
558 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
559 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
560 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
567 /* Couldn't find a match. Return first one that renderer supports. */
568 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
570 if (modes
& color_modes
[i
].mode
)
579 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
584 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
586 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
588 /* Prefer the fewest color bits, then prefer more alpha bits, then
589 prefer more bits per pixel. */
592 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
594 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
596 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
598 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
599 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
607 /* Couldn't find a match. Return last one that renderer supports. */
608 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
610 if (modes
& color_modes
[i
].mode
)
619 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
620 CFMutableSetRef pixel_format_set
)
622 CGLPixelFormatAttribute attribs
[64] = {
623 kCGLPFAMinimumPolicy
,
624 kCGLPFAClosestPolicy
,
625 kCGLPFARendererID
, renderer
.renderer_id
,
626 kCGLPFASingleRenderer
,
628 int n
= 5, n_stack
[16], n_stack_idx
= -1;
629 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
630 new_pixel_formats
= 0;
631 pixel_format request
;
632 unsigned int double_buffer
;
633 unsigned int accelerated
= renderer
.accelerated
;
637 attribs
[n
++] = kCGLPFAAccelerated
;
638 attribs
[n
++] = kCGLPFANoRecovery
;
640 else if (!allow_software_rendering
)
642 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
646 n_stack
[++n_stack_idx
] = n
;
647 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
651 n
= n_stack
[n_stack_idx
];
653 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
654 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
658 attribs
[n
++] = kCGLPFADoubleBuffer
;
659 memset(&request
, 0, sizeof(request
));
660 request
.accelerated
= accelerated
;
661 request
.double_buffer
= double_buffer
;
663 /* Don't bother with in-between aux buffers values: either 0 or max. */
664 n_stack
[++n_stack_idx
] = n
;
665 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
667 unsigned int color_mode
;
669 n
= n_stack
[n_stack_idx
];
671 attribs
[n
++] = kCGLPFAAuxBuffers
;
673 request
.aux_buffers
= aux
;
675 n_stack
[++n_stack_idx
] = n
;
676 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
678 unsigned int depth_mode
;
680 n
= n_stack
[n_stack_idx
];
682 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
685 attribs
[n
++] = kCGLPFAColorSize
;
686 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
687 attribs
[n
++] = kCGLPFAAlphaSize
;
688 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
689 if (color_modes
[color_mode
].is_float
)
690 attribs
[n
++] = kCGLPFAColorFloat
;
691 request
.color_mode
= color_mode
;
693 n_stack
[++n_stack_idx
] = n
;
694 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
696 unsigned int stencil_mode
;
698 n
= n_stack
[n_stack_idx
];
700 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
703 attribs
[n
++] = kCGLPFADepthSize
;
704 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
705 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
707 n_stack
[++n_stack_idx
] = n
;
708 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
712 n
= n_stack
[n_stack_idx
];
714 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
716 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
719 attribs
[n
++] = kCGLPFAStencilSize
;
720 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
721 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
723 /* FIXME: Could trim search space a bit here depending on GPU.
724 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
725 n_stack
[++n_stack_idx
] = n
;
726 for (stereo
= 0; stereo
<= 1; stereo
++)
730 n
= n_stack
[n_stack_idx
];
732 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
733 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
737 attribs
[n
++] = kCGLPFAStereo
;
738 request
.stereo
= stereo
;
740 /* Starts at -1 for a 0 accum size */
741 n_stack
[++n_stack_idx
] = n
;
742 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
744 unsigned int target_pass
;
746 n
= n_stack
[n_stack_idx
];
750 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
753 attribs
[n
++] = kCGLPFAAccumSize
;
754 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
755 request
.accum_mode
= accum_mode
+ 1;
758 request
.accum_mode
= 0;
760 /* Targets to request are:
761 accelerated: window OR window + pbuffer
762 software: window + pbuffer */
763 n_stack
[++n_stack_idx
] = n
;
764 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
766 unsigned int samples
, max_samples
;
768 n
= n_stack
[n_stack_idx
];
770 attribs
[n
++] = kCGLPFAWindow
;
773 if (!accelerated
|| target_pass
> 0)
775 attribs
[n
++] = kCGLPFAPBuffer
;
781 /* FIXME: Could trim search space a bit here depending on GPU.
782 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
783 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
784 n_stack
[++n_stack_idx
] = n
;
785 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
786 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
788 unsigned int backing_store
, min_backing_store
, max_backing_store
;
790 n
= n_stack
[n_stack_idx
];
794 attribs
[n
++] = kCGLPFASampleBuffers
;
795 attribs
[n
++] = renderer
.max_sample_buffers
;
796 attribs
[n
++] = kCGLPFASamples
;
797 attribs
[n
++] = samples
;
798 request
.sample_buffers
= renderer
.max_sample_buffers
;
799 request
.samples
= samples
;
802 request
.sample_buffers
= request
.samples
= 0;
804 if (renderer
.backing_store
&& double_buffer
)
806 /* The software renderer seems to always preserve the backing store, whether
807 we ask for it or not. So don't bother not asking for it. */
808 min_backing_store
= accelerated
? 0 : 1;
809 max_backing_store
= 1;
812 min_backing_store
= max_backing_store
= 0;
813 n_stack
[++n_stack_idx
] = n
;
814 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
816 CGLPixelFormatObj pix
;
817 GLint virtualScreens
;
820 n
= n_stack
[n_stack_idx
];
823 attribs
[n
++] = kCGLPFABackingStore
;
824 request
.backing_store
= backing_store
;
828 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
829 if (err
== kCGLNoError
&& pix
)
832 GLint value
, color_size
, alpha_size
, color_float
;
834 CFNumberRef code_object
;
837 memset(&pf
, 0, sizeof(pf
));
839 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
840 pf
.accelerated
= value
;
841 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
842 pf
.aux_buffers
= value
;
843 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
844 pf
.depth_bits
= value
;
845 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
846 pf
.double_buffer
= value
;
847 if (pf
.double_buffer
&&
848 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
849 pf
.backing_store
= value
;
850 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
852 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
853 pf
.sample_buffers
= value
;
854 if (pf
.sample_buffers
&&
855 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
857 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
858 pf
.stencil_bits
= value
;
859 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
861 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
864 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
866 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
868 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
870 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
872 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
873 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
875 CGLReleasePixelFormat(pix
);
877 pf_code
= code_for_pixel_format(&pf
);
879 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
880 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
881 dupe_pixel_formats
++;
884 CFSetAddValue(pixel_format_set
, code_object
);
885 CFArrayAppendValue(pixel_format_array
, code_object
);
888 CFRelease(code_object
);
890 if (pf_code
== code_for_pixel_format(&request
))
891 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
894 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
895 dupe
? " (duplicate)" : "");
900 failed_pixel_formats
++;
901 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
904 tried_pixel_formats
++;
936 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
937 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
938 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
939 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
943 /* The docs for WGL_ARB_pixel_format say:
944 Indices are assigned to pixel formats in the following order:
945 1. Accelerated pixel formats that are displayable
946 2. Accelerated pixel formats that are displayable and which have
948 3. Generic pixel formats
949 4. Accelerated pixel formats that are non displayable
951 static int pixel_format_category(pixel_format pf
)
953 /* non-displayable */
957 /* non-accelerated a.k.a. software a.k.a. generic */
961 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
962 if (color_modes
[pf
.color_mode
].is_float
)
965 /* accelerated, displayable, no extended attributes */
970 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
972 CFNumberRef number1
= val1
;
973 CFNumberRef number2
= val2
;
975 pixel_format pf1
, pf2
;
976 int category1
, category2
;
978 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
979 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
980 pf1
= pixel_format_for_code(code1
);
981 pf2
= pixel_format_for_code(code2
);
982 category1
= pixel_format_category(pf1
);
983 category2
= pixel_format_category(pf2
);
985 if (category1
< category2
)
986 return kCFCompareLessThan
;
987 if (category1
> category2
)
988 return kCFCompareGreaterThan
;
990 /* Within a category, sort the "best" formats toward the front since that's
991 what wglChoosePixelFormatARB() has to do. The ordering implemented here
992 matches at least one Windows 7 machine's behavior.
994 /* Accelerated before unaccelerated. */
995 if (pf1
.accelerated
&& !pf2
.accelerated
)
996 return kCFCompareLessThan
;
997 if (!pf1
.accelerated
&& pf2
.accelerated
)
998 return kCFCompareGreaterThan
;
1000 /* Explicit color mode ordering. */
1001 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
1002 return kCFCompareLessThan
;
1003 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
1004 return kCFCompareGreaterThan
;
1006 /* Non-pbuffer-capable before pbuffer-capable. */
1007 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
1008 return kCFCompareLessThan
;
1009 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
1010 return kCFCompareGreaterThan
;
1012 /* Fewer samples before more samples. */
1013 if (pf1
.samples
< pf2
.samples
)
1014 return kCFCompareLessThan
;
1015 if (pf1
.samples
> pf2
.samples
)
1016 return kCFCompareGreaterThan
;
1018 /* Monoscopic before stereoscopic. (This is a guess.) */
1019 if (!pf1
.stereo
&& pf2
.stereo
)
1020 return kCFCompareLessThan
;
1021 if (pf1
.stereo
&& !pf2
.stereo
)
1022 return kCFCompareGreaterThan
;
1024 /* Single buffered before double buffered. */
1025 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1026 return kCFCompareLessThan
;
1027 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1028 return kCFCompareGreaterThan
;
1030 /* Possibly-optimized double buffering before backing-store-preserving
1031 double buffering. */
1032 if (!pf1
.backing_store
&& pf2
.backing_store
)
1033 return kCFCompareLessThan
;
1034 if (pf1
.backing_store
&& !pf2
.backing_store
)
1035 return kCFCompareGreaterThan
;
1037 /* Bigger depth buffer before smaller depth buffer. */
1038 if (pf1
.depth_bits
> pf2
.depth_bits
)
1039 return kCFCompareLessThan
;
1040 if (pf1
.depth_bits
< pf2
.depth_bits
)
1041 return kCFCompareGreaterThan
;
1043 /* Smaller stencil buffer before bigger stencil buffer. */
1044 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1045 return kCFCompareLessThan
;
1046 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1047 return kCFCompareGreaterThan
;
1049 /* Smaller alpha bits before larger alpha bits. */
1050 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1051 return kCFCompareLessThan
;
1052 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1053 return kCFCompareGreaterThan
;
1055 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1060 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1061 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1062 return kCFCompareLessThan
;
1063 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1064 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1065 return kCFCompareGreaterThan
;
1067 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1068 return kCFCompareLessThan
;
1069 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1070 return kCFCompareGreaterThan
;
1072 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1073 return kCFCompareLessThan
;
1074 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1075 return kCFCompareGreaterThan
;
1078 return kCFCompareGreaterThan
;
1080 else if (pf2
.accum_mode
)
1081 return kCFCompareLessThan
;
1083 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1084 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1085 return kCFCompareLessThan
;
1086 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1087 return kCFCompareGreaterThan
;
1089 /* If we get here, arbitrarily sort based on code. */
1091 return kCFCompareLessThan
;
1093 return kCFCompareGreaterThan
;
1094 return kCFCompareEqualTo
;
1098 static BOOL
init_pixel_formats(void)
1101 CGLRendererInfoObj renderer_info
;
1102 GLint rendererCount
;
1104 CFMutableSetRef pixel_format_set
;
1105 CFMutableArrayRef pixel_format_array
;
1111 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1114 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1118 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1119 if (!pixel_format_set
)
1121 WARN("CFSetCreateMutable failed\n");
1122 CGLDestroyRendererInfo(renderer_info
);
1126 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1127 if (!pixel_format_array
)
1129 WARN("CFArrayCreateMutable failed\n");
1130 CFRelease(pixel_format_set
);
1131 CGLDestroyRendererInfo(renderer_info
);
1135 for (i
= 0; i
< rendererCount
; i
++)
1137 renderer_properties renderer
;
1139 get_renderer_properties(renderer_info
, i
, &renderer
);
1142 TRACE("renderer_properties %d:\n", i
);
1143 dump_renderer(&renderer
);
1146 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1149 CFRelease(pixel_format_set
);
1150 CGLDestroyRendererInfo(renderer_info
);
1152 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1155 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1158 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1159 for (i
= 0; i
< range
.length
; i
++)
1161 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1164 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1165 pixel_formats
[i
] = pixel_format_for_code(code
);
1166 if (pixel_formats
[i
].window
)
1167 nb_displayable_formats
++;
1170 nb_formats
= range
.length
;
1171 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1175 WARN("failed to allocate pixel format list\n");
1178 WARN("got no pixel formats\n");
1180 CFRelease(pixel_format_array
);
1185 static inline BOOL
is_valid_pixel_format(int format
)
1187 return format
> 0 && format
<= nb_formats
;
1191 static inline BOOL
is_displayable_pixel_format(int format
)
1193 return format
> 0 && format
<= nb_displayable_formats
;
1197 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1199 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1200 * format in case of probing the number of pixel formats.
1202 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1204 TRACE("Returning format %d\n", format
);
1205 return &pixel_formats
[format
- 1];
1211 static BOOL
init_gl_info(void)
1213 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1214 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1216 CGDirectDisplayID display
= CGMainDisplayID();
1217 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1218 CGLPixelFormatAttribute attribs
[] = {
1219 kCGLPFADisplayMask
, displayMask
,
1222 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1223 CGLPixelFormatAttribute core_attribs
[] =
1225 kCGLPFADisplayMask
, displayMask
,
1227 kCGLPFAOpenGLProfile
, (CGLPixelFormatAttribute
)kCGLOGLPVersion_3_2_Core
,
1231 CGLPixelFormatObj pix
;
1232 GLint virtualScreens
;
1234 CGLContextObj context
;
1235 CGLContextObj old_context
= CGLGetCurrentContext();
1239 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1240 if (err
!= kCGLNoError
|| !pix
)
1242 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1246 err
= CGLCreateContext(pix
, NULL
, &context
);
1247 CGLReleasePixelFormat(pix
);
1248 if (err
!= kCGLNoError
|| !context
)
1250 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1254 err
= CGLSetCurrentContext(context
);
1255 if (err
!= kCGLNoError
)
1257 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1258 CGLReleaseContext(context
);
1262 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1263 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1264 strcpy(gl_info
.glVersion
, str
);
1265 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1266 length
= strlen(str
) + sizeof(legacy_extensions
);
1268 length
+= strlen(legacy_ext_swap_control
);
1269 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1270 strcpy(gl_info
.glExtensions
, str
);
1271 strcat(gl_info
.glExtensions
, legacy_extensions
);
1273 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1275 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1277 TRACE("GL version : %s\n", gl_info
.glVersion
);
1278 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1279 sscanf(gl_info
.glVersion
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1281 CGLSetCurrentContext(old_context
);
1282 CGLReleaseContext(context
);
1284 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1285 err
= CGLChoosePixelFormat(core_attribs
, &pix
, &virtualScreens
);
1286 if (err
!= kCGLNoError
|| !pix
)
1288 WARN("CGLChoosePixelFormat() for a core context failed with error %d %s\n",
1289 err
, CGLErrorString(err
));
1293 err
= CGLCreateContext(pix
, NULL
, &context
);
1294 CGLReleasePixelFormat(pix
);
1295 if (err
!= kCGLNoError
|| !context
)
1297 WARN("CGLCreateContext() for a core context failed with error %d %s\n",
1298 err
, CGLErrorString(err
));
1302 err
= CGLSetCurrentContext(context
);
1303 if (err
!= kCGLNoError
)
1305 WARN("CGLSetCurrentContext() for a core context failed with error %d %s\n",
1306 err
, CGLErrorString(err
));
1307 CGLReleaseContext(context
);
1311 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1312 TRACE("Core context GL version: %s\n", str
);
1313 sscanf(str
, "%u.%u", &gl_info
.max_major
, &gl_info
.max_minor
);
1314 CGLSetCurrentContext(old_context
);
1315 CGLReleaseContext(context
);
1322 static int get_dc_pixel_format(HDC hdc
)
1327 if ((hwnd
= WindowFromDC(hdc
)))
1329 struct macdrv_win_data
*data
;
1331 if (!(data
= get_win_data(hwnd
)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1337 format
= data
->pixel_format
;
1338 release_win_data(data
);
1342 struct wgl_pbuffer
*pbuffer
;
1344 EnterCriticalSection(&dc_pbuffers_section
);
1345 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
1347 format
= pbuffer
->format
;
1350 WARN("no window or pbuffer for DC %p\n", hdc
);
1353 LeaveCriticalSection(&dc_pbuffers_section
);
1360 /**********************************************************************
1363 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
, unsigned int major
)
1365 const pixel_format
*pf
;
1366 CGLPixelFormatAttribute attribs
[64];
1368 CGLPixelFormatObj pix
;
1369 GLint virtualScreens
;
1371 BOOL core
= major
>= 3;
1373 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
1376 WARN("OS X version >= 10.7 is required to be able to create core contexts\n");
1381 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
1384 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
1385 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1389 attribs
[n
++] = kCGLPFAMinimumPolicy
;
1390 attribs
[n
++] = kCGLPFAClosestPolicy
;
1392 if (pf
->accelerated
)
1394 attribs
[n
++] = kCGLPFAAccelerated
;
1395 attribs
[n
++] = kCGLPFANoRecovery
;
1399 attribs
[n
++] = kCGLPFARendererID
;
1400 attribs
[n
++] = kCGLRendererGenericFloatID
;
1403 if (pf
->double_buffer
)
1404 attribs
[n
++] = kCGLPFADoubleBuffer
;
1408 attribs
[n
++] = kCGLPFAAuxBuffers
;
1409 attribs
[n
++] = pf
->aux_buffers
;
1412 attribs
[n
++] = kCGLPFAColorSize
;
1413 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
1414 attribs
[n
++] = kCGLPFAAlphaSize
;
1415 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
1416 if (color_modes
[pf
->color_mode
].is_float
)
1417 attribs
[n
++] = kCGLPFAColorFloat
;
1419 attribs
[n
++] = kCGLPFADepthSize
;
1420 attribs
[n
++] = pf
->depth_bits
;
1422 attribs
[n
++] = kCGLPFAStencilSize
;
1423 attribs
[n
++] = pf
->stencil_bits
;
1426 attribs
[n
++] = kCGLPFAStereo
;
1428 if (pf
->accum_mode
&& !core
)
1430 attribs
[n
++] = kCGLPFAAccumSize
;
1431 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
1434 if (pf
->pbuffer
&& !core
)
1435 attribs
[n
++] = kCGLPFAPBuffer
;
1437 if (pf
->sample_buffers
&& pf
->samples
)
1439 attribs
[n
++] = kCGLPFASampleBuffers
;
1440 attribs
[n
++] = pf
->sample_buffers
;
1441 attribs
[n
++] = kCGLPFASamples
;
1442 attribs
[n
++] = pf
->samples
;
1445 if (pf
->backing_store
)
1446 attribs
[n
++] = kCGLPFABackingStore
;
1448 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
1451 attribs
[n
++] = kCGLPFAOpenGLProfile
;
1452 #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
1454 attribs
[n
++] = (int)kCGLOGLPVersion_GL3_Core
;
1456 attribs
[n
++] = (int)kCGLOGLPVersion_GL4_Core
;
1458 attribs
[n
++] = (int)kCGLOGLPVersion_3_2_Core
;
1465 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1466 if (err
!= kCGLNoError
|| !pix
)
1468 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1469 SetLastError(ERROR_INVALID_OPERATION
);
1473 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
1474 CGLReleasePixelFormat(pix
);
1475 if (err
!= kCGLNoError
|| !context
->cglcontext
)
1477 context
->cglcontext
= NULL
;
1478 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1479 SetLastError(ERROR_INVALID_OPERATION
);
1483 if (gl_surface_mode
== GL_SURFACE_IN_FRONT_TRANSPARENT
)
1486 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOpacity
, &opacity
);
1487 if (err
!= kCGLNoError
)
1488 WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err
, CGLErrorString(err
));
1490 else if (gl_surface_mode
== GL_SURFACE_BEHIND
)
1493 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSurfaceOrder
, &order
);
1494 if (err
!= kCGLNoError
)
1495 WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err
, CGLErrorString(err
));
1498 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
1499 CGLReleaseContext(context
->cglcontext
);
1500 if (!context
->context
)
1502 WARN("macdrv_create_opengl_context() failed\n");
1503 SetLastError(ERROR_INVALID_OPERATION
);
1506 context
->major
= major
;
1509 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
1511 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
1517 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1520 *rect
= data
->client_rect
;
1522 if (data
->cocoa_window
)
1525 *window
= data
->cocoa_window
;
1526 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1530 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1531 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1532 struct macdrv_win_data
*top_data
= get_win_data(top
);
1534 if (top_data
&& top_data
->cocoa_window
)
1537 *window
= top_data
->cocoa_window
;
1538 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1539 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1544 release_win_data(top_data
);
1551 /***********************************************************************
1554 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1556 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1560 macdrv_window cocoa_window
;
1562 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1564 ERR("no top-level parent with Cocoa window in this process\n");
1568 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1571 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1575 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1576 wine_dbgstr_rect(&data
->gl_rect
));
1579 data
->pixel_format
= format
;
1585 /**********************************************************************
1588 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1590 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1592 struct macdrv_win_data
*data
;
1593 const pixel_format
*pf
;
1594 HWND hwnd
= WindowFromDC(hdc
);
1597 TRACE("hdc %p format %d\n", hdc
, fmt
);
1599 if (!hwnd
|| hwnd
== GetDesktopWindow())
1601 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1605 if (!(data
= get_win_data(hwnd
)))
1607 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1611 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1613 ret
= (data
->pixel_format
== fmt
);
1617 /* Check if fmt is in our list of supported formats to see if it is supported. */
1618 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1621 ERR("Invalid pixel format: %d\n", fmt
);
1627 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1631 if (!set_win_format(data
, fmt
))
1633 WARN("Couldn't set format of the window, returning failure\n");
1637 TRACE("pixel format:\n");
1638 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1639 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1640 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1641 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1642 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1643 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1644 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1645 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1646 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1647 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1648 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1649 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1650 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1651 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1655 release_win_data(data
);
1656 if (ret
&& gl_surface_mode
== GL_SURFACE_BEHIND
) __wine_set_pixel_format(hwnd
, fmt
);
1661 /**********************************************************************
1662 * set_gl_view_parent
1664 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1666 struct macdrv_win_data
*data
;
1668 if (!(data
= get_win_data(hwnd
))) return;
1672 macdrv_window cocoa_window
;
1674 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1676 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1678 ERR("no top-level parent with Cocoa window in this process\n");
1679 macdrv_dispose_view(data
->gl_view
);
1680 data
->gl_view
= NULL
;
1681 release_win_data(data
);
1682 __wine_set_pixel_format( hwnd
, 0 );
1686 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1689 release_win_data(data
);
1693 /**********************************************************************
1694 * make_context_current
1696 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1699 struct wgl_pbuffer
*pbuffer
;
1703 view
= context
->read_view
;
1704 pbuffer
= context
->read_pbuffer
;
1708 view
= context
->draw_view
;
1709 pbuffer
= context
->draw_pbuffer
;
1712 if (view
|| !pbuffer
)
1713 macdrv_make_context_current(context
->context
, view
);
1716 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1718 CGLSetCurrentContext(context
->cglcontext
);
1723 /**********************************************************************
1726 static BOOL
set_swap_interval(struct wgl_context
*context
, long interval
)
1730 /* In theory, for single-buffered contexts, there's no such thing as a swap
1731 so the swap interval shouldn't matter. But OS X will synchronize flushes
1732 of single-buffered contexts if the interval is set to non-zero. */
1733 if (interval
&& !pixel_formats
[context
->format
- 1].double_buffer
)
1736 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&interval
);
1737 if (err
!= kCGLNoError
)
1738 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n", err
, CGLErrorString(err
));
1740 return err
== kCGLNoError
;
1744 /**********************************************************************
1745 * sync_swap_interval
1747 static void sync_swap_interval(struct wgl_context
*context
)
1749 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
1753 if (context
->draw_hwnd
)
1755 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
1758 interval
= data
->swap_interval
;
1759 release_win_data(data
);
1761 else /* window was destroyed? */
1767 set_swap_interval(context
, interval
);
1772 /**********************************************************************
1773 * macdrv_glCopyColorTable
1775 * Hook into glCopyColorTable as part of the implementation of
1776 * wglMakeContextCurrentARB. If the context has a separate readable,
1777 * temporarily make that current, do glCopyColorTable, and then set it
1778 * back to the drawable. This is modeled after what Mesa GLX's Apple
1779 * implementation does.
1781 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1784 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1786 if (context
->read_view
|| context
->read_pbuffer
)
1787 make_context_current(context
, TRUE
);
1789 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1791 if (context
->read_view
|| context
->read_pbuffer
)
1792 make_context_current(context
, FALSE
);
1796 /**********************************************************************
1797 * macdrv_glCopyPixels
1799 * Hook into glCopyPixels as part of the implementation of
1800 * wglMakeContextCurrentARB. If the context has a separate readable,
1801 * temporarily make that current, do glCopyPixels, and then set it back
1802 * to the drawable. This is modeled after what Mesa GLX's Apple
1803 * implementation does.
1805 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1807 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1809 if (context
->read_view
|| context
->read_pbuffer
)
1810 make_context_current(context
, TRUE
);
1812 pglCopyPixels(x
, y
, width
, height
, type
);
1814 if (context
->read_view
|| context
->read_pbuffer
)
1815 make_context_current(context
, FALSE
);
1819 /**********************************************************************
1822 static void macdrv_glFinish(void)
1824 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1826 sync_swap_interval(context
);
1831 /**********************************************************************
1834 static void macdrv_glFlush(void)
1836 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1838 sync_swap_interval(context
);
1840 if (skip_single_buffer_flushes
)
1842 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1843 DWORD now
= GetTickCount();
1845 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1846 context
->last_flush_time
, now
);
1847 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1849 TRACE("calling glFlushRenderAPPLE()\n");
1850 pglFlushRenderAPPLE();
1855 TRACE("calling glFlush()\n");
1856 context
->last_flush_time
= now
;
1864 /**********************************************************************
1865 * macdrv_glGetString
1867 * Hook into glGetString in order to return some legacy WGL extensions
1868 * that couldn't be advertised via the standard
1869 * WGL_ARB_extensions_string mechanism. Some programs, especially
1870 * older ones, expect to find certain older extensions, such as
1871 * WGL_EXT_extensions_string itself, in the standard GL extensions
1872 * string, and won't query any other WGL extensions unless they find
1873 * that particular extension there.
1875 static const GLubyte
*macdrv_glGetString(GLenum name
)
1877 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1878 return (const GLubyte
*)gl_info
.glExtensions
;
1880 return pglGetString(name
);
1884 /**********************************************************************
1885 * macdrv_glReadPixels
1887 * Hook into glReadPixels as part of the implementation of
1888 * wglMakeContextCurrentARB. If the context has a separate readable,
1889 * temporarily make that current, do glReadPixels, and then set it back
1890 * to the drawable. This is modeled after what Mesa GLX's Apple
1891 * implementation does.
1893 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1894 GLenum format
, GLenum type
, void *pixels
)
1896 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1898 if (context
->read_view
|| context
->read_pbuffer
)
1899 make_context_current(context
, TRUE
);
1901 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1903 if (context
->read_view
|| context
->read_pbuffer
)
1904 make_context_current(context
, FALSE
);
1908 /**********************************************************************
1911 * Hook into glViewport as an opportunity to update the OpenGL context
1912 * if necessary. This is modeled after what Mesa GLX's Apple
1913 * implementation does.
1915 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1917 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1919 macdrv_update_opengl_context(context
->context
);
1920 pglViewport(x
, y
, width
, height
);
1924 /***********************************************************************
1925 * macdrv_wglBindTexImageARB
1927 * WGL_ARB_render_texture: wglBindTexImageARB
1929 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1931 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1935 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1937 if (pbuffer
->no_texture
)
1939 SetLastError(ERROR_INVALID_OPERATION
);
1943 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1944 opengl_funcs
.gl
.p_glFlush();
1948 case WGL_FRONT_LEFT_ARB
:
1949 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1950 source
= GL_FRONT_LEFT
;
1954 case WGL_FRONT_RIGHT_ARB
:
1955 source
= GL_FRONT_RIGHT
;
1957 case WGL_BACK_LEFT_ARB
:
1958 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1959 source
= GL_BACK_LEFT
;
1963 case WGL_BACK_RIGHT_ARB
:
1964 source
= GL_BACK_RIGHT
;
1966 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1967 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1968 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1969 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1977 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1978 SetLastError(ERROR_INVALID_DATA
);
1982 WARN("unknown source buffer 0x%x\n", iBuffer
);
1983 SetLastError(ERROR_INVALID_DATA
);
1987 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1988 if (err
!= kCGLNoError
)
1990 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1991 SetLastError(ERROR_INVALID_OPERATION
);
1999 /***********************************************************************
2000 * macdrv_wglChoosePixelFormatARB
2002 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2004 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
2005 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
2006 int *piFormats
, UINT
*nNumFormats
)
2008 pixel_format pf
, valid
;
2010 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
2011 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
2016 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
2017 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
2019 FIXME("unused pfAttribFList\n");
2021 memset(&pf
, 0, sizeof(pf
));
2022 memset(&valid
, 0, sizeof(valid
));
2023 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
2024 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
2028 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
2031 int value
= iptr
[1];
2033 TRACE("%s\n", debugstr_attrib(attr
, value
));
2037 case WGL_DRAW_TO_WINDOW_ARB
:
2038 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
2039 pf
.window
= (value
!= 0);
2043 case WGL_DRAW_TO_BITMAP_ARB
:
2046 case WGL_ACCELERATION_ARB
:
2047 if (value
== WGL_FULL_ACCELERATION_ARB
)
2049 else if (value
== WGL_NO_ACCELERATION_ARB
)
2053 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
2054 pf
.accelerated
= value
;
2055 valid
.accelerated
= 1;
2058 case WGL_NEED_PALETTE_ARB
:
2059 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2060 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2061 if (value
) goto cant_match
;
2064 case WGL_SWAP_METHOD_ARB
:
2065 if (value
== WGL_SWAP_COPY_ARB
)
2067 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
2071 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
2072 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
2073 pf
.backing_store
= value
;
2074 valid
.backing_store
= 1;
2077 case WGL_NUMBER_OVERLAYS_ARB
:
2078 case WGL_NUMBER_UNDERLAYS_ARB
:
2079 if (value
) goto cant_match
;
2082 case WGL_SHARE_DEPTH_ARB
:
2083 case WGL_SHARE_STENCIL_ARB
:
2084 case WGL_SHARE_ACCUM_ARB
:
2088 case WGL_SUPPORT_GDI_ARB
:
2089 if (value
) goto cant_match
;
2092 case WGL_SUPPORT_OPENGL_ARB
:
2093 if (!value
) goto cant_match
;
2096 case WGL_DOUBLE_BUFFER_ARB
:
2097 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
2098 pf
.double_buffer
= (value
!= 0);
2099 valid
.double_buffer
= 1;
2100 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
2103 case WGL_STEREO_ARB
:
2104 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
2105 pf
.stereo
= (value
!= 0);
2109 case WGL_PIXEL_TYPE_ARB
:
2110 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
2112 else if (value
== WGL_TYPE_RGBA_ARB
)
2116 /* Mac contexts don't support rendering to unsigned floating
2117 point formats, even if GL_EXT_packed_float is supported.
2118 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
2121 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
2122 if (srgb
&& value
) goto cant_match
;
2123 float_color
= value
;
2126 case WGL_COLOR_BITS_ARB
:
2127 if (color_bits
< value
) color_bits
= value
;
2130 case WGL_RED_BITS_ARB
:
2131 if (srgb
&& value
> 8) goto cant_match
;
2132 if (red_bits
< value
) red_bits
= value
;
2135 case WGL_GREEN_BITS_ARB
:
2136 if (srgb
&& value
> 8) goto cant_match
;
2137 if (green_bits
< value
) green_bits
= value
;
2140 case WGL_BLUE_BITS_ARB
:
2141 if (srgb
&& value
> 8) goto cant_match
;
2142 if (blue_bits
< value
) blue_bits
= value
;
2145 case WGL_ALPHA_BITS_ARB
:
2146 if (alpha_bits
< value
) alpha_bits
= value
;
2149 case WGL_ACCUM_BITS_ARB
:
2150 if (accum_bits
< value
) accum_bits
= value
;
2153 case WGL_ACCUM_RED_BITS_ARB
:
2154 if (accum_red_bits
< value
) accum_red_bits
= value
;
2157 case WGL_ACCUM_GREEN_BITS_ARB
:
2158 if (accum_green_bits
< value
) accum_green_bits
= value
;
2161 case WGL_ACCUM_BLUE_BITS_ARB
:
2162 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
2165 case WGL_ACCUM_ALPHA_BITS_ARB
:
2166 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
2169 case WGL_DEPTH_BITS_ARB
:
2170 if (value
> 255) goto cant_match
;
2171 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
2174 case WGL_STENCIL_BITS_ARB
:
2175 if (value
> 255) goto cant_match
;
2176 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
2179 case WGL_AUX_BUFFERS_ARB
:
2180 if (value
> 7) goto cant_match
;
2181 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
2184 case WGL_SAMPLE_BUFFERS_ARB
:
2185 if (value
> 1) goto cant_match
;
2186 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
2189 case WGL_SAMPLES_ARB
:
2190 if (value
> 31) goto cant_match
;
2191 if (pf
.samples
< value
) pf
.samples
= value
;
2194 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2195 /* sRGB is only supported for 8-bit integer color components */
2196 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
2201 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2202 case WGL_RED_SHIFT_ARB
:
2203 case WGL_GREEN_SHIFT_ARB
:
2204 case WGL_BLUE_SHIFT_ARB
:
2205 case WGL_ALPHA_SHIFT_ARB
:
2206 case WGL_TRANSPARENT_ARB
:
2207 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2208 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2209 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2210 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2211 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2215 case WGL_DRAW_TO_PBUFFER_ARB
:
2216 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2217 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2218 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2219 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2220 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
2221 pf
.pbuffer
= (value
!= 0);
2223 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
2229 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
2234 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",
2235 valid
.window
? (pf
.window
? "1" : "0") : "?",
2236 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
2237 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
2239 float_color
== -1 ? "?" : float_color
? "f" : "",
2253 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
2254 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
2255 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
2259 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
2261 const struct color_mode
*mode
;
2263 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
2264 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
2265 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
2266 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
2267 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
2268 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
2270 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
2271 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
2272 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
2273 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
2274 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
2276 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
2277 /* If the mode doesn't have alpha, check requested color bits against
2278 bits per pixel instead of the mode's color bits. On Windows, color
2279 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
2280 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
2281 expects that to match such a pixel format, we need to accommodate that. */
2282 if (mode
->alpha_bits
)
2284 if (mode
->color_bits
< color_bits
)
2289 if (mode
->bits_per_pixel
< color_bits
)
2292 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
2293 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
2295 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
2296 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
2299 if (pixel_formats
[i
].accum_mode
)
2301 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
2302 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
2303 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
2304 mode
->alpha_bits
< accum_alpha_bits
)
2307 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
2310 piFormats
[found
++] = i
+ 1;
2311 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
2315 *nNumFormats
= found
;
2321 /***********************************************************************
2322 * macdrv_wglCreateContextAttribsARB
2324 * WGL_ARB_create_context: wglCreateContextAttribsARB
2326 static struct wgl_context
*macdrv_wglCreateContextAttribsARB(HDC hdc
,
2327 struct wgl_context
*share_context
,
2328 const int *attrib_list
)
2331 struct wgl_context
*context
;
2333 int major
= 1, minor
= 0, profile
= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
, flags
= 0;
2336 TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc
, share_context
, attrib_list
);
2338 format
= get_dc_pixel_format(hdc
);
2340 if (!is_valid_pixel_format(format
))
2342 ERR("Invalid pixel format %d, expect problems!\n", format
);
2343 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2347 for (iptr
= attrib_list
; iptr
&& *iptr
; iptr
+= 2)
2350 int value
= iptr
[1];
2352 TRACE("%s\n", debugstr_attrib(attr
, value
));
2356 case WGL_CONTEXT_MAJOR_VERSION_ARB
:
2360 case WGL_CONTEXT_MINOR_VERSION_ARB
:
2364 case WGL_CONTEXT_LAYER_PLANE_ARB
:
2365 WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
2368 case WGL_CONTEXT_FLAGS_ARB
:
2370 if (flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2371 WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
2372 flags
& ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
);
2375 case WGL_CONTEXT_PROFILE_MASK_ARB
:
2376 if (value
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
&&
2377 value
!= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
)
2379 WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value
);
2380 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2387 WARN("Unknown attribute %s.\n", debugstr_attrib(attr
, value
));
2388 SetLastError(ERROR_INVALID_PARAMETER
);
2393 if ((major
== 3 && (minor
== 2 || minor
== 3)) ||
2394 (major
== 4 && (minor
== 0 || minor
== 1)))
2396 if (!(flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
))
2398 WARN("OS X only supports forward-compatible 3.2+ contexts\n");
2399 SetLastError(ERROR_INVALID_VERSION_ARB
);
2402 if (profile
!= WGL_CONTEXT_CORE_PROFILE_BIT_ARB
)
2404 WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
2405 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2408 if (major
> gl_info
.max_major
||
2409 (major
== gl_info
.max_major
&& minor
> gl_info
.max_minor
))
2411 WARN("This GL implementation does not support the requested GL version %u.%u\n",
2413 SetLastError(ERROR_INVALID_PROFILE_ARB
);
2418 else if (major
>= 3)
2420 WARN("Profile version %u.%u not supported\n", major
, minor
);
2421 SetLastError(ERROR_INVALID_VERSION_ARB
);
2424 else if (major
< 1 || (major
== 1 && (minor
< 0 || minor
> 5)) ||
2425 (major
== 2 && (minor
< 0 || minor
> 1)))
2427 WARN("Invalid GL version requested\n");
2428 SetLastError(ERROR_INVALID_VERSION_ARB
);
2431 if (!core
&& flags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
2433 WARN("Forward compatible context requested for GL version < 3\n");
2434 SetLastError(ERROR_INVALID_VERSION_ARB
);
2438 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
2440 context
->format
= format
;
2441 if (!create_context(context
, share_context
? share_context
->cglcontext
: NULL
, major
))
2443 HeapFree(GetProcessHeap(), 0, context
);
2447 EnterCriticalSection(&context_section
);
2448 list_add_tail(&context_list
, &context
->entry
);
2449 LeaveCriticalSection(&context_section
);
2455 /**********************************************************************
2456 * macdrv_wglCreatePbufferARB
2458 * WGL_ARB_pbuffer: wglCreatePbufferARB
2460 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
2461 const int *piAttribList
)
2463 struct wgl_pbuffer
* pbuffer
;
2465 GLenum internalFormat
= 0;
2468 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2469 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2471 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2473 WARN("invalid pixel format %d\n", iPixelFormat
);
2474 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2478 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2479 pbuffer
->format
= iPixelFormat
;
2481 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2483 int attr
= piAttribList
[0];
2484 int value
= piAttribList
[1];
2488 case WGL_PBUFFER_LARGEST_ARB
:
2489 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2492 case WGL_TEXTURE_FORMAT_ARB
:
2495 case WGL_TEXTURE_RGBA_ARB
:
2496 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2497 internalFormat
= GL_RGBA
;
2499 case WGL_TEXTURE_RGB_ARB
:
2500 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2501 internalFormat
= GL_RGB
;
2503 case WGL_NO_TEXTURE_ARB
:
2504 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2508 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2509 SetLastError(ERROR_INVALID_DATA
);
2514 case WGL_TEXTURE_TARGET_ARB
:
2518 case WGL_NO_TEXTURE_ARB
:
2519 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2522 case WGL_TEXTURE_CUBE_MAP_ARB
:
2523 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2524 target
= GL_TEXTURE_CUBE_MAP
;
2525 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2527 case WGL_TEXTURE_1D_ARB
:
2528 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2529 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2531 case WGL_TEXTURE_2D_ARB
:
2532 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2533 target
= GL_TEXTURE_2D
;
2535 case WGL_TEXTURE_RECTANGLE_NV
:
2536 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2537 target
= GL_TEXTURE_RECTANGLE
;
2540 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2541 SetLastError(ERROR_INVALID_DATA
);
2546 case WGL_MIPMAP_TEXTURE_ARB
:
2547 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2548 pbuffer
->max_level
= 0;
2551 int size
= min(iWidth
, iHeight
) / 2;
2554 pbuffer
->max_level
++;
2561 WARN("unknown attribute 0x%x\n", attr
);
2562 SetLastError(ERROR_INVALID_DATA
);
2567 if (!target
|| !internalFormat
)
2569 pbuffer
->no_texture
= TRUE
;
2570 /* no actual way to turn off ability to texture; use most permissive target */
2571 target
= GL_TEXTURE_RECTANGLE
;
2572 internalFormat
= GL_RGB
;
2575 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2576 if (err
!= kCGLNoError
)
2578 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2579 pbuffer
->pbuffer
= NULL
;
2580 if (err
== kCGLBadAlloc
)
2581 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2583 SetLastError(ERROR_INVALID_DATA
);
2587 if (!pbuffer
->pbuffer
)
2589 HeapFree(GetProcessHeap(), 0, pbuffer
);
2593 TRACE(" -> %p\n", pbuffer
);
2598 /**********************************************************************
2599 * macdrv_wglDestroyPbufferARB
2601 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2603 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2605 TRACE("pbuffer %p\n", pbuffer
);
2606 if (pbuffer
&& pbuffer
->pbuffer
)
2607 CGLReleasePBuffer(pbuffer
->pbuffer
);
2608 HeapFree(GetProcessHeap(), 0, pbuffer
);
2613 /**********************************************************************
2614 * macdrv_wglGetExtensionsStringARB
2616 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2618 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2620 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2621 this can be specific to the CGL renderer like we're supposed to do. */
2622 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2623 return gl_info
.wglExtensions
;
2627 /**********************************************************************
2628 * macdrv_wglGetExtensionsStringEXT
2630 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2632 static const char *macdrv_wglGetExtensionsStringEXT(void)
2634 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2635 return gl_info
.wglExtensions
;
2639 /**********************************************************************
2640 * macdrv_wglGetPbufferDCARB
2642 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2644 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2647 struct wgl_pbuffer
*prev
;
2649 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2652 EnterCriticalSection(&dc_pbuffers_section
);
2653 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2656 CGLReleasePBuffer(prev
->pbuffer
);
2657 HeapFree(GetProcessHeap(), 0, prev
);
2659 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2660 LeaveCriticalSection(&dc_pbuffers_section
);
2662 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2667 /**********************************************************************
2668 * macdrv_wglGetPixelFormatAttribivARB
2670 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2672 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2673 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2675 const pixel_format
*pf
;
2678 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2679 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2681 if (!nAttributes
) return GL_TRUE
;
2683 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2685 piValues
[0] = nb_formats
;
2686 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2690 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2693 WARN("invalid pixel format %d\n", iPixelFormat
);
2694 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2698 for (i
= 0; i
< nAttributes
; ++i
)
2700 switch (piAttributes
[i
])
2702 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2703 piValues
[i
] = nb_formats
;
2706 case WGL_DRAW_TO_WINDOW_ARB
:
2707 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2710 case WGL_DRAW_TO_BITMAP_ARB
:
2711 piValues
[i
] = GL_FALSE
;
2714 case WGL_ACCELERATION_ARB
:
2715 if (iLayerPlane
) goto invalid_layer
;
2716 if (pf
->accelerated
)
2717 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2719 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2722 case WGL_NEED_PALETTE_ARB
:
2723 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2724 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2725 piValues
[i
] = GL_FALSE
;
2728 case WGL_SWAP_METHOD_ARB
:
2729 if (pf
->double_buffer
&& pf
->backing_store
)
2730 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2732 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2735 case WGL_NUMBER_OVERLAYS_ARB
:
2736 case WGL_NUMBER_UNDERLAYS_ARB
:
2740 case WGL_TRANSPARENT_ARB
:
2741 if (iLayerPlane
) goto invalid_layer
;
2742 piValues
[i
] = GL_FALSE
;
2745 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2746 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2747 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2748 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2749 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2750 if (iLayerPlane
) goto invalid_layer
;
2754 case WGL_SHARE_DEPTH_ARB
:
2755 case WGL_SHARE_STENCIL_ARB
:
2756 case WGL_SHARE_ACCUM_ARB
:
2757 if (iLayerPlane
) goto invalid_layer
;
2758 piValues
[i
] = GL_TRUE
;
2761 case WGL_SUPPORT_GDI_ARB
:
2762 if (iLayerPlane
) goto invalid_layer
;
2763 piValues
[i
] = GL_FALSE
;
2766 case WGL_SUPPORT_OPENGL_ARB
:
2767 if (iLayerPlane
) goto invalid_layer
;
2768 piValues
[i
] = GL_TRUE
;
2771 case WGL_DOUBLE_BUFFER_ARB
:
2772 if (iLayerPlane
) goto invalid_layer
;
2773 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2776 case WGL_STEREO_ARB
:
2777 if (iLayerPlane
) goto invalid_layer
;
2778 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2781 case WGL_PIXEL_TYPE_ARB
:
2782 if (iLayerPlane
) goto invalid_layer
;
2783 if (color_modes
[pf
->color_mode
].is_float
)
2784 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2786 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2787 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2788 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2789 However, Mac contexts don't support rendering to unsigned floating-point
2790 formats, even when GL_EXT_packed_float is supported. */
2793 case WGL_COLOR_BITS_ARB
:
2794 if (iLayerPlane
) goto invalid_layer
;
2795 /* If the mode doesn't have alpha, return bits per pixel instead
2796 of color bits. On Windows, color bits sometimes exceeds r+g+b
2797 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2798 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2799 pixel format, we need to accommodate that. */
2800 if (color_modes
[pf
->color_mode
].alpha_bits
)
2801 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2803 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2806 case WGL_RED_BITS_ARB
:
2807 if (iLayerPlane
) goto invalid_layer
;
2808 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2811 case WGL_RED_SHIFT_ARB
:
2812 if (iLayerPlane
) goto invalid_layer
;
2813 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2816 case WGL_GREEN_BITS_ARB
:
2817 if (iLayerPlane
) goto invalid_layer
;
2818 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2821 case WGL_GREEN_SHIFT_ARB
:
2822 if (iLayerPlane
) goto invalid_layer
;
2823 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2826 case WGL_BLUE_BITS_ARB
:
2827 if (iLayerPlane
) goto invalid_layer
;
2828 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2831 case WGL_BLUE_SHIFT_ARB
:
2832 if (iLayerPlane
) goto invalid_layer
;
2833 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2836 case WGL_ALPHA_BITS_ARB
:
2837 if (iLayerPlane
) goto invalid_layer
;
2838 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2841 case WGL_ALPHA_SHIFT_ARB
:
2842 if (iLayerPlane
) goto invalid_layer
;
2843 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2846 case WGL_ACCUM_BITS_ARB
:
2847 if (iLayerPlane
) goto invalid_layer
;
2849 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2854 case WGL_ACCUM_RED_BITS_ARB
:
2855 if (iLayerPlane
) goto invalid_layer
;
2857 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2862 case WGL_ACCUM_GREEN_BITS_ARB
:
2863 if (iLayerPlane
) goto invalid_layer
;
2865 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2870 case WGL_ACCUM_BLUE_BITS_ARB
:
2871 if (iLayerPlane
) goto invalid_layer
;
2873 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2878 case WGL_ACCUM_ALPHA_BITS_ARB
:
2879 if (iLayerPlane
) goto invalid_layer
;
2881 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2886 case WGL_DEPTH_BITS_ARB
:
2887 if (iLayerPlane
) goto invalid_layer
;
2888 piValues
[i
] = pf
->depth_bits
;
2891 case WGL_STENCIL_BITS_ARB
:
2892 if (iLayerPlane
) goto invalid_layer
;
2893 piValues
[i
] = pf
->stencil_bits
;
2896 case WGL_AUX_BUFFERS_ARB
:
2897 if (iLayerPlane
) goto invalid_layer
;
2898 piValues
[i
] = pf
->aux_buffers
;
2901 case WGL_SAMPLE_BUFFERS_ARB
:
2902 if (iLayerPlane
) goto invalid_layer
;
2903 piValues
[i
] = pf
->sample_buffers
;
2906 case WGL_SAMPLES_ARB
:
2907 if (iLayerPlane
) goto invalid_layer
;
2908 piValues
[i
] = pf
->samples
;
2911 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2912 if (iLayerPlane
) goto invalid_layer
;
2913 /* sRGB is only supported for 8-bit integer color components */
2914 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2915 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2916 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2917 !color_modes
[pf
->color_mode
].is_float
)
2918 piValues
[i
] = GL_TRUE
;
2920 piValues
[i
] = GL_FALSE
;
2923 case WGL_DRAW_TO_PBUFFER_ARB
:
2924 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2925 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2926 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2929 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2930 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2931 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2934 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2935 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2938 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2939 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2942 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2943 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2947 WARN("invalid attribute %x\n", piAttributes
[i
]);
2951 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2957 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2962 /**********************************************************************
2963 * macdrv_wglGetPixelFormatAttribfvARB
2965 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2967 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2968 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2973 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2974 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2976 /* Allocate a temporary array to store integer values */
2977 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2980 ERR("couldn't allocate %d array\n", nAttributes
);
2984 /* Piggy-back on wglGetPixelFormatAttribivARB */
2985 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2990 /* Convert integer values to float. Should also check for attributes
2991 that can give decimal values here */
2992 for (i
= 0; i
< nAttributes
; i
++)
2993 pfValues
[i
] = attr
[i
];
2996 HeapFree(GetProcessHeap(), 0, attr
);
3001 /**********************************************************************
3002 * macdrv_wglGetSwapIntervalEXT
3004 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3006 static int macdrv_wglGetSwapIntervalEXT(void)
3008 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3009 struct macdrv_win_data
*data
;
3015 if ((data
= get_win_data(context
->draw_hwnd
)))
3017 value
= data
->swap_interval
;
3018 release_win_data(data
);
3020 if (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
))
3021 set_swap_interval(context
, value
);
3025 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
3026 if (err
!= kCGLNoError
)
3028 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
3029 err
, CGLErrorString(err
));
3038 /***********************************************************************
3039 * macdrv_wglMakeContextCurrentARB
3041 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
3043 * This is not supported directly by OpenGL on the Mac. We emulate it
3044 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
3045 * temporarily swap the drawable. This follows the technique used in
3046 * the implementation of Mesa GLX for Apple.
3048 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
3050 struct macdrv_win_data
*data
;
3053 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
3054 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
3058 macdrv_make_context_current(NULL
, NULL
);
3059 NtCurrentTeb()->glContext
= NULL
;
3063 if ((hwnd
= WindowFromDC(draw_hdc
)))
3065 if (!(data
= get_win_data(hwnd
)))
3067 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
3071 if (!data
->pixel_format
)
3073 WARN("no pixel format set\n");
3074 release_win_data(data
);
3075 SetLastError(ERROR_INVALID_HANDLE
);
3078 if (context
->format
!= data
->pixel_format
)
3080 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
3081 release_win_data(data
);
3082 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3086 if (allow_vsync
&& (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || hwnd
!= context
->draw_hwnd
))
3087 set_swap_interval(context
, data
->swap_interval
);
3089 context
->draw_hwnd
= hwnd
;
3090 context
->draw_view
= data
->gl_view
;
3091 context
->draw_pbuffer
= NULL
;
3092 release_win_data(data
);
3096 struct wgl_pbuffer
*pbuffer
;
3098 EnterCriticalSection(&dc_pbuffers_section
);
3099 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
3102 if (context
->format
!= pbuffer
->format
)
3104 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
3105 LeaveCriticalSection(&dc_pbuffers_section
);
3106 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3111 (InterlockedCompareExchange(&context
->update_swap_interval
, FALSE
, TRUE
) || pbuffer
!= context
->draw_pbuffer
))
3112 set_swap_interval(context
, 0);
3116 WARN("no window or pbuffer for DC\n");
3117 LeaveCriticalSection(&dc_pbuffers_section
);
3118 SetLastError(ERROR_INVALID_HANDLE
);
3122 context
->draw_hwnd
= NULL
;
3123 context
->draw_view
= NULL
;
3124 context
->draw_pbuffer
= pbuffer
;
3125 LeaveCriticalSection(&dc_pbuffers_section
);
3128 context
->read_view
= NULL
;
3129 context
->read_pbuffer
= NULL
;
3130 if (read_hdc
&& read_hdc
!= draw_hdc
)
3132 if ((hwnd
= WindowFromDC(read_hdc
)))
3134 if ((data
= get_win_data(hwnd
)))
3136 if (data
->gl_view
!= context
->draw_view
)
3137 context
->read_view
= data
->gl_view
;
3138 release_win_data(data
);
3143 EnterCriticalSection(&dc_pbuffers_section
);
3144 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
3145 LeaveCriticalSection(&dc_pbuffers_section
);
3149 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
3150 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
3152 make_context_current(context
, FALSE
);
3153 context
->has_been_current
= TRUE
;
3154 NtCurrentTeb()->glContext
= context
;
3160 /**********************************************************************
3161 * macdrv_wglQueryPbufferARB
3163 * WGL_ARB_pbuffer: wglQueryPbufferARB
3165 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
3171 GLenum internalFormat
;
3174 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
3176 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
3177 if (err
!= kCGLNoError
)
3179 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
3180 SetLastError(ERROR_INVALID_HANDLE
);
3186 case WGL_PBUFFER_WIDTH_ARB
:
3189 case WGL_PBUFFER_HEIGHT_ARB
:
3192 case WGL_PBUFFER_LOST_ARB
:
3193 /* Mac PBuffers can't be lost */
3194 *piValue
= GL_FALSE
;
3196 case WGL_TEXTURE_FORMAT_ARB
:
3197 if (pbuffer
->no_texture
)
3198 *piValue
= WGL_NO_TEXTURE_ARB
;
3199 else switch (internalFormat
)
3202 *piValue
= WGL_TEXTURE_RGBA_ARB
;
3206 *piValue
= WGL_TEXTURE_RGB_ARB
;
3210 case WGL_TEXTURE_TARGET_ARB
:
3211 if (pbuffer
->no_texture
)
3212 *piValue
= WGL_NO_TEXTURE_ARB
;
3213 else switch (target
)
3215 case GL_TEXTURE_CUBE_MAP
:
3216 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
3219 *piValue
= WGL_TEXTURE_2D_ARB
;
3221 case GL_TEXTURE_RECTANGLE
:
3223 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
3227 case WGL_MIPMAP_TEXTURE_ARB
:
3228 *piValue
= (pbuffer
->max_level
> 0);
3230 case WGL_MIPMAP_LEVEL_ARB
:
3231 *piValue
= pbuffer
->level
;
3233 case WGL_CUBE_MAP_FACE_ARB
:
3234 switch (pbuffer
->face
)
3236 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
3238 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
3240 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
3241 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
3243 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
3244 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
3246 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
3247 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
3249 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
3250 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
3252 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
3253 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
3258 WARN("invalid attribute 0x%x\n", iAttribute
);
3259 SetLastError(ERROR_INVALID_DATA
);
3267 /**********************************************************************
3268 * macdrv_wglReleasePbufferDCARB
3270 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
3272 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
3274 struct wgl_pbuffer
*prev
;
3276 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
3278 EnterCriticalSection(&dc_pbuffers_section
);
3280 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3283 if (prev
!= pbuffer
)
3284 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
3285 CGLReleasePBuffer(prev
->pbuffer
);
3286 HeapFree(GetProcessHeap(), 0, prev
);
3287 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
3291 LeaveCriticalSection(&dc_pbuffers_section
);
3293 return hdc
&& DeleteDC(hdc
);
3297 /**********************************************************************
3298 * macdrv_wglReleaseTexImageARB
3300 * WGL_ARB_render_texture: wglReleaseTexImageARB
3302 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
3304 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3307 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
3309 if (pbuffer
->no_texture
)
3311 SetLastError(ERROR_INVALID_OPERATION
);
3315 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
3316 if (err
!= kCGLNoError
)
3318 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
3319 SetLastError(ERROR_INVALID_OPERATION
);
3327 /**********************************************************************
3328 * macdrv_wglSetPbufferAttribARB
3330 * WGL_ARB_render_texture: wglSetPbufferAttribARB
3332 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
3334 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3336 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
3338 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
3340 int attr
= piAttribList
[0];
3341 int value
= piAttribList
[1];
3344 case WGL_MIPMAP_LEVEL_ARB
:
3345 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
3346 pbuffer
->level
= value
;
3348 case WGL_CUBE_MAP_FACE_ARB
:
3351 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3352 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
3353 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
3355 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3356 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
3357 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
3359 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3360 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
3361 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
3363 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3364 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
3365 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
3367 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3368 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
3369 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
3371 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3372 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
3373 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
3376 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
3377 SetLastError(ERROR_INVALID_DATA
);
3382 WARN("invalide attribute 0x%x\n", attr
);
3383 SetLastError(ERROR_INVALID_DATA
);
3388 if (context
&& context
->draw_pbuffer
== pbuffer
)
3389 make_context_current(context
, FALSE
);
3395 /**********************************************************************
3396 * macdrv_wglSetPixelFormatWINE
3398 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
3400 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
3402 return set_pixel_format(hdc
, fmt
, TRUE
);
3406 /**********************************************************************
3407 * macdrv_wglSwapIntervalEXT
3409 * WGL_EXT_swap_control: wglSwapIntervalEXT
3411 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
3413 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3414 BOOL changed
= FALSE
;
3416 TRACE("interval %d\n", interval
);
3420 SetLastError(ERROR_INVALID_DATA
);
3426 if (context
->draw_hwnd
)
3428 struct macdrv_win_data
*data
= get_win_data(context
->draw_hwnd
);
3431 changed
= data
->swap_interval
!= interval
;
3433 data
->swap_interval
= interval
;
3434 release_win_data(data
);
3440 InterlockedExchange(&context
->update_swap_interval
, FALSE
);
3441 if (!set_swap_interval(context
, interval
))
3443 SetLastError(ERROR_GEN_FAILURE
);
3449 struct wgl_context
*ctx
;
3451 EnterCriticalSection(&context_section
);
3452 LIST_FOR_EACH_ENTRY(ctx
, &context_list
, struct wgl_context
, entry
)
3454 if (ctx
!= context
&& ctx
->draw_hwnd
== context
->draw_hwnd
)
3455 InterlockedExchange(&context
->update_swap_interval
, TRUE
);
3457 LeaveCriticalSection(&context_section
);
3464 static void register_extension(const char *ext
)
3466 if (gl_info
.wglExtensions
[0])
3467 strcat(gl_info
.wglExtensions
, " ");
3468 strcat(gl_info
.wglExtensions
, ext
);
3470 TRACE("'%s'\n", ext
);
3473 static void load_extensions(void)
3478 register_extension("WGL_ARB_extensions_string");
3479 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
3481 register_extension("WGL_ARB_make_current_read");
3482 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
3483 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
3485 register_extension("WGL_ARB_pixel_format");
3486 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
3487 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
3488 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
3490 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
3492 register_extension("WGL_ARB_pixel_format_float");
3493 register_extension("WGL_ATI_pixel_format_float");
3496 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
3497 register_extension("WGL_ARB_multisample");
3499 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3500 register_extension("WGL_ARB_framebuffer_sRGB");
3502 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
3504 register_extension("WGL_ARB_pbuffer");
3505 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3506 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3507 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3508 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3509 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3511 register_extension("WGL_ARB_render_texture");
3512 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3513 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3514 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3516 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3517 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3518 register_extension("WGL_NV_render_texture_rectangle");
3521 register_extension("WGL_ARB_create_context");
3522 register_extension("WGL_ARB_create_context_profile");
3523 opengl_funcs
.ext
.p_wglCreateContextAttribsARB
= macdrv_wglCreateContextAttribsARB
;
3528 register_extension("WGL_EXT_extensions_string");
3529 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3533 register_extension("WGL_EXT_swap_control");
3534 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3535 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3538 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3539 check for either, so register them separately. */
3540 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3541 register_extension("WGL_EXT_framebuffer_sRGB");
3543 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3544 register_extension("WGL_EXT_pixel_format_packed_float");
3547 * WINE-specific WGL Extensions
3550 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3551 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3553 register_extension("WGL_WINE_pixel_format_passthrough");
3554 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3558 static BOOL
init_opengl(void)
3560 static BOOL init_done
= FALSE
;
3564 if (init_done
) return (opengl_handle
!= NULL
);
3569 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3572 WARN("CFDictionaryCreateMutable failed\n");
3576 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3579 ERR("Failed to load OpenGL: %s\n", buffer
);
3580 ERR("OpenGL support is disabled.\n");
3584 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3586 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3588 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3593 /* redirect some standard OpenGL functions */
3594 #define REDIRECT(func) \
3595 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3596 REDIRECT(glCopyPixels
);
3597 REDIRECT(glGetString
);
3598 REDIRECT(glReadPixels
);
3599 REDIRECT(glViewport
);
3600 if (skip_single_buffer_flushes
|| allow_vsync
)
3606 /* redirect some OpenGL extension functions */
3607 #define REDIRECT(func) \
3608 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3609 REDIRECT(glCopyColorTable
);
3612 if (!init_gl_info())
3615 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3616 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3619 if (!init_pixel_formats())
3625 wine_dlclose(opengl_handle
, NULL
, 0);
3626 opengl_handle
= NULL
;
3631 /***********************************************************************
3634 * Synchronize the Mac GL view position with the Windows child window
3637 void sync_gl_view(struct macdrv_win_data
*data
)
3641 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3643 if (!data
->gl_view
) return;
3645 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3647 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3648 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3649 data
->gl_rect
= rect
;
3654 /**********************************************************************
3655 * macdrv_wglDescribePixelFormat
3657 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3659 const pixel_format
*pf
;
3660 const struct color_mode
*mode
;
3662 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3664 if (!descr
) return nb_displayable_formats
;
3665 if (size
< sizeof(*descr
)) return 0;
3667 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3670 memset(descr
, 0, sizeof(*descr
));
3671 descr
->nSize
= sizeof(*descr
);
3672 descr
->nVersion
= 1;
3674 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3675 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3676 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3677 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3678 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3679 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3681 descr
->iPixelType
= PFD_TYPE_RGBA
;
3683 mode
= &color_modes
[pf
->color_mode
];
3684 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3685 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3686 R8G8B8A0 pixel format). If an app depends on that and expects that
3687 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3688 if (mode
->alpha_bits
)
3689 descr
->cColorBits
= mode
->color_bits
;
3691 descr
->cColorBits
= mode
->bits_per_pixel
;
3692 descr
->cRedBits
= mode
->red_bits
;
3693 descr
->cRedShift
= mode
->red_shift
;
3694 descr
->cGreenBits
= mode
->green_bits
;
3695 descr
->cGreenShift
= mode
->green_shift
;
3696 descr
->cBlueBits
= mode
->blue_bits
;
3697 descr
->cBlueShift
= mode
->blue_shift
;
3698 descr
->cAlphaBits
= mode
->alpha_bits
;
3699 descr
->cAlphaShift
= mode
->alpha_shift
;
3703 mode
= &color_modes
[pf
->accum_mode
- 1];
3704 descr
->cAccumBits
= mode
->color_bits
;
3705 descr
->cAccumRedBits
= mode
->red_bits
;
3706 descr
->cAccumGreenBits
= mode
->green_bits
;
3707 descr
->cAccumBlueBits
= mode
->blue_bits
;
3708 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3711 descr
->cDepthBits
= pf
->depth_bits
;
3712 descr
->cStencilBits
= pf
->stencil_bits
;
3713 descr
->cAuxBuffers
= pf
->aux_buffers
;
3714 descr
->iLayerType
= PFD_MAIN_PLANE
;
3716 TRACE("%s\n", debugstr_pf(pf
));
3717 return nb_displayable_formats
;
3720 /***********************************************************************
3721 * macdrv_wglCopyContext
3723 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3727 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3729 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3730 if (err
!= kCGLNoError
)
3731 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3732 return (err
== kCGLNoError
);
3735 /***********************************************************************
3736 * macdrv_wglCreateContext
3738 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3740 struct wgl_context
*context
;
3742 TRACE("hdc %p\n", hdc
);
3744 context
= macdrv_wglCreateContextAttribsARB(hdc
, NULL
, NULL
);
3749 /***********************************************************************
3750 * macdrv_wglDeleteContext
3752 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3754 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3756 EnterCriticalSection(&context_section
);
3757 list_remove(&context
->entry
);
3758 LeaveCriticalSection(&context_section
);
3760 macdrv_dispose_opengl_context(context
->context
);
3761 HeapFree(GetProcessHeap(), 0, context
);
3764 /***********************************************************************
3765 * macdrv_wglGetPixelFormat
3767 static int macdrv_wglGetPixelFormat(HDC hdc
)
3771 format
= get_dc_pixel_format(hdc
);
3773 if (!is_valid_pixel_format(format
)) /* not set yet */
3775 else if (!is_displayable_pixel_format(format
))
3777 /* Non-displayable formats can't be used with traditional WGL calls.
3778 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3782 TRACE(" hdc %p -> %d\n", hdc
, format
);
3786 /***********************************************************************
3787 * macdrv_wglGetProcAddress
3789 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3793 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3794 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3800 if (dladdr(ret
, &info
))
3801 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3803 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3807 WARN("failed to find proc %s\n", debugstr_a(proc
));
3811 /***********************************************************************
3812 * macdrv_wglMakeCurrent
3814 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3816 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3817 (context
? context
->cglcontext
: NULL
));
3819 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3822 /**********************************************************************
3823 * macdrv_wglSetPixelFormat
3825 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3827 return set_pixel_format(hdc
, fmt
, FALSE
);
3830 /***********************************************************************
3831 * macdrv_wglShareLists
3833 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3835 macdrv_opengl_context saved_context
;
3836 CGLContextObj saved_cglcontext
;
3838 TRACE("org %p dest %p\n", org
, dest
);
3840 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3841 * at context creation time but in case of WGL it is done using wglShareLists.
3843 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3844 * and when a program requests sharing we recreate the destination context if it hasn't been made
3845 * current or when it hasn't shared display lists before.
3848 if (dest
->has_been_current
)
3850 WARN("could not share display lists, the destination context has been current already\n");
3853 else if (dest
->sharing
)
3855 WARN("could not share display lists because dest has already shared lists before\n");
3859 /* Re-create the Mac context and share display lists */
3860 saved_context
= dest
->context
;
3861 saved_cglcontext
= dest
->cglcontext
;
3862 dest
->context
= NULL
;
3863 dest
->cglcontext
= NULL
;
3864 if (!create_context(dest
, org
->cglcontext
, dest
->major
))
3866 dest
->context
= saved_context
;
3867 dest
->cglcontext
= saved_cglcontext
;
3871 /* Implicitly disposes of saved_cglcontext. */
3872 macdrv_dispose_opengl_context(saved_context
);
3874 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3875 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3877 org
->sharing
= TRUE
;
3878 dest
->sharing
= TRUE
;
3883 /**********************************************************************
3884 * macdrv_wglSwapBuffers
3886 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3888 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3892 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3893 (context
? context
->cglcontext
: NULL
));
3896 sync_swap_interval(context
);
3898 if ((hwnd
= WindowFromDC(hdc
)))
3900 struct macdrv_win_data
*data
;
3902 if (!(data
= get_win_data(hwnd
)))
3904 SetLastError(ERROR_INVALID_HANDLE
);
3908 if (context
&& context
->draw_view
== data
->gl_view
)
3911 release_win_data(data
);
3915 struct wgl_pbuffer
*pbuffer
;
3917 EnterCriticalSection(&dc_pbuffers_section
);
3918 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3919 LeaveCriticalSection(&dc_pbuffers_section
);
3923 SetLastError(ERROR_INVALID_HANDLE
);
3927 if (context
&& context
->draw_pbuffer
== pbuffer
)
3932 macdrv_flush_opengl_context(context
->context
);
3935 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3937 /* If there is a current context, then wglSwapBuffers should do an implicit
3938 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3939 in the other branch, but we have to do it explicitly here. */
3947 static struct opengl_funcs opengl_funcs
=
3950 macdrv_wglCopyContext
, /* p_wglCopyContext */
3951 macdrv_wglCreateContext
, /* p_wglCreateContext */
3952 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3953 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3954 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3955 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3956 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3957 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3958 macdrv_wglShareLists
, /* p_wglShareLists */
3959 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3963 /**********************************************************************
3964 * macdrv_wine_get_wgl_driver
3966 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3968 if (version
!= WINE_WGL_DRIVER_VERSION
)
3970 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3974 if (!init_opengl()) return (void *)-1;
3976 return &opengl_funcs
;