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"
29 #include "wine/library.h"
30 #include "wine/debug.h"
32 #include "wine/wgl_driver.h"
33 #include "wine/wglext.h"
37 #include <OpenGL/OpenGL.h>
38 #include <OpenGL/glu.h>
39 #include <OpenGL/CGLRenderers.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(wgl
);
49 char wglExtensions
[4096];
51 GLint max_viewport_dims
[2];
54 static struct gl_info gl_info
;
60 macdrv_opengl_context context
;
61 CGLContextObj cglcontext
;
62 macdrv_view draw_view
;
63 struct wgl_pbuffer
*draw_pbuffer
;
64 macdrv_view read_view
;
65 struct wgl_pbuffer
*read_pbuffer
;
66 BOOL has_been_current
;
68 DWORD last_flush_time
;
74 CGLPBufferObj pbuffer
;
82 static CFMutableDictionaryRef dc_pbuffers
;
84 static CRITICAL_SECTION dc_pbuffers_section
;
85 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
87 0, 0, &dc_pbuffers_section
,
88 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
89 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
91 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
94 static struct opengl_funcs opengl_funcs
;
96 #define USE_GL_FUNC(name) #name,
97 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
101 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
103 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
104 static void (*pglFlush
)(void);
105 static void (*pglFlushRenderAPPLE
)(void);
106 static const GLubyte
*(*pglGetString
)(GLenum name
);
107 static void (*pglReadPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
108 GLenum format
, GLenum type
, void *pixels
);
109 static void (*pglViewport
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
115 GLint color_bits
; /* including alpha_bits */
116 int red_bits
, red_shift
;
117 int green_bits
, green_shift
;
118 int blue_bits
, blue_shift
;
119 GLint alpha_bits
, alpha_shift
;
124 /* The value of "color_ordering" is somewhat arbitrary. It incorporates some
125 observations of the behavior of Windows systems, but also subjective judgments
126 about what color formats are more "normal" than others.
128 On at least some Windows systems, integer color formats are listed before
129 floating-point formats. Within the integer formats, higher color bits were
130 usually listed before lower color bits, while for floating-point formats it
131 was the reverse. However, that leads D3D to select 64-bit integer formats in
132 preference to 32-bit formats when the latter would be sufficient. It seems
133 that a 32-bit format is much more likely to be normally used in that case.
135 Also, there are certain odd color formats supported on the Mac which seem like
136 they would be less appropriate than more common ones. For instance, the color
137 formats with alpha in a separate byte (e.g. kCGLRGB888A8Bit with R8G8B8 in one
138 32-bit value and A8 in a separate 8-bit value) and the formats with 10-bit RGB
141 For two color formats which differ only in whether or not they have alpha bits,
142 we use the same ordering. pixel_format_comparator() gives alpha bits a
143 different weight than color formats.
145 static const struct color_mode color_modes
[] = {
146 { kCGLRGB444Bit
, 16, 12, 4, 8, 4, 4, 4, 0, 0, 0, FALSE
, 5 },
147 { kCGLARGB4444Bit
, 16, 16, 4, 8, 4, 4, 4, 0, 4, 12, FALSE
, 5 },
148 { kCGLRGB444A8Bit
, 24, 20, 4, 8, 4, 4, 4, 0, 8, 16, FALSE
, 10 },
149 { kCGLRGB555Bit
, 16, 15, 5, 10, 5, 5, 5, 0, 0, 0, FALSE
, 4 },
150 { kCGLARGB1555Bit
, 16, 16, 5, 10, 5, 5, 5, 0, 1, 15, FALSE
, 4 },
151 { kCGLRGB555A8Bit
, 24, 23, 5, 10, 5, 5, 5, 0, 8, 16, FALSE
, 9 },
152 { kCGLRGB565Bit
, 16, 16, 5, 11, 6, 5, 5, 0, 0, 0, FALSE
, 3 },
153 { kCGLRGB565A8Bit
, 24, 24, 5, 11, 6, 5, 5, 0, 8, 16, FALSE
, 8 },
154 { kCGLRGB888Bit
, 32, 24, 8, 16, 8, 8, 8, 0, 0, 0, FALSE
, 0 },
155 { kCGLARGB8888Bit
, 32, 32, 8, 16, 8, 8, 8, 0, 8, 24, FALSE
, 0 },
156 { kCGLRGB888A8Bit
, 40, 32, 8, 16, 8, 8, 8, 0, 8, 32, FALSE
, 7 },
157 { kCGLRGB101010Bit
, 32, 30, 10, 20, 10, 10, 10, 0, 0, 0, FALSE
, 6 },
158 { kCGLARGB2101010Bit
, 32, 32, 10, 20, 10, 10, 10, 0, 2, 30, FALSE
, 6 },
159 { kCGLRGB101010_A8Bit
, 40, 38, 10, 20, 10, 10, 10, 0, 8, 32, FALSE
, 11 },
160 { kCGLRGB121212Bit
, 48, 36, 12, 24, 12, 12, 12, 0, 0, 0, FALSE
, 2 },
161 { kCGLARGB12121212Bit
, 48, 48, 12, 24, 12, 12, 12, 0, 12, 36, FALSE
, 2 },
162 { kCGLRGB161616Bit
, 64, 48, 16, 48, 16, 32, 16, 16, 0, 0, FALSE
, 1 },
163 { kCGLRGBA16161616Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, FALSE
, 1 },
164 { kCGLRGBFloat64Bit
, 64, 48, 16, 32, 16, 16, 16, 0, 0, 0, TRUE
, 12 },
165 { kCGLRGBAFloat64Bit
, 64, 64, 16, 48, 16, 32, 16, 16, 16, 0, TRUE
, 12 },
166 { kCGLRGBFloat128Bit
, 128, 96, 32, 96, 32, 64, 32, 32, 0, 0, TRUE
, 13 },
167 { kCGLRGBAFloat128Bit
, 128, 128, 32, 96, 32, 64, 32, 32, 32, 0, TRUE
, 13 },
168 { kCGLRGBFloat256Bit
, 256, 192, 64, 192, 64, 128, 64, 64, 0, 0, TRUE
, 14 },
169 { kCGLRGBAFloat256Bit
, 256, 256, 64, 192, 64, 128, 64, 64, 64, 0, TRUE
, 15 },
173 static const struct {
176 } depth_stencil_modes
[] = {
204 GLint max_aux_buffers
;
205 GLint max_sample_buffers
;
212 } renderer_properties
;
216 unsigned int window
:1;
217 unsigned int pbuffer
:1;
218 unsigned int accelerated
:1;
219 unsigned int color_mode
:5; /* index into color_modes table */
220 unsigned int aux_buffers
:3;
221 unsigned int depth_bits
:8;
222 unsigned int stencil_bits
:8;
223 unsigned int accum_mode
:5; /* 1 + index into color_modes table (0 means no accum buffer) */
224 unsigned int double_buffer
:1;
225 unsigned int stereo
:1;
226 unsigned int sample_buffers
:1;
227 unsigned int samples
:5;
228 unsigned int backing_store
:1;
236 } pixel_format_or_code
;
237 C_ASSERT(sizeof(((pixel_format_or_code
*)0)->format
) <= sizeof(((pixel_format_or_code
*)0)->code
));
240 static pixel_format
*pixel_formats
;
241 static int nb_formats
, nb_displayable_formats
;
244 static void *opengl_handle
;
247 static const char* debugstr_attrib(int attrib
, int value
)
249 static const struct {
253 #define ATTRIB(a) { a, #a }
254 ATTRIB(WGL_ACCELERATION_ARB
),
255 ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB
),
256 ATTRIB(WGL_ACCUM_BITS_ARB
),
257 ATTRIB(WGL_ACCUM_BLUE_BITS_ARB
),
258 ATTRIB(WGL_ACCUM_GREEN_BITS_ARB
),
259 ATTRIB(WGL_ACCUM_RED_BITS_ARB
),
260 ATTRIB(WGL_ALPHA_BITS_ARB
),
261 ATTRIB(WGL_ALPHA_SHIFT_ARB
),
262 ATTRIB(WGL_AUX_BUFFERS_ARB
),
263 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
),
264 ATTRIB(WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
),
265 ATTRIB(WGL_BIND_TO_TEXTURE_RGB_ARB
),
266 ATTRIB(WGL_BIND_TO_TEXTURE_RGBA_ARB
),
267 ATTRIB(WGL_BLUE_BITS_ARB
),
268 ATTRIB(WGL_BLUE_SHIFT_ARB
),
269 ATTRIB(WGL_COLOR_BITS_ARB
),
270 ATTRIB(WGL_DEPTH_BITS_ARB
),
271 ATTRIB(WGL_DOUBLE_BUFFER_ARB
),
272 ATTRIB(WGL_DRAW_TO_BITMAP_ARB
),
273 ATTRIB(WGL_DRAW_TO_PBUFFER_ARB
),
274 ATTRIB(WGL_DRAW_TO_WINDOW_ARB
),
275 ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
),
276 ATTRIB(WGL_GREEN_BITS_ARB
),
277 ATTRIB(WGL_GREEN_SHIFT_ARB
),
278 ATTRIB(WGL_NEED_PALETTE_ARB
),
279 ATTRIB(WGL_NEED_SYSTEM_PALETTE_ARB
),
280 ATTRIB(WGL_NUMBER_OVERLAYS_ARB
),
281 ATTRIB(WGL_NUMBER_PIXEL_FORMATS_ARB
),
282 ATTRIB(WGL_NUMBER_UNDERLAYS_ARB
),
283 ATTRIB(WGL_PIXEL_TYPE_ARB
),
284 ATTRIB(WGL_RED_BITS_ARB
),
285 ATTRIB(WGL_RED_SHIFT_ARB
),
286 ATTRIB(WGL_SAMPLE_BUFFERS_ARB
),
287 ATTRIB(WGL_SAMPLES_ARB
),
288 ATTRIB(WGL_SHARE_ACCUM_ARB
),
289 ATTRIB(WGL_SHARE_DEPTH_ARB
),
290 ATTRIB(WGL_SHARE_STENCIL_ARB
),
291 ATTRIB(WGL_STENCIL_BITS_ARB
),
292 ATTRIB(WGL_STEREO_ARB
),
293 ATTRIB(WGL_SUPPORT_GDI_ARB
),
294 ATTRIB(WGL_SUPPORT_OPENGL_ARB
),
295 ATTRIB(WGL_SWAP_LAYER_BUFFERS_ARB
),
296 ATTRIB(WGL_SWAP_METHOD_ARB
),
297 ATTRIB(WGL_TRANSPARENT_ALPHA_VALUE_ARB
),
298 ATTRIB(WGL_TRANSPARENT_ARB
),
299 ATTRIB(WGL_TRANSPARENT_BLUE_VALUE_ARB
),
300 ATTRIB(WGL_TRANSPARENT_GREEN_VALUE_ARB
),
301 ATTRIB(WGL_TRANSPARENT_INDEX_VALUE_ARB
),
302 ATTRIB(WGL_TRANSPARENT_RED_VALUE_ARB
),
306 const char *attrib_name
= NULL
;
307 const char *value_name
= NULL
;
309 for (i
= 0; i
< sizeof(attrib_names
) / sizeof(attrib_names
[0]); i
++)
311 if (attrib_names
[i
].attrib
== attrib
)
313 attrib_name
= attrib_names
[i
].name
;
319 attrib_name
= wine_dbg_sprintf("Attrib 0x%04x", attrib
);
323 case WGL_ACCELERATION_ARB
:
326 case WGL_FULL_ACCELERATION_ARB
: value_name
= "WGL_FULL_ACCELERATION_ARB"; break;
327 case WGL_GENERIC_ACCELERATION_ARB
: value_name
= "WGL_GENERIC_ACCELERATION_ARB"; break;
328 case WGL_NO_ACCELERATION_ARB
: value_name
= "WGL_NO_ACCELERATION_ARB"; break;
331 case WGL_PIXEL_TYPE_ARB
:
334 case WGL_TYPE_COLORINDEX_ARB
: value_name
= "WGL_TYPE_COLORINDEX_ARB"; break;
335 case WGL_TYPE_RGBA_ARB
: value_name
= "WGL_TYPE_RGBA_ARB"; break;
336 case WGL_TYPE_RGBA_FLOAT_ARB
: value_name
= "WGL_TYPE_RGBA_FLOAT_ARB"; break;
337 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
: value_name
= "WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT"; break;
340 case WGL_SWAP_METHOD_ARB
:
343 case WGL_SWAP_COPY_ARB
: value_name
= "WGL_SWAP_COPY_ARB"; break;
344 case WGL_SWAP_EXCHANGE_ARB
: value_name
= "WGL_SWAP_EXCHANGE_ARB"; break;
345 case WGL_SWAP_UNDEFINED_ARB
: value_name
= "WGL_SWAP_UNDEFINED_ARB"; break;
351 value_name
= wine_dbg_sprintf("%d / 0x%04x", value
, value
);
353 return wine_dbg_sprintf("%40s: %s", attrib_name
, value_name
);
357 static BOOL
get_renderer_property(CGLRendererInfoObj renderer_info
, GLint renderer_index
,
358 CGLRendererProperty property
, GLint
*value
)
360 CGLError err
= CGLDescribeRenderer(renderer_info
, renderer_index
, property
, value
);
361 if (err
!= kCGLNoError
)
362 WARN("CGLDescribeRenderer failed for property %d: %d %s\n", property
, err
, CGLErrorString(err
));
363 return (err
== kCGLNoError
);
367 static void get_renderer_properties(CGLRendererInfoObj renderer_info
, int renderer_index
, renderer_properties
* properties
)
371 memset(properties
, 0, sizeof(*properties
));
373 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPRendererID
, &value
))
374 properties
->renderer_id
= value
& kCGLRendererIDMatchingMask
;
376 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBufferModes
, &value
))
377 properties
->buffer_modes
= value
;
379 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPColorModes
, &value
))
380 properties
->color_modes
= value
;
382 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccumModes
, &value
))
383 properties
->accum_modes
= value
;
385 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPDepthModes
, &value
))
386 properties
->depth_modes
= value
;
388 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPStencilModes
, &value
))
389 properties
->stencil_modes
= value
;
391 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxAuxBuffers
, &value
))
392 properties
->max_aux_buffers
= value
;
394 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSampleBuffers
, &value
))
395 properties
->max_sample_buffers
= value
;
397 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPMaxSamples
, &value
))
398 properties
->max_samples
= value
;
400 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOffScreen
, &value
))
401 properties
->offscreen
= (value
!= 0);
403 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPAccelerated
, &value
))
404 properties
->accelerated
= (value
!= 0);
406 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPBackingStore
, &value
))
407 properties
->backing_store
= (value
!= 0);
409 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPWindow
, &value
))
410 properties
->window
= (value
!= 0);
412 if (get_renderer_property(renderer_info
, renderer_index
, kCGLRPOnline
, &value
))
413 properties
->online
= (value
!= 0);
417 static void dump_renderer(const renderer_properties
* renderer
)
421 TRACE("Renderer ID: 0x%08x\n", renderer
->renderer_id
);
422 TRACE("Buffer modes:\n");
423 TRACE(" Monoscopic: %s\n", (renderer
->buffer_modes
& kCGLMonoscopicBit
) ? "YES" : "NO");
424 TRACE(" Stereoscopic: %s\n", (renderer
->buffer_modes
& kCGLStereoscopicBit
) ? "YES" : "NO");
425 TRACE(" Single buffer: %s\n", (renderer
->buffer_modes
& kCGLSingleBufferBit
) ? "YES" : "NO");
426 TRACE(" Double buffer: %s\n", (renderer
->buffer_modes
& kCGLDoubleBufferBit
) ? "YES" : "NO");
428 TRACE("Color buffer modes:\n");
429 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
431 if (renderer
->color_modes
& color_modes
[i
].mode
)
433 TRACE(" Color size %d, Alpha size %d", color_modes
[i
].color_bits
, color_modes
[i
].alpha_bits
);
434 if (color_modes
[i
].is_float
)
440 TRACE("Accumulation buffer sizes: { ");
441 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
443 if (renderer
->accum_modes
& color_modes
[i
].mode
)
444 TRACE("%d, ", color_modes
[i
].color_bits
);
448 TRACE("Depth buffer sizes: { ");
449 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
451 if (renderer
->depth_modes
& depth_stencil_modes
[i
].mode
)
452 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
456 TRACE("Stencil buffer sizes: { ");
457 for (i
= 0; i
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); i
++)
459 if (renderer
->stencil_modes
& depth_stencil_modes
[i
].mode
)
460 TRACE("%d, ", depth_stencil_modes
[i
].bits
);
464 TRACE("Max. Auxiliary Buffers: %d\n", renderer
->max_aux_buffers
);
465 TRACE("Max. Sample Buffers: %d\n", renderer
->max_sample_buffers
);
466 TRACE("Max. Samples: %d\n", renderer
->max_samples
);
467 TRACE("Offscreen: %s\n", renderer
->offscreen
? "YES" : "NO");
468 TRACE("Accelerated: %s\n", renderer
->accelerated
? "YES" : "NO");
469 TRACE("Backing store: %s\n", renderer
->backing_store
? "YES" : "NO");
470 TRACE("Window: %s\n", renderer
->window
? "YES" : "NO");
471 TRACE("Online: %s\n", renderer
->online
? "YES" : "NO");
475 static inline UInt64
code_for_pixel_format(const pixel_format
* format
)
477 pixel_format_or_code pfc
;
480 pfc
.format
= *format
;
485 static inline pixel_format
pixel_format_for_code(UInt64 code
)
487 pixel_format_or_code pfc
;
494 static const char *debugstr_pf(const pixel_format
*pf
)
496 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",
500 color_modes
[pf
->color_mode
].color_bits
,
501 (color_modes
[pf
->color_mode
].is_float
? "f" : ""),
502 color_modes
[pf
->color_mode
].alpha_bits
,
505 pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0,
512 code_for_pixel_format(pf
));
516 static unsigned int best_color_mode(GLint modes
, GLint color_size
, GLint alpha_size
, GLint color_float
)
521 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
523 if ((modes
& color_modes
[i
].mode
) &&
524 color_modes
[i
].color_bits
>= color_size
&&
525 color_modes
[i
].alpha_bits
>= alpha_size
&&
526 !color_modes
[i
].is_float
== !color_float
)
528 if (best
< 0) /* no existing best choice */
530 else if (color_modes
[i
].color_bits
== color_size
&&
531 color_modes
[i
].alpha_bits
== alpha_size
) /* candidate is exact match */
533 /* prefer it over a best which isn't exact or which has a higher bpp */
534 if (color_modes
[best
].color_bits
!= color_size
||
535 color_modes
[best
].alpha_bits
!= alpha_size
||
536 color_modes
[i
].bits_per_pixel
< color_modes
[best
].bits_per_pixel
)
539 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
||
540 (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
&&
541 color_modes
[i
].alpha_bits
< color_modes
[best
].alpha_bits
)) /* prefer closer */
548 /* Couldn't find a match. Return first one that renderer supports. */
549 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
551 if (modes
& color_modes
[i
].mode
)
560 static unsigned int best_accum_mode(GLint modes
, GLint accum_size
)
565 for (i
= 0; i
< sizeof(color_modes
)/sizeof(color_modes
[0]); i
++)
567 if ((modes
& color_modes
[i
].mode
) && color_modes
[i
].color_bits
>= accum_size
)
569 /* Prefer the fewest color bits, then prefer more alpha bits, then
570 prefer more bits per pixel. */
573 else if (color_modes
[i
].color_bits
< color_modes
[best
].color_bits
)
575 else if (color_modes
[i
].color_bits
== color_modes
[best
].color_bits
)
577 if (color_modes
[i
].alpha_bits
> color_modes
[best
].alpha_bits
)
579 else if (color_modes
[i
].alpha_bits
== color_modes
[best
].alpha_bits
&&
580 color_modes
[i
].bits_per_pixel
> color_modes
[best
].bits_per_pixel
)
588 /* Couldn't find a match. Return last one that renderer supports. */
589 for (i
= sizeof(color_modes
)/sizeof(color_modes
[0]) - 1; i
>= 0; i
--)
591 if (modes
& color_modes
[i
].mode
)
600 static void enum_renderer_pixel_formats(renderer_properties renderer
, CFMutableArrayRef pixel_format_array
,
601 CFMutableSetRef pixel_format_set
)
603 CGLPixelFormatAttribute attribs
[64] = {
604 kCGLPFAMinimumPolicy
,
605 kCGLPFAClosestPolicy
,
606 kCGLPFARendererID
, renderer
.renderer_id
,
607 kCGLPFASingleRenderer
,
609 int n
= 5, n_stack
[16], n_stack_idx
= -1;
610 unsigned int tried_pixel_formats
= 0, failed_pixel_formats
= 0, dupe_pixel_formats
= 0,
611 new_pixel_formats
= 0;
612 pixel_format request
;
613 unsigned int double_buffer
;
614 unsigned int accelerated
= renderer
.accelerated
;
618 attribs
[n
++] = kCGLPFAAccelerated
;
619 attribs
[n
++] = kCGLPFANoRecovery
;
621 else if (!allow_software_rendering
)
623 TRACE("ignoring software renderer because AllowSoftwareRendering is off\n");
627 n_stack
[++n_stack_idx
] = n
;
628 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
632 n
= n_stack
[n_stack_idx
];
634 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
635 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
639 attribs
[n
++] = kCGLPFADoubleBuffer
;
640 memset(&request
, 0, sizeof(request
));
641 request
.accelerated
= accelerated
;
642 request
.double_buffer
= double_buffer
;
644 /* Don't bother with in-between aux buffers values: either 0 or max. */
645 n_stack
[++n_stack_idx
] = n
;
646 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
648 unsigned int color_mode
;
650 n
= n_stack
[n_stack_idx
];
652 attribs
[n
++] = kCGLPFAAuxBuffers
;
654 request
.aux_buffers
= aux
;
656 n_stack
[++n_stack_idx
] = n
;
657 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
659 unsigned int depth_mode
;
661 n
= n_stack
[n_stack_idx
];
663 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
666 attribs
[n
++] = kCGLPFAColorSize
;
667 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
668 attribs
[n
++] = kCGLPFAAlphaSize
;
669 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
670 if (color_modes
[color_mode
].is_float
)
671 attribs
[n
++] = kCGLPFAColorFloat
;
672 request
.color_mode
= color_mode
;
674 n_stack
[++n_stack_idx
] = n
;
675 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
677 unsigned int stencil_mode
;
679 n
= n_stack
[n_stack_idx
];
681 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
684 attribs
[n
++] = kCGLPFADepthSize
;
685 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
686 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
688 n_stack
[++n_stack_idx
] = n
;
689 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
693 n
= n_stack
[n_stack_idx
];
695 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
697 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
700 attribs
[n
++] = kCGLPFAStencilSize
;
701 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
702 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
704 /* FIXME: Could trim search space a bit here depending on GPU.
705 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
706 n_stack
[++n_stack_idx
] = n
;
707 for (stereo
= 0; stereo
<= 1; stereo
++)
711 n
= n_stack
[n_stack_idx
];
713 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
714 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
718 attribs
[n
++] = kCGLPFAStereo
;
719 request
.stereo
= stereo
;
721 /* Starts at -1 for a 0 accum size */
722 n_stack
[++n_stack_idx
] = n
;
723 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
725 unsigned int target_pass
;
727 n
= n_stack
[n_stack_idx
];
731 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
734 attribs
[n
++] = kCGLPFAAccumSize
;
735 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
736 request
.accum_mode
= accum_mode
+ 1;
739 request
.accum_mode
= 0;
741 /* Targets to request are:
742 accelerated: window OR window + pbuffer
743 software: window + pbuffer */
744 n_stack
[++n_stack_idx
] = n
;
745 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
747 unsigned int samples
, max_samples
;
749 n
= n_stack
[n_stack_idx
];
751 attribs
[n
++] = kCGLPFAWindow
;
754 if (!accelerated
|| target_pass
> 0)
756 attribs
[n
++] = kCGLPFAPBuffer
;
762 /* FIXME: Could trim search space a bit here depending on GPU.
763 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
764 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
765 n_stack
[++n_stack_idx
] = n
;
766 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
767 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
769 unsigned int backing_store
, min_backing_store
, max_backing_store
;
771 n
= n_stack
[n_stack_idx
];
775 attribs
[n
++] = kCGLPFASampleBuffers
;
776 attribs
[n
++] = renderer
.max_sample_buffers
;
777 attribs
[n
++] = kCGLPFASamples
;
778 attribs
[n
++] = samples
;
779 request
.sample_buffers
= renderer
.max_sample_buffers
;
780 request
.samples
= samples
;
783 request
.sample_buffers
= request
.samples
= 0;
785 if (renderer
.backing_store
&& double_buffer
)
787 /* The software renderer seems to always preserve the backing store, whether
788 we ask for it or not. So don't bother not asking for it. */
789 min_backing_store
= accelerated
? 0 : 1;
790 max_backing_store
= 1;
793 min_backing_store
= max_backing_store
= 0;
794 n_stack
[++n_stack_idx
] = n
;
795 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
797 CGLPixelFormatObj pix
;
798 GLint virtualScreens
;
801 n
= n_stack
[n_stack_idx
];
804 attribs
[n
++] = kCGLPFABackingStore
;
805 request
.backing_store
= backing_store
;
809 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
810 if (err
== kCGLNoError
&& pix
)
813 GLint value
, color_size
, alpha_size
, color_float
;
815 CFNumberRef code_object
;
818 memset(&pf
, 0, sizeof(pf
));
820 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
821 pf
.accelerated
= value
;
822 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
823 pf
.aux_buffers
= value
;
824 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
825 pf
.depth_bits
= value
;
826 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
827 pf
.double_buffer
= value
;
828 if (pf
.double_buffer
&&
829 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
830 pf
.backing_store
= value
;
831 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
833 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
834 pf
.sample_buffers
= value
;
835 if (pf
.sample_buffers
&&
836 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
838 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
839 pf
.stencil_bits
= value
;
840 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
842 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
845 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
847 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
849 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
851 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
853 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
854 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
856 CGLReleasePixelFormat(pix
);
858 pf_code
= code_for_pixel_format(&pf
);
860 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
861 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
862 dupe_pixel_formats
++;
865 CFSetAddValue(pixel_format_set
, code_object
);
866 CFArrayAppendValue(pixel_format_array
, code_object
);
869 CFRelease(code_object
);
871 if (pf_code
== code_for_pixel_format(&request
))
872 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
875 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
876 dupe
? " (duplicate)" : "");
881 failed_pixel_formats
++;
882 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
885 tried_pixel_formats
++;
917 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
918 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
919 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
920 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
924 /* The docs for WGL_ARB_pixel_format say:
925 Indices are assigned to pixel formats in the following order:
926 1. Accelerated pixel formats that are displayable
927 2. Accelerated pixel formats that are displayable and which have
929 3. Generic pixel formats
930 4. Accelerated pixel formats that are non displayable
932 static int pixel_format_category(pixel_format pf
)
934 /* non-displayable */
938 /* non-accelerated a.k.a. software a.k.a. generic */
942 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
943 if (color_modes
[pf
.color_mode
].is_float
)
946 /* accelerated, displayable, no extended attributes */
951 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
953 CFNumberRef number1
= val1
;
954 CFNumberRef number2
= val2
;
956 pixel_format pf1
, pf2
;
957 int category1
, category2
;
959 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
960 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
961 pf1
= pixel_format_for_code(code1
);
962 pf2
= pixel_format_for_code(code2
);
963 category1
= pixel_format_category(pf1
);
964 category2
= pixel_format_category(pf2
);
966 if (category1
< category2
)
967 return kCFCompareLessThan
;
968 if (category1
> category2
)
969 return kCFCompareGreaterThan
;
971 /* Within a category, sort the "best" formats toward the front since that's
972 what wglChoosePixelFormatARB() has to do. The ordering implemented here
973 matches at least one Windows 7 machine's behavior.
975 /* Accelerated before unaccelerated. */
976 if (pf1
.accelerated
&& !pf2
.accelerated
)
977 return kCFCompareLessThan
;
978 if (!pf1
.accelerated
&& pf2
.accelerated
)
979 return kCFCompareGreaterThan
;
981 /* Explicit color mode ordering. */
982 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
983 return kCFCompareLessThan
;
984 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
985 return kCFCompareGreaterThan
;
987 /* Non-pbuffer-capable before pbuffer-capable. */
988 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
989 return kCFCompareLessThan
;
990 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
991 return kCFCompareGreaterThan
;
993 /* Fewer samples before more samples. */
994 if (pf1
.samples
< pf2
.samples
)
995 return kCFCompareLessThan
;
996 if (pf1
.samples
> pf2
.samples
)
997 return kCFCompareGreaterThan
;
999 /* Monoscopic before stereoscopic. (This is a guess.) */
1000 if (!pf1
.stereo
&& pf2
.stereo
)
1001 return kCFCompareLessThan
;
1002 if (pf1
.stereo
&& !pf2
.stereo
)
1003 return kCFCompareGreaterThan
;
1005 /* Single buffered before double buffered. */
1006 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1007 return kCFCompareLessThan
;
1008 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1009 return kCFCompareGreaterThan
;
1011 /* Possibly-optimized double buffering before backing-store-preserving
1012 double buffering. */
1013 if (!pf1
.backing_store
&& pf2
.backing_store
)
1014 return kCFCompareLessThan
;
1015 if (pf1
.backing_store
&& !pf2
.backing_store
)
1016 return kCFCompareGreaterThan
;
1018 /* Bigger depth buffer before smaller depth buffer. */
1019 if (pf1
.depth_bits
> pf2
.depth_bits
)
1020 return kCFCompareLessThan
;
1021 if (pf1
.depth_bits
< pf2
.depth_bits
)
1022 return kCFCompareGreaterThan
;
1024 /* Smaller stencil buffer before bigger stencil buffer. */
1025 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1026 return kCFCompareLessThan
;
1027 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1028 return kCFCompareGreaterThan
;
1030 /* Smaller alpha bits before larger alpha bits. */
1031 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1032 return kCFCompareLessThan
;
1033 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1034 return kCFCompareGreaterThan
;
1036 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1041 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1042 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1043 return kCFCompareLessThan
;
1044 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1045 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1046 return kCFCompareGreaterThan
;
1048 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1049 return kCFCompareLessThan
;
1050 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1051 return kCFCompareGreaterThan
;
1053 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1054 return kCFCompareLessThan
;
1055 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1056 return kCFCompareGreaterThan
;
1059 return kCFCompareGreaterThan
;
1061 else if (pf2
.accum_mode
)
1062 return kCFCompareLessThan
;
1064 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1065 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1066 return kCFCompareLessThan
;
1067 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1068 return kCFCompareGreaterThan
;
1070 /* If we get here, arbitrarily sort based on code. */
1072 return kCFCompareLessThan
;
1074 return kCFCompareGreaterThan
;
1075 return kCFCompareEqualTo
;
1079 static BOOL
init_pixel_formats(void)
1082 CGLRendererInfoObj renderer_info
;
1083 GLint rendererCount
;
1085 CFMutableSetRef pixel_format_set
;
1086 CFMutableArrayRef pixel_format_array
;
1092 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1095 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1099 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1100 if (!pixel_format_set
)
1102 WARN("CFSetCreateMutable failed\n");
1103 CGLDestroyRendererInfo(renderer_info
);
1107 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1108 if (!pixel_format_array
)
1110 WARN("CFArrayCreateMutable failed\n");
1111 CFRelease(pixel_format_set
);
1112 CGLDestroyRendererInfo(renderer_info
);
1116 for (i
= 0; i
< rendererCount
; i
++)
1118 renderer_properties renderer
;
1120 get_renderer_properties(renderer_info
, i
, &renderer
);
1123 TRACE("renderer_properties %d:\n", i
);
1124 dump_renderer(&renderer
);
1127 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1130 CFRelease(pixel_format_set
);
1131 CGLDestroyRendererInfo(renderer_info
);
1133 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1136 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1139 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1140 for (i
= 0; i
< range
.length
; i
++)
1142 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1145 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1146 pixel_formats
[i
] = pixel_format_for_code(code
);
1147 if (pixel_formats
[i
].window
)
1148 nb_displayable_formats
++;
1151 nb_formats
= range
.length
;
1152 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1156 WARN("failed to allocate pixel format list\n");
1159 WARN("got no pixel formats\n");
1161 CFRelease(pixel_format_array
);
1166 static inline BOOL
is_valid_pixel_format(int format
)
1168 return format
> 0 && format
<= nb_formats
;
1172 static inline BOOL
is_displayable_pixel_format(int format
)
1174 return format
> 0 && format
<= nb_displayable_formats
;
1178 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1180 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1181 * format in case of probing the number of pixel formats.
1183 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1185 TRACE("Returning format %d\n", format
);
1186 return &pixel_formats
[format
- 1];
1192 static BOOL
init_gl_info(void)
1194 static const char legacy_extensions
[] = " WGL_EXT_extensions_string";
1195 static const char legacy_ext_swap_control
[] = " WGL_EXT_swap_control";
1197 CGDirectDisplayID display
= CGMainDisplayID();
1198 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1199 CGLPixelFormatAttribute attribs
[] = {
1200 kCGLPFADisplayMask
, displayMask
,
1203 CGLPixelFormatObj pix
;
1204 GLint virtualScreens
;
1206 CGLContextObj context
;
1207 CGLContextObj old_context
= CGLGetCurrentContext();
1211 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1212 if (err
!= kCGLNoError
|| !pix
)
1214 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1218 err
= CGLCreateContext(pix
, NULL
, &context
);
1219 CGLReleasePixelFormat(pix
);
1220 if (err
!= kCGLNoError
|| !context
)
1222 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1226 err
= CGLSetCurrentContext(context
);
1227 if (err
!= kCGLNoError
)
1229 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1230 CGLReleaseContext(context
);
1234 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1235 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1236 strcpy(gl_info
.glVersion
, str
);
1237 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1238 length
= strlen(str
) + sizeof(legacy_extensions
);
1240 length
+= strlen(legacy_ext_swap_control
);
1241 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, length
);
1242 strcpy(gl_info
.glExtensions
, str
);
1243 strcat(gl_info
.glExtensions
, legacy_extensions
);
1245 strcat(gl_info
.glExtensions
, legacy_ext_swap_control
);
1247 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1249 TRACE("GL version : %s\n", gl_info
.glVersion
);
1250 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1252 CGLSetCurrentContext(old_context
);
1253 CGLReleaseContext(context
);
1259 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1262 *rect
= data
->client_rect
;
1264 if (data
->cocoa_window
)
1267 *window
= data
->cocoa_window
;
1268 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1272 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1273 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1274 struct macdrv_win_data
*top_data
= get_win_data(top
);
1276 if (top_data
&& top_data
->cocoa_window
)
1279 *window
= top_data
->cocoa_window
;
1280 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1281 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1286 release_win_data(top_data
);
1293 /***********************************************************************
1296 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1298 macdrv_window cocoa_window
;
1300 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1302 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1304 ERR("no top-level parent with Cocoa window in this process\n");
1308 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
1309 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1313 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1317 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1318 wine_dbgstr_rect(&data
->gl_rect
));
1320 data
->pixel_format
= format
;
1326 /**********************************************************************
1329 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1331 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1333 struct macdrv_win_data
*data
;
1334 const pixel_format
*pf
;
1335 HWND hwnd
= WindowFromDC(hdc
);
1338 TRACE("hdc %p format %d\n", hdc
, fmt
);
1340 if (!hwnd
|| hwnd
== GetDesktopWindow())
1342 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1346 if (!(data
= get_win_data(hwnd
)))
1348 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1352 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1354 ret
= (data
->pixel_format
== fmt
);
1358 /* Check if fmt is in our list of supported formats to see if it is supported. */
1359 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1362 ERR("Invalid pixel format: %d\n", fmt
);
1368 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1372 if (!set_win_format(data
, fmt
))
1374 WARN("Couldn't set format of the window, returning failure\n");
1378 TRACE("pixel format:\n");
1379 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1380 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1381 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1382 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1383 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1384 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1385 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1386 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1387 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1388 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1389 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1390 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1391 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1392 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1396 release_win_data(data
);
1397 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1402 /**********************************************************************
1403 * set_gl_view_parent
1405 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1407 struct macdrv_win_data
*data
;
1409 if (!(data
= get_win_data(hwnd
))) return;
1413 macdrv_window cocoa_window
;
1415 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1417 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1419 ERR("no top-level parent with Cocoa window in this process\n");
1420 macdrv_dispose_view(data
->gl_view
);
1421 data
->gl_view
= NULL
;
1422 release_win_data(data
);
1423 __wine_set_pixel_format( hwnd
, 0 );
1427 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1430 release_win_data(data
);
1434 /**********************************************************************
1435 * make_context_current
1437 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1440 struct wgl_pbuffer
*pbuffer
;
1444 view
= context
->read_view
;
1445 pbuffer
= context
->read_pbuffer
;
1449 view
= context
->draw_view
;
1450 pbuffer
= context
->draw_pbuffer
;
1453 if (view
|| !pbuffer
)
1454 macdrv_make_context_current(context
->context
, view
);
1457 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1459 CGLSetCurrentContext(context
->cglcontext
);
1464 /**********************************************************************
1465 * macdrv_glCopyColorTable
1467 * Hook into glCopyColorTable as part of the implementation of
1468 * wglMakeContextCurrentARB. If the context has a separate readable,
1469 * temporarily make that current, do glCopyColorTable, and then set it
1470 * back to the drawable. This is modeled after what Mesa GLX's Apple
1471 * implementation does.
1473 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1476 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1478 if (context
->read_view
|| context
->read_pbuffer
)
1479 make_context_current(context
, TRUE
);
1481 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1483 if (context
->read_view
|| context
->read_pbuffer
)
1484 make_context_current(context
, FALSE
);
1488 /**********************************************************************
1489 * macdrv_glCopyPixels
1491 * Hook into glCopyPixels as part of the implementation of
1492 * wglMakeContextCurrentARB. If the context has a separate readable,
1493 * temporarily make that current, do glCopyPixels, and then set it back
1494 * to the drawable. This is modeled after what Mesa GLX's Apple
1495 * implementation does.
1497 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1499 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1501 if (context
->read_view
|| context
->read_pbuffer
)
1502 make_context_current(context
, TRUE
);
1504 pglCopyPixels(x
, y
, width
, height
, type
);
1506 if (context
->read_view
|| context
->read_pbuffer
)
1507 make_context_current(context
, FALSE
);
1511 static void macdrv_glFlush(void)
1513 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1514 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1515 DWORD now
= GetTickCount();
1517 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1518 context
->last_flush_time
, now
);
1519 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1521 TRACE("calling glFlushRenderAPPLE()\n");
1522 pglFlushRenderAPPLE();
1526 TRACE("calling glFlush()\n");
1528 context
->last_flush_time
= now
;
1533 /**********************************************************************
1534 * macdrv_glGetString
1536 * Hook into glGetString in order to return some legacy WGL extensions
1537 * that couldn't be advertised via the standard
1538 * WGL_ARB_extensions_string mechanism. Some programs, especially
1539 * older ones, expect to find certain older extensions, such as
1540 * WGL_EXT_extensions_string itself, in the standard GL extensions
1541 * string, and won't query any other WGL extensions unless they find
1542 * that particular extension there.
1544 static const GLubyte
*macdrv_glGetString(GLenum name
)
1546 if (name
== GL_EXTENSIONS
&& gl_info
.glExtensions
)
1547 return (const GLubyte
*)gl_info
.glExtensions
;
1549 return pglGetString(name
);
1553 /**********************************************************************
1554 * macdrv_glReadPixels
1556 * Hook into glReadPixels as part of the implementation of
1557 * wglMakeContextCurrentARB. If the context has a separate readable,
1558 * temporarily make that current, do glReadPixels, and then set it back
1559 * to the drawable. This is modeled after what Mesa GLX's Apple
1560 * implementation does.
1562 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1563 GLenum format
, GLenum type
, void *pixels
)
1565 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1567 if (context
->read_view
|| context
->read_pbuffer
)
1568 make_context_current(context
, TRUE
);
1570 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1572 if (context
->read_view
|| context
->read_pbuffer
)
1573 make_context_current(context
, FALSE
);
1577 /**********************************************************************
1580 * Hook into glViewport as an opportunity to update the OpenGL context
1581 * if necessary. This is modeled after what Mesa GLX's Apple
1582 * implementation does.
1584 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1586 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1588 macdrv_update_opengl_context(context
->context
);
1589 pglViewport(x
, y
, width
, height
);
1593 /***********************************************************************
1594 * macdrv_wglBindTexImageARB
1596 * WGL_ARB_render_texture: wglBindTexImageARB
1598 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1600 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1604 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1606 if (pbuffer
->no_texture
)
1608 SetLastError(ERROR_INVALID_OPERATION
);
1612 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1613 opengl_funcs
.gl
.p_glFlush();
1617 case WGL_FRONT_LEFT_ARB
:
1618 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1619 source
= GL_FRONT_LEFT
;
1623 case WGL_FRONT_RIGHT_ARB
:
1624 source
= GL_FRONT_RIGHT
;
1626 case WGL_BACK_LEFT_ARB
:
1627 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1628 source
= GL_BACK_LEFT
;
1632 case WGL_BACK_RIGHT_ARB
:
1633 source
= GL_BACK_RIGHT
;
1635 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1636 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1637 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1638 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1646 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1647 SetLastError(ERROR_INVALID_DATA
);
1651 WARN("unknown source buffer 0x%x\n", iBuffer
);
1652 SetLastError(ERROR_INVALID_DATA
);
1656 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1657 if (err
!= kCGLNoError
)
1659 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1660 SetLastError(ERROR_INVALID_OPERATION
);
1668 /***********************************************************************
1669 * macdrv_wglChoosePixelFormatARB
1671 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1673 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1674 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1675 int *piFormats
, UINT
*nNumFormats
)
1677 pixel_format pf
, valid
;
1679 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1680 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
1685 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1686 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
1688 FIXME("unused pfAttribFList\n");
1690 memset(&pf
, 0, sizeof(pf
));
1691 memset(&valid
, 0, sizeof(valid
));
1692 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
1693 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
1697 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
1700 int value
= iptr
[1];
1702 TRACE("%s\n", debugstr_attrib(attr
, value
));
1706 case WGL_DRAW_TO_WINDOW_ARB
:
1707 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
1708 pf
.window
= (value
!= 0);
1712 case WGL_DRAW_TO_BITMAP_ARB
:
1715 case WGL_ACCELERATION_ARB
:
1716 if (value
== WGL_FULL_ACCELERATION_ARB
)
1718 else if (value
== WGL_NO_ACCELERATION_ARB
)
1722 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
1723 pf
.accelerated
= value
;
1724 valid
.accelerated
= 1;
1727 case WGL_NEED_PALETTE_ARB
:
1728 case WGL_NEED_SYSTEM_PALETTE_ARB
:
1729 case WGL_SWAP_LAYER_BUFFERS_ARB
:
1730 if (value
) goto cant_match
;
1733 case WGL_SWAP_METHOD_ARB
:
1734 if (value
== WGL_SWAP_COPY_ARB
)
1736 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
1740 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
1741 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
1742 pf
.backing_store
= value
;
1743 valid
.backing_store
= 1;
1746 case WGL_NUMBER_OVERLAYS_ARB
:
1747 case WGL_NUMBER_UNDERLAYS_ARB
:
1748 if (value
) goto cant_match
;
1751 case WGL_SHARE_DEPTH_ARB
:
1752 case WGL_SHARE_STENCIL_ARB
:
1753 case WGL_SHARE_ACCUM_ARB
:
1757 case WGL_SUPPORT_GDI_ARB
:
1758 if (value
) goto cant_match
;
1761 case WGL_SUPPORT_OPENGL_ARB
:
1762 if (!value
) goto cant_match
;
1765 case WGL_DOUBLE_BUFFER_ARB
:
1766 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
1767 pf
.double_buffer
= (value
!= 0);
1768 valid
.double_buffer
= 1;
1769 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
1772 case WGL_STEREO_ARB
:
1773 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
1774 pf
.stereo
= (value
!= 0);
1778 case WGL_PIXEL_TYPE_ARB
:
1779 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
1781 else if (value
== WGL_TYPE_RGBA_ARB
)
1785 /* Mac contexts don't support rendering to unsigned floating
1786 point formats, even if GL_EXT_packed_float is supported.
1787 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1790 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
1791 if (srgb
&& value
) goto cant_match
;
1792 float_color
= value
;
1795 case WGL_COLOR_BITS_ARB
:
1796 if (color_bits
< value
) color_bits
= value
;
1799 case WGL_RED_BITS_ARB
:
1800 if (srgb
&& value
> 8) goto cant_match
;
1801 if (red_bits
< value
) red_bits
= value
;
1804 case WGL_GREEN_BITS_ARB
:
1805 if (srgb
&& value
> 8) goto cant_match
;
1806 if (green_bits
< value
) green_bits
= value
;
1809 case WGL_BLUE_BITS_ARB
:
1810 if (srgb
&& value
> 8) goto cant_match
;
1811 if (blue_bits
< value
) blue_bits
= value
;
1814 case WGL_ALPHA_BITS_ARB
:
1815 if (alpha_bits
< value
) alpha_bits
= value
;
1818 case WGL_ACCUM_BITS_ARB
:
1819 if (accum_bits
< value
) accum_bits
= value
;
1822 case WGL_ACCUM_RED_BITS_ARB
:
1823 if (accum_red_bits
< value
) accum_red_bits
= value
;
1826 case WGL_ACCUM_GREEN_BITS_ARB
:
1827 if (accum_green_bits
< value
) accum_green_bits
= value
;
1830 case WGL_ACCUM_BLUE_BITS_ARB
:
1831 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
1834 case WGL_ACCUM_ALPHA_BITS_ARB
:
1835 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
1838 case WGL_DEPTH_BITS_ARB
:
1839 if (value
> 255) goto cant_match
;
1840 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
1843 case WGL_STENCIL_BITS_ARB
:
1844 if (value
> 255) goto cant_match
;
1845 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
1848 case WGL_AUX_BUFFERS_ARB
:
1849 if (value
> 7) goto cant_match
;
1850 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
1853 case WGL_SAMPLE_BUFFERS_ARB
:
1854 if (value
> 1) goto cant_match
;
1855 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
1858 case WGL_SAMPLES_ARB
:
1859 if (value
> 31) goto cant_match
;
1860 if (pf
.samples
< value
) pf
.samples
= value
;
1863 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1864 /* sRGB is only supported for 8-bit integer color components */
1865 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
1870 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
1871 case WGL_RED_SHIFT_ARB
:
1872 case WGL_GREEN_SHIFT_ARB
:
1873 case WGL_BLUE_SHIFT_ARB
:
1874 case WGL_ALPHA_SHIFT_ARB
:
1875 case WGL_TRANSPARENT_ARB
:
1876 case WGL_TRANSPARENT_RED_VALUE_ARB
:
1877 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
1878 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
1879 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
1880 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
1884 case WGL_DRAW_TO_PBUFFER_ARB
:
1885 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
1886 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
1887 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
1888 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
1889 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
1890 pf
.pbuffer
= (value
!= 0);
1892 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
1898 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
1903 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",
1904 valid
.window
? (pf
.window
? "1" : "0") : "?",
1905 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
1906 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
1908 float_color
== -1 ? "?" : float_color
? "f" : "",
1922 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
1923 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
1924 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
1928 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
1930 const struct color_mode
*mode
;
1932 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
1933 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
1934 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
1935 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
1936 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
1937 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
1939 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
1940 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
1941 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
1942 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
1943 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
1945 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
1946 /* If the mode doesn't have alpha, check requested color bits against
1947 bits per pixel instead of the mode's color bits. On Windows, color
1948 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1949 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1950 expects that to match such a pixel format, we need to accommodate that. */
1951 if (mode
->alpha_bits
)
1953 if (mode
->color_bits
< color_bits
)
1958 if (mode
->bits_per_pixel
< color_bits
)
1961 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
1962 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
1964 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
1965 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
1968 if (pixel_formats
[i
].accum_mode
)
1970 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
1971 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
1972 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
1973 mode
->alpha_bits
< accum_alpha_bits
)
1976 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
1979 piFormats
[found
++] = i
+ 1;
1980 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
1984 *nNumFormats
= found
;
1990 /**********************************************************************
1991 * macdrv_wglCreatePbufferARB
1993 * WGL_ARB_pbuffer: wglCreatePbufferARB
1995 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
1996 const int *piAttribList
)
1998 struct wgl_pbuffer
* pbuffer
;
2000 GLenum internalFormat
= 0;
2003 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
2004 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
2006 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
2008 WARN("invalid pixel format %d\n", iPixelFormat
);
2009 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2013 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
2014 pbuffer
->format
= iPixelFormat
;
2016 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2018 int attr
= piAttribList
[0];
2019 int value
= piAttribList
[1];
2023 case WGL_PBUFFER_LARGEST_ARB
:
2024 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
2027 case WGL_TEXTURE_FORMAT_ARB
:
2030 case WGL_TEXTURE_RGBA_ARB
:
2031 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
2032 internalFormat
= GL_RGBA
;
2034 case WGL_TEXTURE_RGB_ARB
:
2035 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2036 internalFormat
= GL_RGB
;
2038 case WGL_NO_TEXTURE_ARB
:
2039 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2043 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2044 SetLastError(ERROR_INVALID_DATA
);
2049 case WGL_TEXTURE_TARGET_ARB
:
2053 case WGL_NO_TEXTURE_ARB
:
2054 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2057 case WGL_TEXTURE_CUBE_MAP_ARB
:
2058 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2059 target
= GL_TEXTURE_CUBE_MAP
;
2060 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2062 case WGL_TEXTURE_1D_ARB
:
2063 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2064 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2066 case WGL_TEXTURE_2D_ARB
:
2067 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2068 target
= GL_TEXTURE_2D
;
2070 case WGL_TEXTURE_RECTANGLE_NV
:
2071 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2072 target
= GL_TEXTURE_RECTANGLE
;
2075 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2076 SetLastError(ERROR_INVALID_DATA
);
2081 case WGL_MIPMAP_TEXTURE_ARB
:
2082 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2083 pbuffer
->max_level
= 0;
2086 int size
= min(iWidth
, iHeight
) / 2;
2089 pbuffer
->max_level
++;
2096 WARN("unknown attribute 0x%x\n", attr
);
2097 SetLastError(ERROR_INVALID_DATA
);
2102 if (!target
|| !internalFormat
)
2104 pbuffer
->no_texture
= TRUE
;
2105 /* no actual way to turn off ability to texture; use most permissive target */
2106 target
= GL_TEXTURE_RECTANGLE
;
2107 internalFormat
= GL_RGB
;
2110 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2111 if (err
!= kCGLNoError
)
2113 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2114 pbuffer
->pbuffer
= NULL
;
2115 if (err
== kCGLBadAlloc
)
2116 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2118 SetLastError(ERROR_INVALID_DATA
);
2122 if (!pbuffer
->pbuffer
)
2124 HeapFree(GetProcessHeap(), 0, pbuffer
);
2128 TRACE(" -> %p\n", pbuffer
);
2133 /**********************************************************************
2134 * macdrv_wglDestroyPbufferARB
2136 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2138 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2140 TRACE("pbuffer %p\n", pbuffer
);
2141 if (pbuffer
&& pbuffer
->pbuffer
)
2142 CGLReleasePBuffer(pbuffer
->pbuffer
);
2143 HeapFree(GetProcessHeap(), 0, pbuffer
);
2148 /**********************************************************************
2149 * macdrv_wglGetExtensionsStringARB
2151 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2153 static const char *macdrv_wglGetExtensionsStringARB(HDC hdc
)
2155 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2156 this can be specific to the CGL renderer like we're supposed to do. */
2157 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2158 return gl_info
.wglExtensions
;
2162 /**********************************************************************
2163 * macdrv_wglGetExtensionsStringEXT
2165 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2167 static const char *macdrv_wglGetExtensionsStringEXT(void)
2169 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2170 return gl_info
.wglExtensions
;
2174 /**********************************************************************
2175 * macdrv_wglGetPbufferDCARB
2177 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2179 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2182 struct wgl_pbuffer
*prev
;
2184 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2187 EnterCriticalSection(&dc_pbuffers_section
);
2188 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2191 CGLReleasePBuffer(prev
->pbuffer
);
2192 HeapFree(GetProcessHeap(), 0, prev
);
2194 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2195 LeaveCriticalSection(&dc_pbuffers_section
);
2197 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2202 /**********************************************************************
2203 * macdrv_wglGetPixelFormatAttribivARB
2205 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2207 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2208 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2210 const pixel_format
*pf
;
2213 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2214 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2216 if (!nAttributes
) return GL_TRUE
;
2218 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2220 piValues
[0] = nb_formats
;
2221 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2225 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2228 WARN("invalid pixel format %d\n", iPixelFormat
);
2229 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2233 for (i
= 0; i
< nAttributes
; ++i
)
2235 switch (piAttributes
[i
])
2237 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2238 piValues
[i
] = nb_formats
;
2241 case WGL_DRAW_TO_WINDOW_ARB
:
2242 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2245 case WGL_DRAW_TO_BITMAP_ARB
:
2246 piValues
[i
] = GL_FALSE
;
2249 case WGL_ACCELERATION_ARB
:
2250 if (iLayerPlane
) goto invalid_layer
;
2251 if (pf
->accelerated
)
2252 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2254 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2257 case WGL_NEED_PALETTE_ARB
:
2258 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2259 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2260 piValues
[i
] = GL_FALSE
;
2263 case WGL_SWAP_METHOD_ARB
:
2264 if (pf
->double_buffer
&& pf
->backing_store
)
2265 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2267 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2270 case WGL_NUMBER_OVERLAYS_ARB
:
2271 case WGL_NUMBER_UNDERLAYS_ARB
:
2275 case WGL_TRANSPARENT_ARB
:
2276 if (iLayerPlane
) goto invalid_layer
;
2277 piValues
[i
] = GL_FALSE
;
2280 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2281 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2282 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2283 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2284 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2285 if (iLayerPlane
) goto invalid_layer
;
2289 case WGL_SHARE_DEPTH_ARB
:
2290 case WGL_SHARE_STENCIL_ARB
:
2291 case WGL_SHARE_ACCUM_ARB
:
2292 if (iLayerPlane
) goto invalid_layer
;
2293 piValues
[i
] = GL_TRUE
;
2296 case WGL_SUPPORT_GDI_ARB
:
2297 if (iLayerPlane
) goto invalid_layer
;
2298 piValues
[i
] = GL_FALSE
;
2301 case WGL_SUPPORT_OPENGL_ARB
:
2302 if (iLayerPlane
) goto invalid_layer
;
2303 piValues
[i
] = GL_TRUE
;
2306 case WGL_DOUBLE_BUFFER_ARB
:
2307 if (iLayerPlane
) goto invalid_layer
;
2308 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2311 case WGL_STEREO_ARB
:
2312 if (iLayerPlane
) goto invalid_layer
;
2313 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2316 case WGL_PIXEL_TYPE_ARB
:
2317 if (iLayerPlane
) goto invalid_layer
;
2318 if (color_modes
[pf
->color_mode
].is_float
)
2319 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2321 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2322 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2323 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2324 However, Mac contexts don't support rendering to unsigned floating-point
2325 formats, even when GL_EXT_packed_float is supported. */
2328 case WGL_COLOR_BITS_ARB
:
2329 if (iLayerPlane
) goto invalid_layer
;
2330 /* If the mode doesn't have alpha, return bits per pixel instead
2331 of color bits. On Windows, color bits sometimes exceeds r+g+b
2332 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2333 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2334 pixel format, we need to accommodate that. */
2335 if (color_modes
[pf
->color_mode
].alpha_bits
)
2336 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2338 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2341 case WGL_RED_BITS_ARB
:
2342 if (iLayerPlane
) goto invalid_layer
;
2343 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2346 case WGL_RED_SHIFT_ARB
:
2347 if (iLayerPlane
) goto invalid_layer
;
2348 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2351 case WGL_GREEN_BITS_ARB
:
2352 if (iLayerPlane
) goto invalid_layer
;
2353 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2356 case WGL_GREEN_SHIFT_ARB
:
2357 if (iLayerPlane
) goto invalid_layer
;
2358 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2361 case WGL_BLUE_BITS_ARB
:
2362 if (iLayerPlane
) goto invalid_layer
;
2363 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2366 case WGL_BLUE_SHIFT_ARB
:
2367 if (iLayerPlane
) goto invalid_layer
;
2368 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2371 case WGL_ALPHA_BITS_ARB
:
2372 if (iLayerPlane
) goto invalid_layer
;
2373 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2376 case WGL_ALPHA_SHIFT_ARB
:
2377 if (iLayerPlane
) goto invalid_layer
;
2378 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2381 case WGL_ACCUM_BITS_ARB
:
2382 if (iLayerPlane
) goto invalid_layer
;
2384 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2389 case WGL_ACCUM_RED_BITS_ARB
:
2390 if (iLayerPlane
) goto invalid_layer
;
2392 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2397 case WGL_ACCUM_GREEN_BITS_ARB
:
2398 if (iLayerPlane
) goto invalid_layer
;
2400 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2405 case WGL_ACCUM_BLUE_BITS_ARB
:
2406 if (iLayerPlane
) goto invalid_layer
;
2408 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2413 case WGL_ACCUM_ALPHA_BITS_ARB
:
2414 if (iLayerPlane
) goto invalid_layer
;
2416 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2421 case WGL_DEPTH_BITS_ARB
:
2422 if (iLayerPlane
) goto invalid_layer
;
2423 piValues
[i
] = pf
->depth_bits
;
2426 case WGL_STENCIL_BITS_ARB
:
2427 if (iLayerPlane
) goto invalid_layer
;
2428 piValues
[i
] = pf
->stencil_bits
;
2431 case WGL_AUX_BUFFERS_ARB
:
2432 if (iLayerPlane
) goto invalid_layer
;
2433 piValues
[i
] = pf
->aux_buffers
;
2436 case WGL_SAMPLE_BUFFERS_ARB
:
2437 if (iLayerPlane
) goto invalid_layer
;
2438 piValues
[i
] = pf
->sample_buffers
;
2441 case WGL_SAMPLES_ARB
:
2442 if (iLayerPlane
) goto invalid_layer
;
2443 piValues
[i
] = pf
->samples
;
2446 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2447 if (iLayerPlane
) goto invalid_layer
;
2448 /* sRGB is only supported for 8-bit integer color components */
2449 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2450 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2451 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2452 !color_modes
[pf
->color_mode
].is_float
)
2453 piValues
[i
] = GL_TRUE
;
2455 piValues
[i
] = GL_FALSE
;
2458 case WGL_DRAW_TO_PBUFFER_ARB
:
2459 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2460 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2461 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2464 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2465 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2466 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2469 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2470 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2473 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2474 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2477 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2478 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2482 WARN("invalid attribute %x\n", piAttributes
[i
]);
2486 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2492 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2497 /**********************************************************************
2498 * macdrv_wglGetPixelFormatAttribfvARB
2500 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2502 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2503 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2508 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2509 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2511 /* Allocate a temporary array to store integer values */
2512 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2515 ERR("couldn't allocate %d array\n", nAttributes
);
2519 /* Piggy-back on wglGetPixelFormatAttribivARB */
2520 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2525 /* Convert integer values to float. Should also check for attributes
2526 that can give decimal values here */
2527 for (i
= 0; i
< nAttributes
; i
++)
2528 pfValues
[i
] = attr
[i
];
2531 HeapFree(GetProcessHeap(), 0, attr
);
2536 /**********************************************************************
2537 * macdrv_wglGetSwapIntervalEXT
2539 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2541 static int macdrv_wglGetSwapIntervalEXT(void)
2543 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2549 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2550 if (err
!= kCGLNoError
)
2552 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2553 err
, CGLErrorString(err
));
2561 /***********************************************************************
2562 * macdrv_wglMakeContextCurrentARB
2564 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2566 * This is not supported directly by OpenGL on the Mac. We emulate it
2567 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2568 * temporarily swap the drawable. This follows the technique used in
2569 * the implementation of Mesa GLX for Apple.
2571 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
2573 struct macdrv_win_data
*data
;
2576 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
2577 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
2581 macdrv_make_context_current(NULL
, NULL
);
2582 NtCurrentTeb()->glContext
= NULL
;
2586 if ((hwnd
= WindowFromDC(draw_hdc
)))
2588 if (!(data
= get_win_data(hwnd
)))
2590 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
2594 if (!data
->pixel_format
)
2596 WARN("no pixel format set\n");
2597 release_win_data(data
);
2598 SetLastError(ERROR_INVALID_HANDLE
);
2601 if (context
->format
!= data
->pixel_format
)
2603 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
2604 release_win_data(data
);
2605 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2609 context
->draw_view
= data
->gl_view
;
2610 context
->draw_pbuffer
= NULL
;
2611 release_win_data(data
);
2615 struct wgl_pbuffer
*pbuffer
;
2617 EnterCriticalSection(&dc_pbuffers_section
);
2618 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
2621 if (context
->format
!= pbuffer
->format
)
2623 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
2624 LeaveCriticalSection(&dc_pbuffers_section
);
2625 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2631 WARN("no window or pbuffer for DC\n");
2632 LeaveCriticalSection(&dc_pbuffers_section
);
2633 SetLastError(ERROR_INVALID_HANDLE
);
2637 context
->draw_view
= NULL
;
2638 context
->draw_pbuffer
= pbuffer
;
2639 LeaveCriticalSection(&dc_pbuffers_section
);
2642 context
->read_view
= NULL
;
2643 context
->read_pbuffer
= NULL
;
2644 if (read_hdc
&& read_hdc
!= draw_hdc
)
2646 if ((hwnd
= WindowFromDC(read_hdc
)))
2648 if ((data
= get_win_data(hwnd
)))
2650 if (data
->gl_view
!= context
->draw_view
)
2651 context
->read_view
= data
->gl_view
;
2652 release_win_data(data
);
2657 EnterCriticalSection(&dc_pbuffers_section
);
2658 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
2659 LeaveCriticalSection(&dc_pbuffers_section
);
2663 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2664 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
2666 make_context_current(context
, FALSE
);
2667 context
->has_been_current
= TRUE
;
2668 NtCurrentTeb()->glContext
= context
;
2674 /**********************************************************************
2675 * macdrv_wglQueryPbufferARB
2677 * WGL_ARB_pbuffer: wglQueryPbufferARB
2679 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
2685 GLenum internalFormat
;
2688 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
2690 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
2691 if (err
!= kCGLNoError
)
2693 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
2694 SetLastError(ERROR_INVALID_HANDLE
);
2700 case WGL_PBUFFER_WIDTH_ARB
:
2703 case WGL_PBUFFER_HEIGHT_ARB
:
2706 case WGL_PBUFFER_LOST_ARB
:
2707 /* Mac PBuffers can't be lost */
2708 *piValue
= GL_FALSE
;
2710 case WGL_TEXTURE_FORMAT_ARB
:
2711 if (pbuffer
->no_texture
)
2712 *piValue
= WGL_NO_TEXTURE_ARB
;
2713 else switch (internalFormat
)
2716 *piValue
= WGL_TEXTURE_RGBA_ARB
;
2720 *piValue
= WGL_TEXTURE_RGB_ARB
;
2724 case WGL_TEXTURE_TARGET_ARB
:
2725 if (pbuffer
->no_texture
)
2726 *piValue
= WGL_NO_TEXTURE_ARB
;
2727 else switch (target
)
2729 case GL_TEXTURE_CUBE_MAP
:
2730 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
2733 *piValue
= WGL_TEXTURE_2D_ARB
;
2735 case GL_TEXTURE_RECTANGLE
:
2737 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
2741 case WGL_MIPMAP_TEXTURE_ARB
:
2742 *piValue
= (pbuffer
->max_level
> 0);
2744 case WGL_MIPMAP_LEVEL_ARB
:
2745 *piValue
= pbuffer
->level
;
2747 case WGL_CUBE_MAP_FACE_ARB
:
2748 switch (pbuffer
->face
)
2750 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
2752 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
2754 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
2755 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
2757 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
2758 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
2760 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
2761 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
2763 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
2764 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
2766 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
2767 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
2772 WARN("invalid attribute 0x%x\n", iAttribute
);
2773 SetLastError(ERROR_INVALID_DATA
);
2781 /**********************************************************************
2782 * macdrv_wglReleasePbufferDCARB
2784 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2786 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
2788 struct wgl_pbuffer
*prev
;
2790 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
2792 EnterCriticalSection(&dc_pbuffers_section
);
2794 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2797 if (prev
!= pbuffer
)
2798 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
2799 CGLReleasePBuffer(prev
->pbuffer
);
2800 HeapFree(GetProcessHeap(), 0, prev
);
2801 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
2805 LeaveCriticalSection(&dc_pbuffers_section
);
2807 return hdc
&& DeleteDC(hdc
);
2811 /**********************************************************************
2812 * macdrv_wglReleaseTexImageARB
2814 * WGL_ARB_render_texture: wglReleaseTexImageARB
2816 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2818 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2821 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
2823 if (pbuffer
->no_texture
)
2825 SetLastError(ERROR_INVALID_OPERATION
);
2829 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
2830 if (err
!= kCGLNoError
)
2832 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2833 SetLastError(ERROR_INVALID_OPERATION
);
2841 /**********************************************************************
2842 * macdrv_wglSetPbufferAttribARB
2844 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2846 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
2848 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2850 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
2852 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2854 int attr
= piAttribList
[0];
2855 int value
= piAttribList
[1];
2858 case WGL_MIPMAP_LEVEL_ARB
:
2859 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
2860 pbuffer
->level
= value
;
2862 case WGL_CUBE_MAP_FACE_ARB
:
2865 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
2866 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2867 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2869 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
2870 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2871 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
2873 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
2874 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2875 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
2877 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
2878 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2879 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
2881 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
2882 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2883 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
2885 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
2886 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2887 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
2890 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
2891 SetLastError(ERROR_INVALID_DATA
);
2896 WARN("invalide attribute 0x%x\n", attr
);
2897 SetLastError(ERROR_INVALID_DATA
);
2902 if (context
&& context
->draw_pbuffer
== pbuffer
)
2903 make_context_current(context
, FALSE
);
2909 /**********************************************************************
2910 * macdrv_wglSetPixelFormatWINE
2912 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2914 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
2916 return set_pixel_format(hdc
, fmt
, TRUE
);
2920 /**********************************************************************
2921 * macdrv_wglSwapIntervalEXT
2923 * WGL_EXT_swap_control: wglSwapIntervalEXT
2925 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
2927 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2931 TRACE("interval %d\n", interval
);
2935 SetLastError(ERROR_INVALID_DATA
);
2939 if (!pixel_formats
[context
->format
- 1].double_buffer
)
2941 else if (interval
> 1)
2945 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2946 if (err
!= kCGLNoError
)
2948 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2949 err
, CGLErrorString(err
));
2950 SetLastError(ERROR_GEN_FAILURE
);
2958 static void register_extension(const char *ext
)
2960 if (gl_info
.wglExtensions
[0])
2961 strcat(gl_info
.wglExtensions
, " ");
2962 strcat(gl_info
.wglExtensions
, ext
);
2964 TRACE("'%s'\n", ext
);
2967 static void load_extensions(void)
2972 register_extension("WGL_ARB_extensions_string");
2973 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
2975 register_extension("WGL_ARB_make_current_read");
2976 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
2977 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
2979 register_extension("WGL_ARB_pixel_format");
2980 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
2981 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
2982 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
2984 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
2986 register_extension("WGL_ARB_pixel_format_float");
2987 register_extension("WGL_ATI_pixel_format_float");
2990 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
2991 register_extension("WGL_ARB_multisample");
2993 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
2994 register_extension("WGL_ARB_framebuffer_sRGB");
2996 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
2998 register_extension("WGL_ARB_pbuffer");
2999 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
3000 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
3001 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
3002 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
3003 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
3005 register_extension("WGL_ARB_render_texture");
3006 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
3007 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
3008 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
3010 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
3011 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
3012 register_extension("WGL_NV_render_texture_rectangle");
3016 WGL_ARB_create_context: wglCreateContextAttribsARB
3017 WGL_ARB_create_context_profile
3023 register_extension("WGL_EXT_extensions_string");
3024 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
3028 register_extension("WGL_EXT_swap_control");
3029 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
3030 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
3033 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
3034 check for either, so register them separately. */
3035 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3036 register_extension("WGL_EXT_framebuffer_sRGB");
3038 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3039 register_extension("WGL_EXT_pixel_format_packed_float");
3042 * WINE-specific WGL Extensions
3045 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3046 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3048 register_extension("WGL_WINE_pixel_format_passthrough");
3049 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3053 static BOOL
init_opengl(void)
3055 static BOOL init_done
= FALSE
;
3059 if (init_done
) return (opengl_handle
!= NULL
);
3064 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3067 WARN("CFDictionaryCreateMutable failed\n");
3071 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3074 ERR("Failed to load OpenGL: %s\n", buffer
);
3075 ERR("OpenGL support is disabled.\n");
3079 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3081 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3083 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3088 /* redirect some standard OpenGL functions */
3089 #define REDIRECT(func) \
3090 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3091 REDIRECT(glCopyPixels
);
3092 REDIRECT(glGetString
);
3093 REDIRECT(glReadPixels
);
3094 REDIRECT(glViewport
);
3095 if (skip_single_buffer_flushes
)
3099 /* redirect some OpenGL extension functions */
3100 #define REDIRECT(func) \
3101 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3102 REDIRECT(glCopyColorTable
);
3105 if (!init_gl_info())
3108 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3109 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3112 if (!init_pixel_formats())
3118 wine_dlclose(opengl_handle
, NULL
, 0);
3119 opengl_handle
= NULL
;
3124 /***********************************************************************
3127 * Synchronize the Mac GL view position with the Windows child window
3130 void sync_gl_view(struct macdrv_win_data
*data
)
3134 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3136 if (!data
->gl_view
) return;
3138 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3140 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3141 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3142 data
->gl_rect
= rect
;
3147 static int get_dc_pixel_format(HDC hdc
)
3152 if ((hwnd
= WindowFromDC(hdc
)))
3154 struct macdrv_win_data
*data
;
3156 if (!(data
= get_win_data(hwnd
)))
3158 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
3162 format
= data
->pixel_format
;
3163 release_win_data(data
);
3167 struct wgl_pbuffer
*pbuffer
;
3169 EnterCriticalSection(&dc_pbuffers_section
);
3170 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3172 format
= pbuffer
->format
;
3175 WARN("no window or pbuffer for DC %p\n", hdc
);
3178 LeaveCriticalSection(&dc_pbuffers_section
);
3185 /**********************************************************************
3188 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
)
3190 const pixel_format
*pf
;
3191 CGLPixelFormatAttribute attribs
[64];
3193 CGLPixelFormatObj pix
;
3194 GLint virtualScreens
;
3198 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
3201 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
3202 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3206 attribs
[n
++] = kCGLPFAMinimumPolicy
;
3207 attribs
[n
++] = kCGLPFAClosestPolicy
;
3209 if (pf
->accelerated
)
3211 attribs
[n
++] = kCGLPFAAccelerated
;
3212 attribs
[n
++] = kCGLPFANoRecovery
;
3216 attribs
[n
++] = kCGLPFARendererID
;
3217 attribs
[n
++] = kCGLRendererGenericFloatID
;
3220 if (pf
->double_buffer
)
3221 attribs
[n
++] = kCGLPFADoubleBuffer
;
3223 attribs
[n
++] = kCGLPFAAuxBuffers
;
3224 attribs
[n
++] = pf
->aux_buffers
;
3226 attribs
[n
++] = kCGLPFAColorSize
;
3227 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
3228 attribs
[n
++] = kCGLPFAAlphaSize
;
3229 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
3230 if (color_modes
[pf
->color_mode
].is_float
)
3231 attribs
[n
++] = kCGLPFAColorFloat
;
3233 attribs
[n
++] = kCGLPFADepthSize
;
3234 attribs
[n
++] = pf
->depth_bits
;
3236 attribs
[n
++] = kCGLPFAStencilSize
;
3237 attribs
[n
++] = pf
->stencil_bits
;
3240 attribs
[n
++] = kCGLPFAStereo
;
3244 attribs
[n
++] = kCGLPFAAccumSize
;
3245 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3249 attribs
[n
++] = kCGLPFAWindow
;
3251 attribs
[n
++] = kCGLPFAPBuffer
;
3253 if (pf
->sample_buffers
&& pf
->samples
)
3255 attribs
[n
++] = kCGLPFASampleBuffers
;
3256 attribs
[n
++] = pf
->sample_buffers
;
3257 attribs
[n
++] = kCGLPFASamples
;
3258 attribs
[n
++] = pf
->samples
;
3261 if (pf
->backing_store
)
3262 attribs
[n
++] = kCGLPFABackingStore
;
3266 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
3267 if (err
!= kCGLNoError
|| !pix
)
3269 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
3273 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
3274 CGLReleasePixelFormat(pix
);
3275 if (err
!= kCGLNoError
|| !context
->cglcontext
)
3277 context
->cglcontext
= NULL
;
3278 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
3282 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3283 a context is 1. CGL contexts default to 0, so we need to set it. This
3284 only make sense for double-buffered contexts, though. In theory, for
3285 single-buffered contexts, there's no such thing as a swap. But OS X
3286 will synchronize flushes of single-buffered contexts if this is set. */
3287 if (pf
->double_buffer
&& allow_vsync
)
3291 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&swap_interval
);
3292 if (err
!= kCGLNoError
)
3293 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err
, CGLErrorString(err
));
3295 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
3296 CGLReleaseContext(context
->cglcontext
);
3297 if (!context
->context
)
3299 WARN("macdrv_create_opengl_context() failed\n");
3303 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3309 /**********************************************************************
3310 * macdrv_wglDescribePixelFormat
3312 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3314 const pixel_format
*pf
;
3315 const struct color_mode
*mode
;
3317 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3319 if (!descr
) return nb_displayable_formats
;
3320 if (size
< sizeof(*descr
)) return 0;
3322 if (!(pf
= get_pixel_format(fmt
, FALSE
)))
3325 memset(descr
, 0, sizeof(*descr
));
3326 descr
->nSize
= sizeof(*descr
);
3327 descr
->nVersion
= 1;
3329 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3330 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3331 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3332 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3333 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3334 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3336 descr
->iPixelType
= PFD_TYPE_RGBA
;
3338 mode
= &color_modes
[pf
->color_mode
];
3339 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3340 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3341 R8G8B8A0 pixel format). If an app depends on that and expects that
3342 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3343 if (mode
->alpha_bits
)
3344 descr
->cColorBits
= mode
->color_bits
;
3346 descr
->cColorBits
= mode
->bits_per_pixel
;
3347 descr
->cRedBits
= mode
->red_bits
;
3348 descr
->cRedShift
= mode
->red_shift
;
3349 descr
->cGreenBits
= mode
->green_bits
;
3350 descr
->cGreenShift
= mode
->green_shift
;
3351 descr
->cBlueBits
= mode
->blue_bits
;
3352 descr
->cBlueShift
= mode
->blue_shift
;
3353 descr
->cAlphaBits
= mode
->alpha_bits
;
3354 descr
->cAlphaShift
= mode
->alpha_shift
;
3358 mode
= &color_modes
[pf
->accum_mode
- 1];
3359 descr
->cAccumBits
= mode
->color_bits
;
3360 descr
->cAccumRedBits
= mode
->red_bits
;
3361 descr
->cAccumGreenBits
= mode
->green_bits
;
3362 descr
->cAccumBlueBits
= mode
->blue_bits
;
3363 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3366 descr
->cDepthBits
= pf
->depth_bits
;
3367 descr
->cStencilBits
= pf
->stencil_bits
;
3368 descr
->cAuxBuffers
= pf
->aux_buffers
;
3369 descr
->iLayerType
= PFD_MAIN_PLANE
;
3371 TRACE("%s\n", debugstr_pf(pf
));
3372 return nb_displayable_formats
;
3375 /***********************************************************************
3376 * macdrv_wglCopyContext
3378 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3382 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3384 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3385 if (err
!= kCGLNoError
)
3386 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3387 return (err
== kCGLNoError
);
3390 /***********************************************************************
3391 * macdrv_wglCreateContext
3393 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3396 struct wgl_context
*context
;
3398 TRACE("hdc %p\n", hdc
);
3400 format
= get_dc_pixel_format(hdc
);
3402 if (!is_valid_pixel_format(format
))
3404 ERR("Invalid pixel format %d, expect problems!\n", format
);
3405 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3409 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3411 context
->format
= format
;
3412 if (!create_context(context
, NULL
))
3414 HeapFree(GetProcessHeap(), 0, context
);
3421 /***********************************************************************
3422 * macdrv_wglDeleteContext
3424 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3426 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3427 macdrv_dispose_opengl_context(context
->context
);
3428 HeapFree(GetProcessHeap(), 0, context
);
3431 /***********************************************************************
3432 * macdrv_wglGetPixelFormat
3434 static int macdrv_wglGetPixelFormat(HDC hdc
)
3438 format
= get_dc_pixel_format(hdc
);
3440 if (!is_valid_pixel_format(format
)) /* not set yet */
3442 else if (!is_displayable_pixel_format(format
))
3444 /* Non-displayable formats can't be used with traditional WGL calls.
3445 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3449 TRACE(" hdc %p -> %d\n", hdc
, format
);
3453 /***********************************************************************
3454 * macdrv_wglGetProcAddress
3456 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3460 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3461 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3467 if (dladdr(ret
, &info
))
3468 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3470 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3474 WARN("failed to find proc %s\n", debugstr_a(proc
));
3478 /***********************************************************************
3479 * macdrv_wglMakeCurrent
3481 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3483 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3484 (context
? context
->cglcontext
: NULL
));
3486 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3489 /**********************************************************************
3490 * macdrv_wglSetPixelFormat
3492 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3494 return set_pixel_format(hdc
, fmt
, FALSE
);
3497 /***********************************************************************
3498 * macdrv_wglShareLists
3500 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3502 macdrv_opengl_context saved_context
;
3503 CGLContextObj saved_cglcontext
;
3505 TRACE("org %p dest %p\n", org
, dest
);
3507 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3508 * at context creation time but in case of WGL it is done using wglShareLists.
3510 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3511 * and when a program requests sharing we recreate the destination context if it hasn't been made
3512 * current or when it hasn't shared display lists before.
3515 if (dest
->has_been_current
)
3517 WARN("could not share display lists, the destination context has been current already\n");
3520 else if (dest
->sharing
)
3522 WARN("could not share display lists because dest has already shared lists before\n");
3526 /* Re-create the Mac context and share display lists */
3527 saved_context
= dest
->context
;
3528 saved_cglcontext
= dest
->cglcontext
;
3529 dest
->context
= NULL
;
3530 dest
->cglcontext
= NULL
;
3531 if (!create_context(dest
, org
->cglcontext
))
3533 dest
->context
= saved_context
;
3534 dest
->cglcontext
= saved_cglcontext
;
3538 /* Implicitly disposes of saved_cglcontext. */
3539 macdrv_dispose_opengl_context(saved_context
);
3541 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3542 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3544 org
->sharing
= TRUE
;
3545 dest
->sharing
= TRUE
;
3550 /**********************************************************************
3551 * macdrv_wglSwapBuffers
3553 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3555 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3559 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3560 (context
? context
->cglcontext
: NULL
));
3562 if ((hwnd
= WindowFromDC(hdc
)))
3564 struct macdrv_win_data
*data
;
3566 if (!(data
= get_win_data(hwnd
)))
3568 SetLastError(ERROR_INVALID_HANDLE
);
3572 if (context
&& context
->draw_view
== data
->gl_view
)
3575 release_win_data(data
);
3579 struct wgl_pbuffer
*pbuffer
;
3581 EnterCriticalSection(&dc_pbuffers_section
);
3582 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3583 LeaveCriticalSection(&dc_pbuffers_section
);
3587 SetLastError(ERROR_INVALID_HANDLE
);
3591 if (context
&& context
->draw_pbuffer
== pbuffer
)
3596 macdrv_flush_opengl_context(context
->context
);
3599 FIXME("current context %p doesn't match hdc %p; can't swap\n", context
, hdc
);
3601 /* If there is a current context, then wglSwapBuffers should do an implicit
3602 glFlush(). That would be taken care of by macdrv_flush_opengl_context()
3603 in the other branch, but we have to do it explicitly here. */
3611 static struct opengl_funcs opengl_funcs
=
3614 macdrv_wglCopyContext
, /* p_wglCopyContext */
3615 macdrv_wglCreateContext
, /* p_wglCreateContext */
3616 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3617 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3618 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3619 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3620 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3621 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3622 macdrv_wglShareLists
, /* p_wglShareLists */
3623 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3627 /**********************************************************************
3628 * macdrv_wine_get_wgl_driver
3630 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3632 if (version
!= WINE_WGL_DRIVER_VERSION
)
3634 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3638 if (!init_opengl()) return (void *)-1;
3640 return &opengl_funcs
;