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
;
61 macdrv_opengl_context context
;
62 CGLContextObj cglcontext
;
63 macdrv_view draw_view
;
64 struct wgl_pbuffer
*draw_pbuffer
;
65 macdrv_view read_view
;
66 struct wgl_pbuffer
*read_pbuffer
;
67 BOOL has_been_current
;
69 DWORD last_flush_time
;
75 CGLPBufferObj pbuffer
;
83 static CFMutableDictionaryRef dc_pbuffers
;
85 static CRITICAL_SECTION dc_pbuffers_section
;
86 static CRITICAL_SECTION_DEBUG dc_pbuffers_section_debug
=
88 0, 0, &dc_pbuffers_section
,
89 { &dc_pbuffers_section_debug
.ProcessLocksList
, &dc_pbuffers_section_debug
.ProcessLocksList
},
90 0, 0, { (DWORD_PTR
)(__FILE__
": dc_pbuffers_section") }
92 static CRITICAL_SECTION dc_pbuffers_section
= { &dc_pbuffers_section_debug
, -1, 0, 0, 0, 0 };
95 static struct opengl_funcs opengl_funcs
;
97 #define USE_GL_FUNC(name) #name,
98 static const char *opengl_func_names
[] = { ALL_WGL_FUNCS
};
102 static void (*pglCopyColorTable
)(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
104 static void (*pglCopyPixels
)(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
);
105 static void (*pglFlush
)(void);
106 static void (*pglFlushRenderAPPLE
)(void);
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
;
622 n_stack
[++n_stack_idx
] = n
;
623 for (double_buffer
= 0; double_buffer
<= 1; double_buffer
++)
627 n
= n_stack
[n_stack_idx
];
629 if ((!double_buffer
&& !(renderer
.buffer_modes
& kCGLSingleBufferBit
)) ||
630 (double_buffer
&& !(renderer
.buffer_modes
& kCGLDoubleBufferBit
)))
634 attribs
[n
++] = kCGLPFADoubleBuffer
;
635 memset(&request
, 0, sizeof(request
));
636 request
.accelerated
= accelerated
;
637 request
.double_buffer
= double_buffer
;
639 /* Don't bother with in-between aux buffers values: either 0 or max. */
640 n_stack
[++n_stack_idx
] = n
;
641 for (aux
= 0; aux
<= renderer
.max_aux_buffers
; aux
+= renderer
.max_aux_buffers
)
643 unsigned int color_mode
;
645 n
= n_stack
[n_stack_idx
];
647 attribs
[n
++] = kCGLPFAAuxBuffers
;
649 request
.aux_buffers
= aux
;
651 n_stack
[++n_stack_idx
] = n
;
652 for (color_mode
= 0; color_mode
< sizeof(color_modes
)/sizeof(color_modes
[0]); color_mode
++)
654 unsigned int depth_mode
;
656 n
= n_stack
[n_stack_idx
];
658 if (!(renderer
.color_modes
& color_modes
[color_mode
].mode
))
661 attribs
[n
++] = kCGLPFAColorSize
;
662 attribs
[n
++] = color_modes
[color_mode
].color_bits
;
663 attribs
[n
++] = kCGLPFAAlphaSize
;
664 attribs
[n
++] = color_modes
[color_mode
].alpha_bits
;
665 if (color_modes
[color_mode
].is_float
)
666 attribs
[n
++] = kCGLPFAColorFloat
;
667 request
.color_mode
= color_mode
;
669 n_stack
[++n_stack_idx
] = n
;
670 for (depth_mode
= 0; depth_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); depth_mode
++)
672 unsigned int stencil_mode
;
674 n
= n_stack
[n_stack_idx
];
676 if (!(renderer
.depth_modes
& depth_stencil_modes
[depth_mode
].mode
))
679 attribs
[n
++] = kCGLPFADepthSize
;
680 attribs
[n
++] = depth_stencil_modes
[depth_mode
].bits
;
681 request
.depth_bits
= depth_stencil_modes
[depth_mode
].bits
;
683 n_stack
[++n_stack_idx
] = n
;
684 for (stencil_mode
= 0; stencil_mode
< sizeof(depth_stencil_modes
)/sizeof(depth_stencil_modes
[0]); stencil_mode
++)
688 n
= n_stack
[n_stack_idx
];
690 if (!(renderer
.stencil_modes
& depth_stencil_modes
[stencil_mode
].mode
))
692 if (accelerated
&& depth_stencil_modes
[depth_mode
].bits
!= 24 && stencil_mode
> 0)
695 attribs
[n
++] = kCGLPFAStencilSize
;
696 attribs
[n
++] = depth_stencil_modes
[stencil_mode
].bits
;
697 request
.stencil_bits
= depth_stencil_modes
[stencil_mode
].bits
;
699 /* FIXME: Could trim search space a bit here depending on GPU.
700 For ATI Radeon HD 4850, kCGLRGBA16161616Bit implies stereo-capable. */
701 n_stack
[++n_stack_idx
] = n
;
702 for (stereo
= 0; stereo
<= 1; stereo
++)
706 n
= n_stack
[n_stack_idx
];
708 if ((!stereo
&& !(renderer
.buffer_modes
& kCGLMonoscopicBit
)) ||
709 (stereo
&& !(renderer
.buffer_modes
& kCGLStereoscopicBit
)))
713 attribs
[n
++] = kCGLPFAStereo
;
714 request
.stereo
= stereo
;
716 /* Starts at -1 for a 0 accum size */
717 n_stack
[++n_stack_idx
] = n
;
718 for (accum_mode
= -1; accum_mode
< (int)(sizeof(color_modes
)/sizeof(color_modes
[0])); accum_mode
++)
720 unsigned int target_pass
;
722 n
= n_stack
[n_stack_idx
];
726 if (!(renderer
.accum_modes
& color_modes
[accum_mode
].mode
))
729 attribs
[n
++] = kCGLPFAAccumSize
;
730 attribs
[n
++] = color_modes
[accum_mode
].color_bits
;
731 request
.accum_mode
= accum_mode
+ 1;
734 request
.accum_mode
= 0;
736 /* Targets to request are:
737 accelerated: window OR window + pbuffer
738 software: window + pbuffer */
739 n_stack
[++n_stack_idx
] = n
;
740 for (target_pass
= 0; target_pass
<= accelerated
; target_pass
++)
742 unsigned int samples
, max_samples
;
744 n
= n_stack
[n_stack_idx
];
746 attribs
[n
++] = kCGLPFAWindow
;
749 if (!accelerated
|| target_pass
> 0)
751 attribs
[n
++] = kCGLPFAPBuffer
;
757 /* FIXME: Could trim search space a bit here depending on GPU.
758 For Nvidia GeForce 8800 GT, limited to 4 samples for color_bits >= 128.
759 For ATI Radeon HD 4850, can't multi-sample for color_bits >= 64 or pbuffer. */
760 n_stack
[++n_stack_idx
] = n
;
761 max_samples
= renderer
.max_sample_buffers
? max(1, renderer
.max_samples
) : 1;
762 for (samples
= 1; samples
<= max_samples
; samples
*= 2)
764 unsigned int backing_store
, min_backing_store
, max_backing_store
;
766 n
= n_stack
[n_stack_idx
];
770 attribs
[n
++] = kCGLPFASampleBuffers
;
771 attribs
[n
++] = renderer
.max_sample_buffers
;
772 attribs
[n
++] = kCGLPFASamples
;
773 attribs
[n
++] = samples
;
774 request
.sample_buffers
= renderer
.max_sample_buffers
;
775 request
.samples
= samples
;
778 request
.sample_buffers
= request
.samples
= 0;
780 if (renderer
.backing_store
&& double_buffer
)
782 /* The software renderer seems to always preserve the backing store, whether
783 we ask for it or not. So don't bother not asking for it. */
784 min_backing_store
= accelerated
? 0 : 1;
785 max_backing_store
= 1;
788 min_backing_store
= max_backing_store
= 0;
789 n_stack
[++n_stack_idx
] = n
;
790 for (backing_store
= min_backing_store
; backing_store
<= max_backing_store
; backing_store
++)
792 CGLPixelFormatObj pix
;
793 GLint virtualScreens
;
796 n
= n_stack
[n_stack_idx
];
799 attribs
[n
++] = kCGLPFABackingStore
;
800 request
.backing_store
= backing_store
;
804 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
805 if (err
== kCGLNoError
&& pix
)
808 GLint value
, color_size
, alpha_size
, color_float
;
810 CFNumberRef code_object
;
813 memset(&pf
, 0, sizeof(pf
));
815 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccelerated
, &value
) == kCGLNoError
)
816 pf
.accelerated
= value
;
817 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAuxBuffers
, &value
) == kCGLNoError
)
818 pf
.aux_buffers
= value
;
819 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADepthSize
, &value
) == kCGLNoError
)
820 pf
.depth_bits
= value
;
821 if (CGLDescribePixelFormat(pix
, 0, kCGLPFADoubleBuffer
, &value
) == kCGLNoError
)
822 pf
.double_buffer
= value
;
823 if (pf
.double_buffer
&&
824 CGLDescribePixelFormat(pix
, 0, kCGLPFABackingStore
, &value
) == kCGLNoError
)
825 pf
.backing_store
= value
;
826 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAPBuffer
, &value
) == kCGLNoError
)
828 if (CGLDescribePixelFormat(pix
, 0, kCGLPFASampleBuffers
, &value
) == kCGLNoError
)
829 pf
.sample_buffers
= value
;
830 if (pf
.sample_buffers
&&
831 CGLDescribePixelFormat(pix
, 0, kCGLPFASamples
, &value
) == kCGLNoError
)
833 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStencilSize
, &value
) == kCGLNoError
)
834 pf
.stencil_bits
= value
;
835 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAStereo
, &value
) == kCGLNoError
)
837 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAWindow
, &value
) == kCGLNoError
)
840 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorSize
, &color_size
) != kCGLNoError
)
842 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAlphaSize
, &alpha_size
) != kCGLNoError
)
844 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAColorFloat
, &color_float
) != kCGLNoError
)
846 pf
.color_mode
= best_color_mode(renderer
.color_modes
, color_size
, alpha_size
, color_float
);
848 if (CGLDescribePixelFormat(pix
, 0, kCGLPFAAccumSize
, &value
) == kCGLNoError
&& value
)
849 pf
.accum_mode
= best_accum_mode(renderer
.accum_modes
, value
) + 1;
851 CGLReleasePixelFormat(pix
);
853 pf_code
= code_for_pixel_format(&pf
);
855 code_object
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &pf_code
);
856 if ((dupe
= CFSetContainsValue(pixel_format_set
, code_object
)))
857 dupe_pixel_formats
++;
860 CFSetAddValue(pixel_format_set
, code_object
);
861 CFArrayAppendValue(pixel_format_array
, code_object
);
864 CFRelease(code_object
);
866 if (pf_code
== code_for_pixel_format(&request
))
867 TRACE("%s%s\n", debugstr_pf(&pf
), dupe
? " (duplicate)" : "");
870 TRACE("%s remapped from %s%s\n", debugstr_pf(&pf
), debugstr_pf(&request
),
871 dupe
? " (duplicate)" : "");
876 failed_pixel_formats
++;
877 TRACE("%s failed request err %d %s\n", debugstr_pf(&request
), err
, err
? CGLErrorString(err
) : "");
880 tried_pixel_formats
++;
912 TRACE("Number of pixel format attribute combinations: %u\n", tried_pixel_formats
);
913 TRACE(" Number which failed to choose a pixel format: %u\n", failed_pixel_formats
);
914 TRACE(" Number which chose redundant pixel formats: %u\n", dupe_pixel_formats
);
915 TRACE("Number of new pixel formats for this renderer: %u\n", new_pixel_formats
);
919 /* The docs for WGL_ARB_pixel_format say:
920 Indices are assigned to pixel formats in the following order:
921 1. Accelerated pixel formats that are displayable
922 2. Accelerated pixel formats that are displayable and which have
924 3. Generic pixel formats
925 4. Accelerated pixel formats that are non displayable
927 static int pixel_format_category(pixel_format pf
)
929 /* non-displayable */
933 /* non-accelerated a.k.a. software a.k.a. generic */
937 /* extended attributes that can't be represented in PIXELFORMATDESCRIPTOR */
938 if (color_modes
[pf
.color_mode
].is_float
)
941 /* accelerated, displayable, no extended attributes */
946 static CFComparisonResult
pixel_format_comparator(const void *val1
, const void *val2
, void *context
)
948 CFNumberRef number1
= val1
;
949 CFNumberRef number2
= val2
;
951 pixel_format pf1
, pf2
;
952 int category1
, category2
;
954 CFNumberGetValue(number1
, kCFNumberLongLongType
, &code1
);
955 CFNumberGetValue(number2
, kCFNumberLongLongType
, &code2
);
956 pf1
= pixel_format_for_code(code1
);
957 pf2
= pixel_format_for_code(code2
);
958 category1
= pixel_format_category(pf1
);
959 category2
= pixel_format_category(pf2
);
961 if (category1
< category2
)
962 return kCFCompareLessThan
;
963 if (category1
> category2
)
964 return kCFCompareGreaterThan
;
966 /* Within a category, sort the "best" formats toward the front since that's
967 what wglChoosePixelFormatARB() has to do. The ordering implemented here
968 matches at least one Windows 7 machine's behavior.
970 /* Accelerated before unaccelerated. */
971 if (pf1
.accelerated
&& !pf2
.accelerated
)
972 return kCFCompareLessThan
;
973 if (!pf1
.accelerated
&& pf2
.accelerated
)
974 return kCFCompareGreaterThan
;
976 /* Explicit color mode ordering. */
977 if (color_modes
[pf1
.color_mode
].color_ordering
< color_modes
[pf2
.color_mode
].color_ordering
)
978 return kCFCompareLessThan
;
979 if (color_modes
[pf1
.color_mode
].color_ordering
> color_modes
[pf2
.color_mode
].color_ordering
)
980 return kCFCompareGreaterThan
;
982 /* Non-pbuffer-capable before pbuffer-capable. */
983 if (!pf1
.pbuffer
&& pf2
.pbuffer
)
984 return kCFCompareLessThan
;
985 if (pf1
.pbuffer
&& !pf2
.pbuffer
)
986 return kCFCompareGreaterThan
;
988 /* Fewer samples before more samples. */
989 if (pf1
.samples
< pf2
.samples
)
990 return kCFCompareLessThan
;
991 if (pf1
.samples
> pf2
.samples
)
992 return kCFCompareGreaterThan
;
994 /* Monoscopic before stereoscopic. (This is a guess.) */
995 if (!pf1
.stereo
&& pf2
.stereo
)
996 return kCFCompareLessThan
;
997 if (pf1
.stereo
&& !pf2
.stereo
)
998 return kCFCompareGreaterThan
;
1000 /* Single buffered before double buffered. */
1001 if (!pf1
.double_buffer
&& pf2
.double_buffer
)
1002 return kCFCompareLessThan
;
1003 if (pf1
.double_buffer
&& !pf2
.double_buffer
)
1004 return kCFCompareGreaterThan
;
1006 /* Possibly-optimized double buffering before backing-store-preserving
1007 double buffering. */
1008 if (!pf1
.backing_store
&& pf2
.backing_store
)
1009 return kCFCompareLessThan
;
1010 if (pf1
.backing_store
&& !pf2
.backing_store
)
1011 return kCFCompareGreaterThan
;
1013 /* Bigger depth buffer before smaller depth buffer. */
1014 if (pf1
.depth_bits
> pf2
.depth_bits
)
1015 return kCFCompareLessThan
;
1016 if (pf1
.depth_bits
< pf2
.depth_bits
)
1017 return kCFCompareGreaterThan
;
1019 /* Smaller stencil buffer before bigger stencil buffer. */
1020 if (pf1
.stencil_bits
< pf2
.stencil_bits
)
1021 return kCFCompareLessThan
;
1022 if (pf1
.stencil_bits
> pf2
.stencil_bits
)
1023 return kCFCompareGreaterThan
;
1025 /* Smaller alpha bits before larger alpha bits. */
1026 if (color_modes
[pf1
.color_mode
].alpha_bits
< color_modes
[pf2
.color_mode
].alpha_bits
)
1027 return kCFCompareLessThan
;
1028 if (color_modes
[pf1
.color_mode
].alpha_bits
> color_modes
[pf2
.color_mode
].alpha_bits
)
1029 return kCFCompareGreaterThan
;
1031 /* Smaller accum buffer before larger accum buffer. (This is a guess.) */
1036 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
<
1037 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1038 return kCFCompareLessThan
;
1039 if (color_modes
[pf1
.accum_mode
- 1].color_bits
- color_modes
[pf1
.accum_mode
- 1].alpha_bits
>
1040 color_modes
[pf2
.accum_mode
- 1].color_bits
- color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1041 return kCFCompareGreaterThan
;
1043 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
< color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1044 return kCFCompareLessThan
;
1045 if (color_modes
[pf1
.accum_mode
- 1].bits_per_pixel
> color_modes
[pf2
.accum_mode
- 1].bits_per_pixel
)
1046 return kCFCompareGreaterThan
;
1048 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
< color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1049 return kCFCompareLessThan
;
1050 if (color_modes
[pf1
.accum_mode
- 1].alpha_bits
> color_modes
[pf2
.accum_mode
- 1].alpha_bits
)
1051 return kCFCompareGreaterThan
;
1054 return kCFCompareGreaterThan
;
1056 else if (pf2
.accum_mode
)
1057 return kCFCompareLessThan
;
1059 /* Fewer auxiliary buffers before more auxiliary buffers. (This is a guess.) */
1060 if (pf1
.aux_buffers
< pf2
.aux_buffers
)
1061 return kCFCompareLessThan
;
1062 if (pf1
.aux_buffers
> pf2
.aux_buffers
)
1063 return kCFCompareGreaterThan
;
1065 /* If we get here, arbitrarily sort based on code. */
1067 return kCFCompareLessThan
;
1069 return kCFCompareGreaterThan
;
1070 return kCFCompareEqualTo
;
1074 static BOOL
init_pixel_formats(void)
1077 CGLRendererInfoObj renderer_info
;
1078 GLint rendererCount
;
1080 CFMutableSetRef pixel_format_set
;
1081 CFMutableArrayRef pixel_format_array
;
1087 err
= CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), &renderer_info
, &rendererCount
);
1090 WARN("CGLQueryRendererInfo failed (%d) %s\n", err
, CGLErrorString(err
));
1094 pixel_format_set
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1095 if (!pixel_format_set
)
1097 WARN("CFSetCreateMutable failed\n");
1098 CGLDestroyRendererInfo(renderer_info
);
1102 pixel_format_array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1103 if (!pixel_format_array
)
1105 WARN("CFArrayCreateMutable failed\n");
1106 CFRelease(pixel_format_set
);
1107 CGLDestroyRendererInfo(renderer_info
);
1111 for (i
= 0; i
< rendererCount
; i
++)
1113 renderer_properties renderer
;
1115 get_renderer_properties(renderer_info
, i
, &renderer
);
1118 TRACE("renderer_properties %d:\n", i
);
1119 dump_renderer(&renderer
);
1122 enum_renderer_pixel_formats(renderer
, pixel_format_array
, pixel_format_set
);
1125 CFRelease(pixel_format_set
);
1126 CGLDestroyRendererInfo(renderer_info
);
1128 range
= CFRangeMake(0, CFArrayGetCount(pixel_format_array
));
1131 pixel_formats
= HeapAlloc(GetProcessHeap(), 0, range
.length
* sizeof(*pixel_formats
));
1134 CFArraySortValues(pixel_format_array
, range
, pixel_format_comparator
, NULL
);
1135 for (i
= 0; i
< range
.length
; i
++)
1137 CFNumberRef number
= CFArrayGetValueAtIndex(pixel_format_array
, i
);
1140 CFNumberGetValue(number
, kCFNumberLongLongType
, &code
);
1141 pixel_formats
[i
] = pixel_format_for_code(code
);
1142 if (pixel_formats
[i
].window
)
1143 nb_displayable_formats
++;
1146 nb_formats
= range
.length
;
1147 TRACE("Total number of unique pixel formats: %d\n", nb_formats
);
1151 WARN("failed to allocate pixel format list\n");
1154 WARN("got no pixel formats\n");
1156 CFRelease(pixel_format_array
);
1161 static inline BOOL
is_valid_pixel_format(int format
)
1163 return format
> 0 && format
<= nb_formats
;
1167 static inline BOOL
is_displayable_pixel_format(int format
)
1169 return format
> 0 && format
<= nb_displayable_formats
;
1173 static const pixel_format
*get_pixel_format(int format
, BOOL allow_nondisplayable
)
1175 /* Check if the pixel format is valid. Note that it is legal to pass an invalid
1176 * format in case of probing the number of pixel formats.
1178 if (is_valid_pixel_format(format
) && (is_displayable_pixel_format(format
) || allow_nondisplayable
))
1180 TRACE("Returning format %d\n", format
);
1181 return &pixel_formats
[format
- 1];
1187 static BOOL
init_gl_info(void)
1189 CGDirectDisplayID display
= CGMainDisplayID();
1190 CGOpenGLDisplayMask displayMask
= CGDisplayIDToOpenGLDisplayMask(display
);
1191 CGLPixelFormatAttribute attribs
[] = {
1192 kCGLPFADisplayMask
, displayMask
,
1195 CGLPixelFormatObj pix
;
1196 GLint virtualScreens
;
1198 CGLContextObj context
;
1199 CGLContextObj old_context
= CGLGetCurrentContext();
1202 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
1203 if (err
!= kCGLNoError
|| !pix
)
1205 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
1209 err
= CGLCreateContext(pix
, NULL
, &context
);
1210 CGLReleasePixelFormat(pix
);
1211 if (err
!= kCGLNoError
|| !context
)
1213 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1217 err
= CGLSetCurrentContext(context
);
1218 if (err
!= kCGLNoError
)
1220 WARN("CGLSetCurrentContext() failed with error %d %s\n", err
, CGLErrorString(err
));
1221 CGLReleaseContext(context
);
1225 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_VERSION
);
1226 gl_info
.glVersion
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1227 strcpy(gl_info
.glVersion
, str
);
1228 str
= (const char*)opengl_funcs
.gl
.p_glGetString(GL_EXTENSIONS
);
1229 gl_info
.glExtensions
= HeapAlloc(GetProcessHeap(), 0, strlen(str
) + 1);
1230 strcpy(gl_info
.glExtensions
, str
);
1232 opengl_funcs
.gl
.p_glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, gl_info
.max_viewport_dims
);
1234 TRACE("GL version : %s\n", gl_info
.glVersion
);
1235 TRACE("GL renderer : %s\n", opengl_funcs
.gl
.p_glGetString(GL_RENDERER
));
1237 CGLSetCurrentContext(old_context
);
1238 CGLReleaseContext(context
);
1244 static BOOL
get_gl_view_window_rect(struct macdrv_win_data
*data
, macdrv_window
*window
, RECT
*rect
)
1247 *rect
= data
->client_rect
;
1249 if (data
->cocoa_window
)
1252 *window
= data
->cocoa_window
;
1253 OffsetRect(rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1257 HWND top
= GetAncestor(data
->hwnd
, GA_ROOT
);
1258 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1259 struct macdrv_win_data
*top_data
= get_win_data(top
);
1261 if (top_data
&& top_data
->cocoa_window
)
1264 *window
= top_data
->cocoa_window
;
1265 MapWindowPoints(parent
, 0, (POINT
*)rect
, 2);
1266 OffsetRect(rect
, -top_data
->whole_rect
.left
, -top_data
->whole_rect
.top
);
1271 release_win_data(top_data
);
1278 /***********************************************************************
1281 static BOOL
set_win_format(struct macdrv_win_data
*data
, int format
)
1283 macdrv_window cocoa_window
;
1285 TRACE("hwnd %p format %d\n", data
->hwnd
, format
);
1287 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1289 ERR("no top-level parent with Cocoa window in this process\n");
1293 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
1294 data
->gl_view
= macdrv_create_view(cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1298 WARN("failed to create GL view for window %p rect %s\n", cocoa_window
, wine_dbgstr_rect(&data
->gl_rect
));
1302 TRACE("created GL view %p in window %p at %s\n", data
->gl_view
, cocoa_window
,
1303 wine_dbgstr_rect(&data
->gl_rect
));
1305 data
->pixel_format
= format
;
1311 /**********************************************************************
1314 * Implementation of wglSetPixelFormat and wglSetPixelFormatWINE.
1316 static BOOL
set_pixel_format(HDC hdc
, int fmt
, BOOL allow_reset
)
1318 struct macdrv_win_data
*data
;
1319 const pixel_format
*pf
;
1320 HWND hwnd
= WindowFromDC(hdc
);
1323 TRACE("hdc %p format %d\n", hdc
, fmt
);
1325 if (!hwnd
|| hwnd
== GetDesktopWindow())
1327 WARN("not a proper window DC %p/%p\n", hdc
, hwnd
);
1331 if (!(data
= get_win_data(hwnd
)))
1333 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
1337 if (!allow_reset
&& data
->pixel_format
) /* cannot change it if already set */
1339 ret
= (data
->pixel_format
== fmt
);
1343 /* Check if fmt is in our list of supported formats to see if it is supported. */
1344 pf
= get_pixel_format(fmt
, FALSE
/* non-displayable */);
1347 ERR("Invalid pixel format: %d\n", fmt
);
1353 WARN("Pixel format %d is not compatible for window rendering\n", fmt
);
1357 if (!set_win_format(data
, fmt
))
1359 WARN("Couldn't set format of the window, returning failure\n");
1363 TRACE("pixel format:\n");
1364 TRACE(" window: %u\n", (unsigned int)pf
->window
);
1365 TRACE(" pBuffer: %u\n", (unsigned int)pf
->pbuffer
);
1366 TRACE(" accelerated: %u\n", (unsigned int)pf
->accelerated
);
1367 TRACE(" color bits: %u%s\n", (unsigned int)color_modes
[pf
->color_mode
].color_bits
, (color_modes
[pf
->color_mode
].is_float
? " float" : ""));
1368 TRACE(" alpha bits: %u\n", (unsigned int)color_modes
[pf
->color_mode
].alpha_bits
);
1369 TRACE(" aux buffers: %u\n", (unsigned int)pf
->aux_buffers
);
1370 TRACE(" depth bits: %u\n", (unsigned int)pf
->depth_bits
);
1371 TRACE(" stencil bits: %u\n", (unsigned int)pf
->stencil_bits
);
1372 TRACE(" accum bits: %u\n", (unsigned int)pf
->accum_mode
? color_modes
[pf
->accum_mode
- 1].color_bits
: 0);
1373 TRACE(" double_buffer: %u\n", (unsigned int)pf
->double_buffer
);
1374 TRACE(" stereo: %u\n", (unsigned int)pf
->stereo
);
1375 TRACE(" sample_buffers: %u\n", (unsigned int)pf
->sample_buffers
);
1376 TRACE(" samples: %u\n", (unsigned int)pf
->samples
);
1377 TRACE(" backing_store: %u\n", (unsigned int)pf
->backing_store
);
1381 release_win_data(data
);
1382 if (ret
) __wine_set_pixel_format(hwnd
, fmt
);
1387 /**********************************************************************
1388 * set_gl_view_parent
1390 void set_gl_view_parent(HWND hwnd
, HWND parent
)
1392 struct macdrv_win_data
*data
;
1394 if (!(data
= get_win_data(hwnd
))) return;
1398 macdrv_window cocoa_window
;
1400 TRACE("moving GL view %p to parent %p\n", data
->gl_view
, parent
);
1402 if (!get_gl_view_window_rect(data
, &cocoa_window
, &data
->gl_rect
))
1404 ERR("no top-level parent with Cocoa window in this process\n");
1405 macdrv_dispose_view(data
->gl_view
);
1406 data
->gl_view
= NULL
;
1407 release_win_data(data
);
1408 __wine_set_pixel_format( hwnd
, 0 );
1412 macdrv_set_view_window_and_frame(data
->gl_view
, cocoa_window
, cgrect_from_rect(data
->gl_rect
));
1415 release_win_data(data
);
1419 /**********************************************************************
1420 * make_context_current
1422 static void make_context_current(struct wgl_context
*context
, BOOL read
)
1425 struct wgl_pbuffer
*pbuffer
;
1429 view
= context
->read_view
;
1430 pbuffer
= context
->read_pbuffer
;
1434 view
= context
->draw_view
;
1435 pbuffer
= context
->draw_pbuffer
;
1438 if (view
|| !pbuffer
)
1439 macdrv_make_context_current(context
->context
, view
);
1442 CGLSetPBuffer(context
->cglcontext
, pbuffer
->pbuffer
, pbuffer
->face
,
1444 CGLSetCurrentContext(context
->cglcontext
);
1449 /**********************************************************************
1450 * macdrv_glCopyColorTable
1452 * Hook into glCopyColorTable as part of the implementation of
1453 * wglMakeContextCurrentARB. If the context has a separate readable,
1454 * temporarily make that current, do glCopyColorTable, and then set it
1455 * back to the drawable. This is modeled after what Mesa GLX's Apple
1456 * implementation does.
1458 static void macdrv_glCopyColorTable(GLenum target
, GLenum internalformat
, GLint x
, GLint y
,
1461 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1463 if (context
->read_view
|| context
->read_pbuffer
)
1464 make_context_current(context
, TRUE
);
1466 pglCopyColorTable(target
, internalformat
, x
, y
, width
);
1468 if (context
->read_view
|| context
->read_pbuffer
)
1469 make_context_current(context
, FALSE
);
1473 /**********************************************************************
1474 * macdrv_glCopyPixels
1476 * Hook into glCopyPixels as part of the implementation of
1477 * wglMakeContextCurrentARB. If the context has a separate readable,
1478 * temporarily make that current, do glCopyPixels, and then set it back
1479 * to the drawable. This is modeled after what Mesa GLX's Apple
1480 * implementation does.
1482 static void macdrv_glCopyPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
, GLenum type
)
1484 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1486 if (context
->read_view
|| context
->read_pbuffer
)
1487 make_context_current(context
, TRUE
);
1489 pglCopyPixels(x
, y
, width
, height
, type
);
1491 if (context
->read_view
|| context
->read_pbuffer
)
1492 make_context_current(context
, FALSE
);
1496 static void macdrv_glFlush(void)
1498 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1499 const pixel_format
*pf
= &pixel_formats
[context
->format
- 1];
1500 DWORD now
= GetTickCount();
1502 TRACE("double buffer %d last flush time %d now %d\n", (int)pf
->double_buffer
,
1503 context
->last_flush_time
, now
);
1504 if (pglFlushRenderAPPLE
&& !pf
->double_buffer
&& (now
- context
->last_flush_time
) < 17)
1506 TRACE("calling glFlushRenderAPPLE()\n");
1507 pglFlushRenderAPPLE();
1511 TRACE("calling glFlush()\n");
1513 context
->last_flush_time
= now
;
1518 /**********************************************************************
1519 * macdrv_glReadPixels
1521 * Hook into glReadPixels as part of the implementation of
1522 * wglMakeContextCurrentARB. If the context has a separate readable,
1523 * temporarily make that current, do glReadPixels, and then set it back
1524 * to the drawable. This is modeled after what Mesa GLX's Apple
1525 * implementation does.
1527 static void macdrv_glReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1528 GLenum format
, GLenum type
, void *pixels
)
1530 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1532 if (context
->read_view
|| context
->read_pbuffer
)
1533 make_context_current(context
, TRUE
);
1535 pglReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
1537 if (context
->read_view
|| context
->read_pbuffer
)
1538 make_context_current(context
, FALSE
);
1542 /**********************************************************************
1545 * Hook into glViewport as an opportunity to update the OpenGL context
1546 * if necessary. This is modeled after what Mesa GLX's Apple
1547 * implementation does.
1549 static void macdrv_glViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1551 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1553 macdrv_update_opengl_context(context
->context
);
1554 pglViewport(x
, y
, width
, height
);
1558 /***********************************************************************
1559 * macdrv_wglBindTexImageARB
1561 * WGL_ARB_render_texture: wglBindTexImageARB
1563 static BOOL
macdrv_wglBindTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
1565 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
1569 TRACE("pbuffer %p iBuffer 0x%x\n", pbuffer
, iBuffer
);
1571 if (pbuffer
->no_texture
)
1573 SetLastError(ERROR_INVALID_OPERATION
);
1577 if (!context
->draw_view
&& context
->draw_pbuffer
== pbuffer
)
1578 opengl_funcs
.gl
.p_glFlush();
1582 case WGL_FRONT_LEFT_ARB
:
1583 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1584 source
= GL_FRONT_LEFT
;
1588 case WGL_FRONT_RIGHT_ARB
:
1589 source
= GL_FRONT_RIGHT
;
1591 case WGL_BACK_LEFT_ARB
:
1592 if (pixel_formats
[pbuffer
->format
- 1].stereo
)
1593 source
= GL_BACK_LEFT
;
1597 case WGL_BACK_RIGHT_ARB
:
1598 source
= GL_BACK_RIGHT
;
1600 case WGL_AUX0_ARB
: source
= GL_AUX0
; break;
1601 case WGL_AUX1_ARB
: source
= GL_AUX1
; break;
1602 case WGL_AUX2_ARB
: source
= GL_AUX2
; break;
1603 case WGL_AUX3_ARB
: source
= GL_AUX3
; break;
1611 FIXME("unsupported source buffer 0x%x\n", iBuffer
);
1612 SetLastError(ERROR_INVALID_DATA
);
1616 WARN("unknown source buffer 0x%x\n", iBuffer
);
1617 SetLastError(ERROR_INVALID_DATA
);
1621 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, source
);
1622 if (err
!= kCGLNoError
)
1624 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
1625 SetLastError(ERROR_INVALID_OPERATION
);
1633 /***********************************************************************
1634 * macdrv_wglChoosePixelFormatARB
1636 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
1638 static BOOL
macdrv_wglChoosePixelFormatARB(HDC hdc
, const int *piAttribIList
,
1639 const FLOAT
*pfAttribFList
, UINT nMaxFormats
,
1640 int *piFormats
, UINT
*nNumFormats
)
1642 pixel_format pf
, valid
;
1644 int color_bits
, red_bits
, green_bits
, blue_bits
, alpha_bits
;
1645 int accum_bits
, accum_red_bits
, accum_green_bits
, accum_blue_bits
, accum_alpha_bits
;
1650 TRACE("hdc %p piAttribIList %p pfAttribFList %p nMaxFormats %u piFormats %p nNumFormats %p\n",
1651 hdc
, piAttribIList
, pfAttribFList
, nMaxFormats
, piFormats
, nNumFormats
);
1653 FIXME("unused pfAttribFList\n");
1655 memset(&pf
, 0, sizeof(pf
));
1656 memset(&valid
, 0, sizeof(valid
));
1657 color_bits
= red_bits
= green_bits
= blue_bits
= alpha_bits
= 0;
1658 accum_bits
= accum_red_bits
= accum_green_bits
= accum_blue_bits
= accum_alpha_bits
= 0;
1662 for (iptr
= piAttribIList
; iptr
&& *iptr
; iptr
+= 2)
1665 int value
= iptr
[1];
1667 TRACE("%s\n", debugstr_attrib(attr
, value
));
1671 case WGL_DRAW_TO_WINDOW_ARB
:
1672 if (valid
.window
&& (!pf
.window
!= !value
)) goto cant_match
;
1673 pf
.window
= (value
!= 0);
1677 case WGL_DRAW_TO_BITMAP_ARB
:
1680 case WGL_ACCELERATION_ARB
:
1681 if (value
== WGL_FULL_ACCELERATION_ARB
)
1683 else if (value
== WGL_NO_ACCELERATION_ARB
)
1687 if (valid
.accelerated
&& pf
.accelerated
!= value
) goto cant_match
;
1688 pf
.accelerated
= value
;
1689 valid
.accelerated
= 1;
1692 case WGL_NEED_PALETTE_ARB
:
1693 case WGL_NEED_SYSTEM_PALETTE_ARB
:
1694 case WGL_SWAP_LAYER_BUFFERS_ARB
:
1695 if (value
) goto cant_match
;
1698 case WGL_SWAP_METHOD_ARB
:
1699 if (value
== WGL_SWAP_COPY_ARB
)
1701 else if (value
== WGL_SWAP_UNDEFINED_ARB
)
1705 if (valid
.backing_store
&& pf
.backing_store
!= value
) goto cant_match
;
1706 if (valid
.double_buffer
&& !pf
.double_buffer
&& value
) goto cant_match
;
1707 pf
.backing_store
= value
;
1708 valid
.backing_store
= 1;
1711 case WGL_NUMBER_OVERLAYS_ARB
:
1712 case WGL_NUMBER_UNDERLAYS_ARB
:
1713 if (value
) goto cant_match
;
1716 case WGL_SHARE_DEPTH_ARB
:
1717 case WGL_SHARE_STENCIL_ARB
:
1718 case WGL_SHARE_ACCUM_ARB
:
1722 case WGL_SUPPORT_GDI_ARB
:
1723 if (value
) goto cant_match
;
1726 case WGL_SUPPORT_OPENGL_ARB
:
1727 if (!value
) goto cant_match
;
1730 case WGL_DOUBLE_BUFFER_ARB
:
1731 if (valid
.double_buffer
&& (!pf
.double_buffer
!= !value
)) goto cant_match
;
1732 pf
.double_buffer
= (value
!= 0);
1733 valid
.double_buffer
= 1;
1734 if (valid
.backing_store
&& pf
.backing_store
&& !pf
.double_buffer
) goto cant_match
;
1737 case WGL_STEREO_ARB
:
1738 if (valid
.stereo
&& (!pf
.stereo
!= !value
)) goto cant_match
;
1739 pf
.stereo
= (value
!= 0);
1743 case WGL_PIXEL_TYPE_ARB
:
1744 if (value
== WGL_TYPE_RGBA_FLOAT_ARB
)
1746 else if (value
== WGL_TYPE_RGBA_ARB
)
1750 /* Mac contexts don't support rendering to unsigned floating
1751 point formats, even if GL_EXT_packed_float is supported.
1752 So, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT is not supported. */
1755 if (float_color
!= -1 && float_color
!= value
) goto cant_match
;
1756 if (srgb
&& value
) goto cant_match
;
1757 float_color
= value
;
1760 case WGL_COLOR_BITS_ARB
:
1761 if (color_bits
< value
) color_bits
= value
;
1764 case WGL_RED_BITS_ARB
:
1765 if (srgb
&& value
> 8) goto cant_match
;
1766 if (red_bits
< value
) red_bits
= value
;
1769 case WGL_GREEN_BITS_ARB
:
1770 if (srgb
&& value
> 8) goto cant_match
;
1771 if (green_bits
< value
) green_bits
= value
;
1774 case WGL_BLUE_BITS_ARB
:
1775 if (srgb
&& value
> 8) goto cant_match
;
1776 if (blue_bits
< value
) blue_bits
= value
;
1779 case WGL_ALPHA_BITS_ARB
:
1780 if (alpha_bits
< value
) alpha_bits
= value
;
1783 case WGL_ACCUM_BITS_ARB
:
1784 if (accum_bits
< value
) accum_bits
= value
;
1787 case WGL_ACCUM_RED_BITS_ARB
:
1788 if (accum_red_bits
< value
) accum_red_bits
= value
;
1791 case WGL_ACCUM_GREEN_BITS_ARB
:
1792 if (accum_green_bits
< value
) accum_green_bits
= value
;
1795 case WGL_ACCUM_BLUE_BITS_ARB
:
1796 if (accum_blue_bits
< value
) accum_blue_bits
= value
;
1799 case WGL_ACCUM_ALPHA_BITS_ARB
:
1800 if (accum_alpha_bits
< value
) accum_alpha_bits
= value
;
1803 case WGL_DEPTH_BITS_ARB
:
1804 if (value
> 255) goto cant_match
;
1805 if (pf
.depth_bits
< value
) pf
.depth_bits
= value
;
1808 case WGL_STENCIL_BITS_ARB
:
1809 if (value
> 255) goto cant_match
;
1810 if (pf
.stencil_bits
< value
) pf
.stencil_bits
= value
;
1813 case WGL_AUX_BUFFERS_ARB
:
1814 if (value
> 7) goto cant_match
;
1815 if (pf
.aux_buffers
< value
) pf
.aux_buffers
= value
;
1818 case WGL_SAMPLE_BUFFERS_ARB
:
1819 if (value
> 1) goto cant_match
;
1820 if (pf
.sample_buffers
< value
) pf
.sample_buffers
= value
;
1823 case WGL_SAMPLES_ARB
:
1824 if (value
> 31) goto cant_match
;
1825 if (pf
.samples
< value
) pf
.samples
= value
;
1828 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
1829 /* sRGB is only supported for 8-bit integer color components */
1830 if (float_color
>= 1 || red_bits
> 8 || green_bits
> 8 || blue_bits
> 8)
1835 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
1836 case WGL_RED_SHIFT_ARB
:
1837 case WGL_GREEN_SHIFT_ARB
:
1838 case WGL_BLUE_SHIFT_ARB
:
1839 case WGL_ALPHA_SHIFT_ARB
:
1840 case WGL_TRANSPARENT_ARB
:
1841 case WGL_TRANSPARENT_RED_VALUE_ARB
:
1842 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
1843 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
1844 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
1845 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
1849 case WGL_DRAW_TO_PBUFFER_ARB
:
1850 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
1851 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
1852 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
1853 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
1854 if (valid
.pbuffer
&& (!pf
.pbuffer
!= !value
)) goto cant_match
;
1855 pf
.pbuffer
= (value
!= 0);
1857 if ((attr
== WGL_BIND_TO_TEXTURE_RGBA_ARB
|| attr
== WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
) &&
1863 WARN("invalid attribute %s\n", debugstr_attrib(attr
, value
));
1868 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",
1869 valid
.window
? (pf
.window
? "1" : "0") : "?",
1870 valid
.pbuffer
? (pf
.pbuffer
? "1" : "0") : "?",
1871 valid
.accelerated
? (pf
.accelerated
? "1" : "0") : "?",
1873 float_color
== -1 ? "?" : float_color
? "f" : "",
1887 valid
.backing_store
? (pf
.backing_store
? "1" : "0") : "?",
1888 valid
.double_buffer
? (pf
.double_buffer
? "1" : "0") : "?",
1889 valid
.stereo
? (pf
.stereo
? "1" : "0") : "?",
1893 for (i
= 0; i
< nb_formats
&& found
< nMaxFormats
; i
++)
1895 const struct color_mode
*mode
;
1897 if (valid
.window
&& pixel_formats
[i
].window
!= pf
.window
) continue;
1898 if (valid
.pbuffer
&& pixel_formats
[i
].pbuffer
!= pf
.pbuffer
) continue;
1899 if (valid
.accelerated
&& pixel_formats
[i
].accelerated
!= pf
.accelerated
) continue;
1900 if (valid
.double_buffer
&& pixel_formats
[i
].double_buffer
!= pf
.double_buffer
) continue;
1901 if (valid
.stereo
&& pixel_formats
[i
].stereo
!= pf
.stereo
) continue;
1902 if (valid
.backing_store
&& pixel_formats
[i
].backing_store
!= pf
.backing_store
) continue;
1904 if (pixel_formats
[i
].aux_buffers
< pf
.aux_buffers
) continue;
1905 if (pixel_formats
[i
].depth_bits
< pf
.depth_bits
) continue;
1906 if (pixel_formats
[i
].stencil_bits
< pf
.stencil_bits
) continue;
1907 if (pixel_formats
[i
].sample_buffers
< pf
.sample_buffers
) continue;
1908 if (pixel_formats
[i
].samples
< pf
.samples
) continue;
1910 mode
= &color_modes
[pixel_formats
[i
].color_mode
];
1911 /* If the mode doesn't have alpha, check requested color bits against
1912 bits per pixel instead of the mode's color bits. On Windows, color
1913 bits sometimes exceeds r+g+b (e.g. it's 32 for an R8G8B8A0 pixel format).
1914 If an app depends on that and requests WGL_COLOR_BITS_ARB == 32 and
1915 expects that to match such a pixel format, we need to accommodate that. */
1916 if (mode
->alpha_bits
)
1918 if (mode
->color_bits
< color_bits
)
1923 if (mode
->bits_per_pixel
< color_bits
)
1926 if (mode
->red_bits
< red_bits
|| mode
->green_bits
< green_bits
||
1927 mode
->blue_bits
< blue_bits
|| mode
->alpha_bits
< alpha_bits
)
1929 if (float_color
!= -1 && (!mode
->is_float
!= !float_color
)) continue;
1930 if (srgb
&& (mode
->red_bits
!= 8 || mode
->green_bits
!= 8 || mode
->blue_bits
!= 8 || mode
->is_float
))
1933 if (pixel_formats
[i
].accum_mode
)
1935 mode
= &color_modes
[pixel_formats
[i
].accum_mode
- 1];
1936 if (mode
->color_bits
< accum_bits
|| mode
->red_bits
< accum_red_bits
||
1937 mode
->green_bits
< accum_green_bits
|| mode
->blue_bits
< accum_blue_bits
||
1938 mode
->alpha_bits
< accum_alpha_bits
)
1941 else if (accum_bits
|| accum_red_bits
|| accum_green_bits
|| accum_blue_bits
|| accum_alpha_bits
)
1944 piFormats
[found
++] = i
+ 1;
1945 TRACE("match: pixel format %d %s\n", i
+ 1, debugstr_pf(&pixel_formats
[i
]));
1949 *nNumFormats
= found
;
1955 /**********************************************************************
1956 * macdrv_wglCreatePbufferARB
1958 * WGL_ARB_pbuffer: wglCreatePbufferARB
1960 static struct wgl_pbuffer
*macdrv_wglCreatePbufferARB(HDC hdc
, int iPixelFormat
, int iWidth
, int iHeight
,
1961 const int *piAttribList
)
1963 struct wgl_pbuffer
* pbuffer
;
1965 GLenum internalFormat
= 0;
1968 TRACE("hdc %p iPixelFormat %d iWidth %d iHeight %d piAttribList %p\n",
1969 hdc
, iPixelFormat
, iWidth
, iHeight
, piAttribList
);
1971 if (!is_valid_pixel_format(iPixelFormat
) || !pixel_formats
[iPixelFormat
- 1].pbuffer
)
1973 WARN("invalid pixel format %d\n", iPixelFormat
);
1974 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
1978 pbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pbuffer
));
1979 pbuffer
->format
= iPixelFormat
;
1981 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
1983 int attr
= piAttribList
[0];
1984 int value
= piAttribList
[1];
1988 case WGL_PBUFFER_LARGEST_ARB
:
1989 FIXME("WGL_PBUFFER_LARGEST_ARB: %d; ignoring\n", value
);
1992 case WGL_TEXTURE_FORMAT_ARB
:
1995 case WGL_TEXTURE_RGBA_ARB
:
1996 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGBA_ARB\n");
1997 internalFormat
= GL_RGBA
;
1999 case WGL_TEXTURE_RGB_ARB
:
2000 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_TEXTURE_RGB_ARB\n");
2001 internalFormat
= GL_RGB
;
2003 case WGL_NO_TEXTURE_ARB
:
2004 TRACE("WGL_TEXTURE_FORMAT_ARB: WGL_NO_TEXTURE_ARB\n");
2008 WARN("unknown WGL_TEXTURE_FORMAT_ARB value 0x%x\n", value
);
2009 SetLastError(ERROR_INVALID_DATA
);
2014 case WGL_TEXTURE_TARGET_ARB
:
2018 case WGL_NO_TEXTURE_ARB
:
2019 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_NO_TEXTURE_ARB\n");
2022 case WGL_TEXTURE_CUBE_MAP_ARB
:
2023 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_CUBE_MAP_ARB\n");
2024 target
= GL_TEXTURE_CUBE_MAP
;
2025 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2027 case WGL_TEXTURE_1D_ARB
:
2028 FIXME("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_1D_ARB; not supported\n");
2029 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2031 case WGL_TEXTURE_2D_ARB
:
2032 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_2D_ARB\n");
2033 target
= GL_TEXTURE_2D
;
2035 case WGL_TEXTURE_RECTANGLE_NV
:
2036 TRACE("WGL_TEXTURE_TARGET_ARB: WGL_TEXTURE_RECTANGLE_NV\n");
2037 target
= GL_TEXTURE_RECTANGLE
;
2040 WARN("unknown WGL_TEXTURE_TARGET_ARB value 0x%x\n", value
);
2041 SetLastError(ERROR_INVALID_DATA
);
2046 case WGL_MIPMAP_TEXTURE_ARB
:
2047 TRACE("WGL_MIPMAP_TEXTURE_ARB: %d\n", value
);
2048 pbuffer
->max_level
= 0;
2051 int size
= min(iWidth
, iHeight
) / 2;
2054 pbuffer
->max_level
++;
2061 WARN("unknown attribute 0x%x\n", attr
);
2062 SetLastError(ERROR_INVALID_DATA
);
2067 if (!target
|| !internalFormat
)
2069 pbuffer
->no_texture
= TRUE
;
2070 /* no actual way to turn off ability to texture; use most permissive target */
2071 target
= GL_TEXTURE_RECTANGLE
;
2072 internalFormat
= GL_RGB
;
2075 err
= CGLCreatePBuffer(iWidth
, iHeight
, target
, internalFormat
, pbuffer
->max_level
, &pbuffer
->pbuffer
);
2076 if (err
!= kCGLNoError
)
2078 WARN("CGLCreatePBuffer failed; err %d %s\n", err
, CGLErrorString(err
));
2079 pbuffer
->pbuffer
= NULL
;
2080 if (err
== kCGLBadAlloc
)
2081 SetLastError(ERROR_NO_SYSTEM_RESOURCES
);
2083 SetLastError(ERROR_INVALID_DATA
);
2087 if (!pbuffer
->pbuffer
)
2089 HeapFree(GetProcessHeap(), 0, pbuffer
);
2093 TRACE(" -> %p\n", pbuffer
);
2098 /**********************************************************************
2099 * macdrv_wglDestroyPbufferARB
2101 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2103 static BOOL
macdrv_wglDestroyPbufferARB(struct wgl_pbuffer
*pbuffer
)
2105 TRACE("pbuffer %p\n", pbuffer
);
2106 if (pbuffer
&& pbuffer
->pbuffer
)
2107 CGLReleasePBuffer(pbuffer
->pbuffer
);
2108 HeapFree(GetProcessHeap(), 0, pbuffer
);
2113 /**********************************************************************
2114 * macdrv_wglGetExtensionsStringARB
2116 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2118 static const GLubyte
*macdrv_wglGetExtensionsStringARB(HDC hdc
)
2120 /* FIXME: Since we're given an HDC, this should be device-specific. I.e.
2121 this can be specific to the CGL renderer like we're supposed to do. */
2122 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2123 return (const GLubyte
*)gl_info
.wglExtensions
;
2127 /**********************************************************************
2128 * macdrv_wglGetExtensionsStringEXT
2130 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
2132 static const GLubyte
*macdrv_wglGetExtensionsStringEXT(void)
2134 TRACE("returning \"%s\"\n", gl_info
.wglExtensions
);
2135 return (const GLubyte
*)gl_info
.wglExtensions
;
2139 /**********************************************************************
2140 * macdrv_wglGetPbufferDCARB
2142 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2144 static HDC
macdrv_wglGetPbufferDCARB(struct wgl_pbuffer
*pbuffer
)
2147 struct wgl_pbuffer
*prev
;
2149 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2152 EnterCriticalSection(&dc_pbuffers_section
);
2153 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2156 CGLReleasePBuffer(prev
->pbuffer
);
2157 HeapFree(GetProcessHeap(), 0, prev
);
2159 CFDictionarySetValue(dc_pbuffers
, hdc
, pbuffer
);
2160 LeaveCriticalSection(&dc_pbuffers_section
);
2162 TRACE("pbuffer %p -> hdc %p\n", pbuffer
, hdc
);
2167 /**********************************************************************
2168 * macdrv_wglGetPixelFormatAttribivARB
2170 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2172 static BOOL
macdrv_wglGetPixelFormatAttribivARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2173 UINT nAttributes
, const int *piAttributes
, int *piValues
)
2175 const pixel_format
*pf
;
2178 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p piValues %p\n",
2179 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, piValues
);
2181 if (!nAttributes
) return GL_TRUE
;
2183 if (nAttributes
== 1 && piAttributes
[0] == WGL_NUMBER_PIXEL_FORMATS_ARB
)
2185 piValues
[0] = nb_formats
;
2186 TRACE("%s\n", debugstr_attrib(piAttributes
[0], piValues
[0]));
2190 pf
= get_pixel_format(iPixelFormat
, TRUE
/* non-displayable */);
2193 WARN("invalid pixel format %d\n", iPixelFormat
);
2194 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2198 for (i
= 0; i
< nAttributes
; ++i
)
2200 switch (piAttributes
[i
])
2202 case WGL_NUMBER_PIXEL_FORMATS_ARB
:
2203 piValues
[i
] = nb_formats
;
2206 case WGL_DRAW_TO_WINDOW_ARB
:
2207 piValues
[i
] = pf
->window
? GL_TRUE
: GL_FALSE
;
2210 case WGL_DRAW_TO_BITMAP_ARB
:
2211 piValues
[i
] = GL_FALSE
;
2214 case WGL_ACCELERATION_ARB
:
2215 if (iLayerPlane
) goto invalid_layer
;
2216 if (pf
->accelerated
)
2217 piValues
[i
] = WGL_FULL_ACCELERATION_ARB
;
2219 piValues
[i
] = WGL_NO_ACCELERATION_ARB
;
2222 case WGL_NEED_PALETTE_ARB
:
2223 case WGL_NEED_SYSTEM_PALETTE_ARB
:
2224 case WGL_SWAP_LAYER_BUFFERS_ARB
:
2225 piValues
[i
] = GL_FALSE
;
2228 case WGL_SWAP_METHOD_ARB
:
2229 if (pf
->double_buffer
&& pf
->backing_store
)
2230 piValues
[i
] = WGL_SWAP_COPY_ARB
;
2232 piValues
[i
] = WGL_SWAP_UNDEFINED_ARB
;
2235 case WGL_NUMBER_OVERLAYS_ARB
:
2236 case WGL_NUMBER_UNDERLAYS_ARB
:
2240 case WGL_TRANSPARENT_ARB
:
2241 if (iLayerPlane
) goto invalid_layer
;
2242 piValues
[i
] = GL_FALSE
;
2245 case WGL_TRANSPARENT_RED_VALUE_ARB
:
2246 case WGL_TRANSPARENT_GREEN_VALUE_ARB
:
2247 case WGL_TRANSPARENT_BLUE_VALUE_ARB
:
2248 case WGL_TRANSPARENT_ALPHA_VALUE_ARB
:
2249 case WGL_TRANSPARENT_INDEX_VALUE_ARB
:
2250 if (iLayerPlane
) goto invalid_layer
;
2254 case WGL_SHARE_DEPTH_ARB
:
2255 case WGL_SHARE_STENCIL_ARB
:
2256 case WGL_SHARE_ACCUM_ARB
:
2257 if (iLayerPlane
) goto invalid_layer
;
2258 piValues
[i
] = GL_TRUE
;
2261 case WGL_SUPPORT_GDI_ARB
:
2262 if (iLayerPlane
) goto invalid_layer
;
2263 piValues
[i
] = GL_FALSE
;
2266 case WGL_SUPPORT_OPENGL_ARB
:
2267 if (iLayerPlane
) goto invalid_layer
;
2268 piValues
[i
] = GL_TRUE
;
2271 case WGL_DOUBLE_BUFFER_ARB
:
2272 if (iLayerPlane
) goto invalid_layer
;
2273 piValues
[i
] = pf
->double_buffer
? GL_TRUE
: GL_FALSE
;
2276 case WGL_STEREO_ARB
:
2277 if (iLayerPlane
) goto invalid_layer
;
2278 piValues
[i
] = pf
->stereo
? GL_TRUE
: GL_FALSE
;
2281 case WGL_PIXEL_TYPE_ARB
:
2282 if (iLayerPlane
) goto invalid_layer
;
2283 if (color_modes
[pf
->color_mode
].is_float
)
2284 piValues
[i
] = WGL_TYPE_RGBA_FLOAT_ARB
;
2286 piValues
[i
] = WGL_TYPE_RGBA_ARB
;
2287 /* WGL_EXT_pixel_format_packed_float may be supported, which should in theory
2288 make another pixel type available: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT.
2289 However, Mac contexts don't support rendering to unsigned floating-point
2290 formats, even when GL_EXT_packed_float is supported. */
2293 case WGL_COLOR_BITS_ARB
:
2294 if (iLayerPlane
) goto invalid_layer
;
2295 /* If the mode doesn't have alpha, return bits per pixel instead
2296 of color bits. On Windows, color bits sometimes exceeds r+g+b
2297 (e.g. it's 32 for an R8G8B8A0 pixel format). If an app depends
2298 on that and expects that WGL_COLOR_BITS_ARB >= 32 for such a
2299 pixel format, we need to accommodate that. */
2300 if (color_modes
[pf
->color_mode
].alpha_bits
)
2301 piValues
[i
] = color_modes
[pf
->color_mode
].color_bits
;
2303 piValues
[i
] = color_modes
[pf
->color_mode
].bits_per_pixel
;
2306 case WGL_RED_BITS_ARB
:
2307 if (iLayerPlane
) goto invalid_layer
;
2308 piValues
[i
] = color_modes
[pf
->color_mode
].red_bits
;
2311 case WGL_RED_SHIFT_ARB
:
2312 if (iLayerPlane
) goto invalid_layer
;
2313 piValues
[i
] = color_modes
[pf
->color_mode
].red_shift
;
2316 case WGL_GREEN_BITS_ARB
:
2317 if (iLayerPlane
) goto invalid_layer
;
2318 piValues
[i
] = color_modes
[pf
->color_mode
].green_bits
;
2321 case WGL_GREEN_SHIFT_ARB
:
2322 if (iLayerPlane
) goto invalid_layer
;
2323 piValues
[i
] = color_modes
[pf
->color_mode
].green_shift
;
2326 case WGL_BLUE_BITS_ARB
:
2327 if (iLayerPlane
) goto invalid_layer
;
2328 piValues
[i
] = color_modes
[pf
->color_mode
].blue_bits
;
2331 case WGL_BLUE_SHIFT_ARB
:
2332 if (iLayerPlane
) goto invalid_layer
;
2333 piValues
[i
] = color_modes
[pf
->color_mode
].blue_shift
;
2336 case WGL_ALPHA_BITS_ARB
:
2337 if (iLayerPlane
) goto invalid_layer
;
2338 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_bits
;
2341 case WGL_ALPHA_SHIFT_ARB
:
2342 if (iLayerPlane
) goto invalid_layer
;
2343 piValues
[i
] = color_modes
[pf
->color_mode
].alpha_shift
;
2346 case WGL_ACCUM_BITS_ARB
:
2347 if (iLayerPlane
) goto invalid_layer
;
2349 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].color_bits
;
2354 case WGL_ACCUM_RED_BITS_ARB
:
2355 if (iLayerPlane
) goto invalid_layer
;
2357 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].red_bits
;
2362 case WGL_ACCUM_GREEN_BITS_ARB
:
2363 if (iLayerPlane
) goto invalid_layer
;
2365 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].green_bits
;
2370 case WGL_ACCUM_BLUE_BITS_ARB
:
2371 if (iLayerPlane
) goto invalid_layer
;
2373 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].blue_bits
;
2378 case WGL_ACCUM_ALPHA_BITS_ARB
:
2379 if (iLayerPlane
) goto invalid_layer
;
2381 piValues
[i
] = color_modes
[pf
->accum_mode
- 1].alpha_bits
;
2386 case WGL_DEPTH_BITS_ARB
:
2387 if (iLayerPlane
) goto invalid_layer
;
2388 piValues
[i
] = pf
->depth_bits
;
2391 case WGL_STENCIL_BITS_ARB
:
2392 if (iLayerPlane
) goto invalid_layer
;
2393 piValues
[i
] = pf
->stencil_bits
;
2396 case WGL_AUX_BUFFERS_ARB
:
2397 if (iLayerPlane
) goto invalid_layer
;
2398 piValues
[i
] = pf
->aux_buffers
;
2401 case WGL_SAMPLE_BUFFERS_ARB
:
2402 if (iLayerPlane
) goto invalid_layer
;
2403 piValues
[i
] = pf
->sample_buffers
;
2406 case WGL_SAMPLES_ARB
:
2407 if (iLayerPlane
) goto invalid_layer
;
2408 piValues
[i
] = pf
->samples
;
2411 case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB
: /* a.k.a. WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT */
2412 if (iLayerPlane
) goto invalid_layer
;
2413 /* sRGB is only supported for 8-bit integer color components */
2414 if (color_modes
[pf
->color_mode
].red_bits
== 8 &&
2415 color_modes
[pf
->color_mode
].green_bits
== 8 &&
2416 color_modes
[pf
->color_mode
].blue_bits
== 8 &&
2417 !color_modes
[pf
->color_mode
].is_float
)
2418 piValues
[i
] = GL_TRUE
;
2420 piValues
[i
] = GL_FALSE
;
2423 case WGL_DRAW_TO_PBUFFER_ARB
:
2424 case WGL_BIND_TO_TEXTURE_RGB_ARB
:
2425 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV
:
2426 piValues
[i
] = pf
->pbuffer
? GL_TRUE
: GL_FALSE
;
2429 case WGL_BIND_TO_TEXTURE_RGBA_ARB
:
2430 case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV
:
2431 piValues
[i
] = (pf
->pbuffer
&& color_modes
[pf
->color_mode
].alpha_bits
) ? GL_TRUE
: GL_FALSE
;
2434 case WGL_MAX_PBUFFER_WIDTH_ARB
:
2435 piValues
[i
] = gl_info
.max_viewport_dims
[0];
2438 case WGL_MAX_PBUFFER_HEIGHT_ARB
:
2439 piValues
[i
] = gl_info
.max_viewport_dims
[1];
2442 case WGL_MAX_PBUFFER_PIXELS_ARB
:
2443 piValues
[i
] = gl_info
.max_viewport_dims
[0] * gl_info
.max_viewport_dims
[1];
2447 WARN("invalid attribute %x\n", piAttributes
[i
]);
2451 TRACE("%s\n", debugstr_attrib(piAttributes
[i
], piValues
[i
]));
2457 FIXME("unsupported iLayerPlane %d\n", iLayerPlane
);
2462 /**********************************************************************
2463 * macdrv_wglGetPixelFormatAttribfvARB
2465 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2467 static BOOL
macdrv_wglGetPixelFormatAttribfvARB(HDC hdc
, int iPixelFormat
, int iLayerPlane
,
2468 UINT nAttributes
, const int *piAttributes
, FLOAT
*pfValues
)
2473 TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
2474 hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, pfValues
);
2476 /* Allocate a temporary array to store integer values */
2477 attr
= HeapAlloc(GetProcessHeap(), 0, nAttributes
* sizeof(int));
2480 ERR("couldn't allocate %d array\n", nAttributes
);
2484 /* Piggy-back on wglGetPixelFormatAttribivARB */
2485 ret
= macdrv_wglGetPixelFormatAttribivARB(hdc
, iPixelFormat
, iLayerPlane
, nAttributes
, piAttributes
, attr
);
2490 /* Convert integer values to float. Should also check for attributes
2491 that can give decimal values here */
2492 for (i
= 0; i
< nAttributes
; i
++)
2493 pfValues
[i
] = attr
[i
];
2496 HeapFree(GetProcessHeap(), 0, attr
);
2501 /**********************************************************************
2502 * macdrv_wglGetSwapIntervalEXT
2504 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
2506 static int macdrv_wglGetSwapIntervalEXT(void)
2508 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2514 err
= CGLGetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2515 if (err
!= kCGLNoError
)
2517 WARN("CGLGetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2518 err
, CGLErrorString(err
));
2526 /***********************************************************************
2527 * macdrv_wglMakeContextCurrentARB
2529 * WGL_ARB_make_current_read: wglMakeContextCurrentARB
2531 * This is not supported directly by OpenGL on the Mac. We emulate it
2532 * by hooking into glReadPixels, glCopyPixels, and glCopyColorTable to
2533 * temporarily swap the drawable. This follows the technique used in
2534 * the implementation of Mesa GLX for Apple.
2536 static BOOL
macdrv_wglMakeContextCurrentARB(HDC draw_hdc
, HDC read_hdc
, struct wgl_context
*context
)
2538 struct macdrv_win_data
*data
;
2541 TRACE("draw_hdc %p read_hdc %p context %p/%p/%p\n", draw_hdc
, read_hdc
, context
,
2542 (context
? context
->context
: NULL
), (context
? context
->cglcontext
: NULL
));
2546 macdrv_make_context_current(NULL
, NULL
);
2547 NtCurrentTeb()->glContext
= NULL
;
2551 if ((hwnd
= WindowFromDC(draw_hdc
)))
2553 if (!(data
= get_win_data(hwnd
)))
2555 FIXME("draw DC for window %p of other process: not implemented\n", hwnd
);
2559 if (!data
->pixel_format
)
2561 WARN("no pixel format set\n");
2562 release_win_data(data
);
2563 SetLastError(ERROR_INVALID_HANDLE
);
2566 if (context
->format
!= data
->pixel_format
)
2568 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, data
->pixel_format
, context
, context
->format
);
2569 release_win_data(data
);
2570 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2574 context
->draw_view
= data
->gl_view
;
2575 context
->draw_pbuffer
= NULL
;
2576 release_win_data(data
);
2580 struct wgl_pbuffer
*pbuffer
;
2582 EnterCriticalSection(&dc_pbuffers_section
);
2583 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, draw_hdc
);
2586 if (context
->format
!= pbuffer
->format
)
2588 WARN("mismatched pixel format draw_hdc %p %u context %p %u\n", draw_hdc
, pbuffer
->format
, context
, context
->format
);
2589 LeaveCriticalSection(&dc_pbuffers_section
);
2590 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
2596 WARN("no window or pbuffer for DC\n");
2597 LeaveCriticalSection(&dc_pbuffers_section
);
2598 SetLastError(ERROR_INVALID_HANDLE
);
2602 context
->draw_view
= NULL
;
2603 context
->draw_pbuffer
= pbuffer
;
2604 LeaveCriticalSection(&dc_pbuffers_section
);
2607 context
->read_view
= NULL
;
2608 context
->read_pbuffer
= NULL
;
2609 if (read_hdc
&& read_hdc
!= draw_hdc
)
2611 if ((hwnd
= WindowFromDC(read_hdc
)))
2613 if ((data
= get_win_data(hwnd
)))
2615 if (data
->gl_view
!= context
->draw_view
)
2616 context
->read_view
= data
->gl_view
;
2617 release_win_data(data
);
2622 EnterCriticalSection(&dc_pbuffers_section
);
2623 context
->read_pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, read_hdc
);
2624 LeaveCriticalSection(&dc_pbuffers_section
);
2628 TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n",
2629 context
->draw_view
, context
->draw_pbuffer
, context
->read_view
, context
->read_pbuffer
, context
->format
);
2631 make_context_current(context
, FALSE
);
2632 context
->has_been_current
= TRUE
;
2633 NtCurrentTeb()->glContext
= context
;
2639 /**********************************************************************
2640 * macdrv_wglQueryPbufferARB
2642 * WGL_ARB_pbuffer: wglQueryPbufferARB
2644 static BOOL
macdrv_wglQueryPbufferARB(struct wgl_pbuffer
*pbuffer
, int iAttribute
, int *piValue
)
2650 GLenum internalFormat
;
2653 TRACE("pbuffer %p iAttribute 0x%x piValue %p\n", pbuffer
, iAttribute
, piValue
);
2655 err
= CGLDescribePBuffer(pbuffer
->pbuffer
, &width
, &height
, &target
, &internalFormat
, &mipmap
);
2656 if (err
!= kCGLNoError
)
2658 WARN("CGLDescribePBuffer failed; error %d %s\n", err
, CGLErrorString(err
));
2659 SetLastError(ERROR_INVALID_HANDLE
);
2665 case WGL_PBUFFER_WIDTH_ARB
:
2668 case WGL_PBUFFER_HEIGHT_ARB
:
2671 case WGL_PBUFFER_LOST_ARB
:
2672 /* Mac PBuffers can't be lost */
2673 *piValue
= GL_FALSE
;
2675 case WGL_TEXTURE_FORMAT_ARB
:
2676 if (pbuffer
->no_texture
)
2677 *piValue
= WGL_NO_TEXTURE_ARB
;
2678 else switch (internalFormat
)
2681 *piValue
= WGL_TEXTURE_RGBA_ARB
;
2685 *piValue
= WGL_TEXTURE_RGB_ARB
;
2689 case WGL_TEXTURE_TARGET_ARB
:
2690 if (pbuffer
->no_texture
)
2691 *piValue
= WGL_NO_TEXTURE_ARB
;
2692 else switch (target
)
2694 case GL_TEXTURE_CUBE_MAP
:
2695 *piValue
= WGL_TEXTURE_CUBE_MAP_ARB
;
2698 *piValue
= WGL_TEXTURE_2D_ARB
;
2700 case GL_TEXTURE_RECTANGLE
:
2702 *piValue
= WGL_TEXTURE_RECTANGLE_NV
;
2706 case WGL_MIPMAP_TEXTURE_ARB
:
2707 *piValue
= (pbuffer
->max_level
> 0);
2709 case WGL_MIPMAP_LEVEL_ARB
:
2710 *piValue
= pbuffer
->level
;
2712 case WGL_CUBE_MAP_FACE_ARB
:
2713 switch (pbuffer
->face
)
2715 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
2717 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
;
2719 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
2720 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
;
2722 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
2723 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
;
2725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
2726 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
;
2728 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
2729 *piValue
= WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
;
2731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
2732 *piValue
= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
;
2737 WARN("invalid attribute 0x%x\n", iAttribute
);
2738 SetLastError(ERROR_INVALID_DATA
);
2746 /**********************************************************************
2747 * macdrv_wglReleasePbufferDCARB
2749 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2751 static int macdrv_wglReleasePbufferDCARB(struct wgl_pbuffer
*pbuffer
, HDC hdc
)
2753 struct wgl_pbuffer
*prev
;
2755 TRACE("pbuffer %p hdc %p\n", pbuffer
, hdc
);
2757 EnterCriticalSection(&dc_pbuffers_section
);
2759 prev
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
2762 if (prev
!= pbuffer
)
2763 FIXME("hdc %p isn't associated with pbuffer %p\n", hdc
, pbuffer
);
2764 CGLReleasePBuffer(prev
->pbuffer
);
2765 HeapFree(GetProcessHeap(), 0, prev
);
2766 CFDictionaryRemoveValue(dc_pbuffers
, hdc
);
2770 LeaveCriticalSection(&dc_pbuffers_section
);
2772 return hdc
&& DeleteDC(hdc
);
2776 /**********************************************************************
2777 * macdrv_wglReleaseTexImageARB
2779 * WGL_ARB_render_texture: wglReleaseTexImageARB
2781 static BOOL
macdrv_wglReleaseTexImageARB(struct wgl_pbuffer
*pbuffer
, int iBuffer
)
2783 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2786 TRACE("pbuffer %p iBuffer 0x%x; stub!\n", pbuffer
, iBuffer
);
2788 if (pbuffer
->no_texture
)
2790 SetLastError(ERROR_INVALID_OPERATION
);
2794 err
= CGLTexImagePBuffer(context
->cglcontext
, pbuffer
->pbuffer
, GL_NONE
);
2795 if (err
!= kCGLNoError
)
2797 WARN("CGLTexImagePBuffer failed with err %d %s\n", err
, CGLErrorString(err
));
2798 SetLastError(ERROR_INVALID_OPERATION
);
2806 /**********************************************************************
2807 * macdrv_wglSetPbufferAttribARB
2809 * WGL_ARB_render_texture: wglSetPbufferAttribARB
2811 static BOOL
macdrv_wglSetPbufferAttribARB(struct wgl_pbuffer
*pbuffer
, const int *piAttribList
)
2813 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2815 TRACE("pbuffer %p piAttribList %p\n", pbuffer
, piAttribList
);
2817 for ( ; piAttribList
&& *piAttribList
; piAttribList
+= 2)
2819 int attr
= piAttribList
[0];
2820 int value
= piAttribList
[1];
2823 case WGL_MIPMAP_LEVEL_ARB
:
2824 TRACE("WGL_MIPMAP_LEVEL_ARB: %d\n", value
);
2825 pbuffer
->level
= value
;
2827 case WGL_CUBE_MAP_FACE_ARB
:
2830 case WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
2831 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\n");
2832 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
2834 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
2835 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\n");
2836 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_X
;
2838 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
2839 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\n");
2840 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Y
;
2842 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
2843 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\n");
2844 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
;
2846 case WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
2847 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\n");
2848 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_POSITIVE_Z
;
2850 case WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
2851 TRACE("WGL_CUBE_MAP_FACE_ARB: WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\n");
2852 pbuffer
->face
= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
;
2855 WARN("unknown WGL_CUBE_MAP_FACE_ARB value 0x%x\n", value
);
2856 SetLastError(ERROR_INVALID_DATA
);
2861 WARN("invalide attribute 0x%x\n", attr
);
2862 SetLastError(ERROR_INVALID_DATA
);
2867 if (context
&& context
->draw_pbuffer
== pbuffer
)
2868 make_context_current(context
, FALSE
);
2874 /**********************************************************************
2875 * macdrv_wglSetPixelFormatWINE
2877 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
2879 static BOOL
macdrv_wglSetPixelFormatWINE(HDC hdc
, int fmt
)
2881 return set_pixel_format(hdc
, fmt
, TRUE
);
2885 /**********************************************************************
2886 * macdrv_wglSwapIntervalEXT
2888 * WGL_EXT_swap_control: wglSwapIntervalEXT
2890 static BOOL
macdrv_wglSwapIntervalEXT(int interval
)
2892 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
2896 TRACE("interval %d\n", interval
);
2900 SetLastError(ERROR_INVALID_DATA
);
2904 if (!pixel_formats
[context
->format
- 1].double_buffer
)
2906 else if (interval
> 1)
2910 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&value
);
2911 if (err
!= kCGLNoError
)
2913 WARN("CGLSetParameter(kCGLCPSwapInterval) failed; error %d %s\n",
2914 err
, CGLErrorString(err
));
2915 SetLastError(ERROR_GEN_FAILURE
);
2923 static void register_extension(const char *ext
)
2925 if (gl_info
.wglExtensions
[0])
2926 strcat(gl_info
.wglExtensions
, " ");
2927 strcat(gl_info
.wglExtensions
, ext
);
2929 TRACE("'%s'\n", ext
);
2932 static void load_extensions(void)
2937 register_extension("WGL_ARB_extensions_string");
2938 opengl_funcs
.ext
.p_wglGetExtensionsStringARB
= macdrv_wglGetExtensionsStringARB
;
2940 register_extension("WGL_ARB_make_current_read");
2941 opengl_funcs
.ext
.p_wglGetCurrentReadDCARB
= (void *)1; /* never called */
2942 opengl_funcs
.ext
.p_wglMakeContextCurrentARB
= macdrv_wglMakeContextCurrentARB
;
2944 register_extension("WGL_ARB_pixel_format");
2945 opengl_funcs
.ext
.p_wglChoosePixelFormatARB
= macdrv_wglChoosePixelFormatARB
;
2946 opengl_funcs
.ext
.p_wglGetPixelFormatAttribfvARB
= macdrv_wglGetPixelFormatAttribfvARB
;
2947 opengl_funcs
.ext
.p_wglGetPixelFormatAttribivARB
= macdrv_wglGetPixelFormatAttribivARB
;
2949 if (gluCheckExtension((GLubyte
*)"GL_ARB_color_buffer_float", (GLubyte
*)gl_info
.glExtensions
))
2951 register_extension("WGL_ARB_pixel_format_float");
2952 register_extension("WGL_ATI_pixel_format_float");
2955 if (gluCheckExtension((GLubyte
*)"GL_ARB_multisample", (GLubyte
*)gl_info
.glExtensions
))
2956 register_extension("WGL_ARB_multisample");
2958 if (gluCheckExtension((GLubyte
*)"GL_ARB_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
2959 register_extension("WGL_ARB_framebuffer_sRGB");
2961 if (gluCheckExtension((GLubyte
*)"GL_APPLE_pixel_buffer", (GLubyte
*)gl_info
.glExtensions
))
2963 register_extension("WGL_ARB_pbuffer");
2964 opengl_funcs
.ext
.p_wglCreatePbufferARB
= macdrv_wglCreatePbufferARB
;
2965 opengl_funcs
.ext
.p_wglDestroyPbufferARB
= macdrv_wglDestroyPbufferARB
;
2966 opengl_funcs
.ext
.p_wglGetPbufferDCARB
= macdrv_wglGetPbufferDCARB
;
2967 opengl_funcs
.ext
.p_wglQueryPbufferARB
= macdrv_wglQueryPbufferARB
;
2968 opengl_funcs
.ext
.p_wglReleasePbufferDCARB
= macdrv_wglReleasePbufferDCARB
;
2970 register_extension("WGL_ARB_render_texture");
2971 opengl_funcs
.ext
.p_wglBindTexImageARB
= macdrv_wglBindTexImageARB
;
2972 opengl_funcs
.ext
.p_wglReleaseTexImageARB
= macdrv_wglReleaseTexImageARB
;
2973 opengl_funcs
.ext
.p_wglSetPbufferAttribARB
= macdrv_wglSetPbufferAttribARB
;
2975 if (gluCheckExtension((GLubyte
*)"GL_ARB_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
) ||
2976 gluCheckExtension((GLubyte
*)"GL_EXT_texture_rectangle", (GLubyte
*)gl_info
.glExtensions
))
2977 register_extension("WGL_NV_render_texture_rectangle");
2981 WGL_ARB_create_context: wglCreateContextAttribsARB
2982 WGL_ARB_create_context_profile
2988 register_extension("WGL_EXT_extensions_string");
2989 opengl_funcs
.ext
.p_wglGetExtensionsStringEXT
= macdrv_wglGetExtensionsStringEXT
;
2993 register_extension("WGL_EXT_swap_control");
2994 opengl_funcs
.ext
.p_wglSwapIntervalEXT
= macdrv_wglSwapIntervalEXT
;
2995 opengl_funcs
.ext
.p_wglGetSwapIntervalEXT
= macdrv_wglGetSwapIntervalEXT
;
2998 /* Presumably identical to [W]GL_ARB_framebuffer_sRGB, above, but clients may
2999 check for either, so register them separately. */
3000 if (gluCheckExtension((GLubyte
*)"GL_EXT_framebuffer_sRGB", (GLubyte
*)gl_info
.glExtensions
))
3001 register_extension("WGL_EXT_framebuffer_sRGB");
3003 if (gluCheckExtension((GLubyte
*)"GL_EXT_packed_float", (GLubyte
*)gl_info
.glExtensions
))
3004 register_extension("WGL_EXT_pixel_format_packed_float");
3007 * WINE-specific WGL Extensions
3010 /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
3011 * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
3013 register_extension("WGL_WINE_pixel_format_passthrough");
3014 opengl_funcs
.ext
.p_wglSetPixelFormatWINE
= macdrv_wglSetPixelFormatWINE
;
3018 static BOOL
init_opengl(void)
3020 static int init_done
;
3024 if (init_done
) return (opengl_handle
!= NULL
);
3029 dc_pbuffers
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
3032 WARN("CFDictionaryCreateMutable failed\n");
3036 opengl_handle
= wine_dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY
|RTLD_LOCAL
|RTLD_NOLOAD
, buffer
, sizeof(buffer
));
3039 ERR("Failed to load OpenGL: %s\n", buffer
);
3040 ERR("OpenGL support is disabled.\n");
3044 for (i
= 0; i
< sizeof(opengl_func_names
)/sizeof(opengl_func_names
[0]); i
++)
3046 if (!(((void **)&opengl_funcs
.gl
)[i
] = wine_dlsym(opengl_handle
, opengl_func_names
[i
], NULL
, 0)))
3048 ERR("%s not found in OpenGL, disabling.\n", opengl_func_names
[i
]);
3053 /* redirect some standard OpenGL functions */
3054 #define REDIRECT(func) \
3055 do { p##func = opengl_funcs.gl.p_##func; opengl_funcs.gl.p_##func = macdrv_##func; } while(0)
3056 REDIRECT(glCopyPixels
);
3057 REDIRECT(glReadPixels
);
3058 REDIRECT(glViewport
);
3059 if (skip_single_buffer_flushes
)
3063 /* redirect some OpenGL extension functions */
3064 #define REDIRECT(func) \
3065 do { if (opengl_funcs.ext.p_##func) { p##func = opengl_funcs.ext.p_##func; opengl_funcs.ext.p_##func = macdrv_##func; } } while(0)
3066 REDIRECT(glCopyColorTable
);
3069 if (!init_gl_info())
3072 if (gluCheckExtension((GLubyte
*)"GL_APPLE_flush_render", (GLubyte
*)gl_info
.glExtensions
))
3073 pglFlushRenderAPPLE
= wine_dlsym(opengl_handle
, "glFlushRenderAPPLE", NULL
, 0);
3076 if (!init_pixel_formats())
3082 wine_dlclose(opengl_handle
, NULL
, 0);
3083 opengl_handle
= NULL
;
3088 /***********************************************************************
3091 * Synchronize the Mac GL view position with the Windows child window
3094 void sync_gl_view(struct macdrv_win_data
*data
)
3098 TRACE("hwnd %p gl_view %p\n", data
->hwnd
, data
->gl_view
);
3100 if (!data
->gl_view
) return;
3102 if (get_gl_view_window_rect(data
, NULL
, &rect
) && memcmp(&data
->gl_rect
, &rect
, sizeof(rect
)))
3104 TRACE("Setting GL view %p frame to %s\n", data
->gl_view
, wine_dbgstr_rect(&rect
));
3105 macdrv_set_view_window_and_frame(data
->gl_view
, NULL
, cgrect_from_rect(rect
));
3106 data
->gl_rect
= rect
;
3111 static int get_dc_pixel_format(HDC hdc
)
3116 if ((hwnd
= WindowFromDC(hdc
)))
3118 struct macdrv_win_data
*data
;
3120 if (!(data
= get_win_data(hwnd
)))
3122 FIXME("DC for window %p of other process: not implemented\n", hwnd
);
3126 format
= data
->pixel_format
;
3127 release_win_data(data
);
3131 struct wgl_pbuffer
*pbuffer
;
3133 EnterCriticalSection(&dc_pbuffers_section
);
3134 pbuffer
= (struct wgl_pbuffer
*)CFDictionaryGetValue(dc_pbuffers
, hdc
);
3136 format
= pbuffer
->format
;
3139 WARN("no window or pbuffer for DC %p\n", hdc
);
3142 LeaveCriticalSection(&dc_pbuffers_section
);
3149 /**********************************************************************
3152 static BOOL
create_context(struct wgl_context
*context
, CGLContextObj share
)
3154 const pixel_format
*pf
;
3155 CGLPixelFormatAttribute attribs
[64];
3157 CGLPixelFormatObj pix
;
3158 GLint virtualScreens
;
3162 pf
= get_pixel_format(context
->format
, TRUE
/* non-displayable */);
3165 ERR("Invalid pixel format %d, expect problems!\n", context
->format
);
3166 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3170 attribs
[n
++] = kCGLPFAMinimumPolicy
;
3171 attribs
[n
++] = kCGLPFAClosestPolicy
;
3173 if (pf
->accelerated
)
3175 attribs
[n
++] = kCGLPFAAccelerated
;
3176 attribs
[n
++] = kCGLPFANoRecovery
;
3180 attribs
[n
++] = kCGLPFARendererID
;
3181 attribs
[n
++] = kCGLRendererGenericFloatID
;
3184 if (pf
->double_buffer
)
3185 attribs
[n
++] = kCGLPFADoubleBuffer
;
3187 attribs
[n
++] = kCGLPFAAuxBuffers
;
3188 attribs
[n
++] = pf
->aux_buffers
;
3190 attribs
[n
++] = kCGLPFAColorSize
;
3191 attribs
[n
++] = color_modes
[pf
->color_mode
].color_bits
;
3192 attribs
[n
++] = kCGLPFAAlphaSize
;
3193 attribs
[n
++] = color_modes
[pf
->color_mode
].alpha_bits
;
3194 if (color_modes
[pf
->color_mode
].is_float
)
3195 attribs
[n
++] = kCGLPFAColorFloat
;
3197 attribs
[n
++] = kCGLPFADepthSize
;
3198 attribs
[n
++] = pf
->depth_bits
;
3200 attribs
[n
++] = kCGLPFAStencilSize
;
3201 attribs
[n
++] = pf
->stencil_bits
;
3204 attribs
[n
++] = kCGLPFAStereo
;
3208 attribs
[n
++] = kCGLPFAAccumSize
;
3209 attribs
[n
++] = color_modes
[pf
->accum_mode
- 1].color_bits
;
3213 attribs
[n
++] = kCGLPFAWindow
;
3215 attribs
[n
++] = kCGLPFAPBuffer
;
3217 if (pf
->sample_buffers
&& pf
->samples
)
3219 attribs
[n
++] = kCGLPFASampleBuffers
;
3220 attribs
[n
++] = pf
->sample_buffers
;
3221 attribs
[n
++] = kCGLPFASamples
;
3222 attribs
[n
++] = pf
->samples
;
3225 if (pf
->backing_store
)
3226 attribs
[n
++] = kCGLPFABackingStore
;
3230 err
= CGLChoosePixelFormat(attribs
, &pix
, &virtualScreens
);
3231 if (err
!= kCGLNoError
|| !pix
)
3233 WARN("CGLChoosePixelFormat() failed with error %d %s\n", err
, CGLErrorString(err
));
3237 err
= CGLCreateContext(pix
, share
, &context
->cglcontext
);
3238 CGLReleasePixelFormat(pix
);
3239 if (err
!= kCGLNoError
|| !context
->cglcontext
)
3241 context
->cglcontext
= NULL
;
3242 WARN("CGLCreateContext() failed with error %d %s\n", err
, CGLErrorString(err
));
3246 /* According to the WGL_EXT_swap_control docs, the default swap interval for
3247 a context is 1. CGL contexts default to 0, so we need to set it. This
3248 only make sense for double-buffered contexts, though. In theory, for
3249 single-buffered contexts, there's no such thing as a swap. But OS X
3250 will synchronize flushes of single-buffered contexts if this is set. */
3251 if (pf
->double_buffer
&& allow_vsync
)
3255 err
= CGLSetParameter(context
->cglcontext
, kCGLCPSwapInterval
, (GLint
*)&swap_interval
);
3256 if (err
!= kCGLNoError
)
3257 WARN("CGLSetParameter(kCGLCPSwapInterval) failed with error %d %s; leaving un-vsynced\n", err
, CGLErrorString(err
));
3259 context
->context
= macdrv_create_opengl_context(context
->cglcontext
);
3260 CGLReleaseContext(context
->cglcontext
);
3261 if (!context
->context
)
3263 WARN("macdrv_create_opengl_context() failed\n");
3267 TRACE("created context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3273 /**********************************************************************
3274 * macdrv_wglDescribePixelFormat
3276 int macdrv_wglDescribePixelFormat(HDC hdc
, int fmt
, UINT size
, PIXELFORMATDESCRIPTOR
*descr
)
3278 int ret
= nb_formats
;
3279 const pixel_format
*pf
;
3280 const struct color_mode
*mode
;
3282 TRACE("hdc %p fmt %d size %u descr %p\n", hdc
, fmt
, size
, descr
);
3284 if (fmt
<= 0 || fmt
> ret
) return ret
;
3285 if (size
< sizeof(*descr
)) return 0;
3287 pf
= &pixel_formats
[fmt
- 1];
3289 memset(descr
, 0, sizeof(*descr
));
3290 descr
->nSize
= sizeof(*descr
);
3291 descr
->nVersion
= 1;
3293 descr
->dwFlags
= PFD_SUPPORT_OPENGL
;
3294 if (pf
->window
) descr
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
3295 if (!pf
->accelerated
) descr
->dwFlags
|= PFD_GENERIC_FORMAT
;
3296 if (pf
->double_buffer
) descr
->dwFlags
|= PFD_DOUBLEBUFFER
;
3297 if (pf
->stereo
) descr
->dwFlags
|= PFD_STEREO
;
3298 if (pf
->backing_store
) descr
->dwFlags
|= PFD_SWAP_COPY
;
3300 descr
->iPixelType
= PFD_TYPE_RGBA
;
3302 mode
= &color_modes
[pf
->color_mode
];
3303 /* If the mode doesn't have alpha, return bits per pixel instead of color bits.
3304 On Windows, color bits sometimes exceeds r+g+b (e.g. it's 32 for an
3305 R8G8B8A0 pixel format). If an app depends on that and expects that
3306 cColorBits >= 32 for such a pixel format, we need to accommodate that. */
3307 if (mode
->alpha_bits
)
3308 descr
->cColorBits
= mode
->color_bits
;
3310 descr
->cColorBits
= mode
->bits_per_pixel
;
3311 descr
->cRedBits
= mode
->red_bits
;
3312 descr
->cRedShift
= mode
->red_shift
;
3313 descr
->cGreenBits
= mode
->green_bits
;
3314 descr
->cGreenShift
= mode
->green_shift
;
3315 descr
->cBlueBits
= mode
->blue_bits
;
3316 descr
->cBlueShift
= mode
->blue_shift
;
3317 descr
->cAlphaBits
= mode
->alpha_bits
;
3318 descr
->cAlphaShift
= mode
->alpha_shift
;
3322 mode
= &color_modes
[pf
->accum_mode
- 1];
3323 descr
->cAccumBits
= mode
->color_bits
;
3324 descr
->cAccumRedBits
= mode
->red_bits
;
3325 descr
->cAccumGreenBits
= mode
->green_bits
;
3326 descr
->cAccumBlueBits
= mode
->blue_bits
;
3327 descr
->cAccumAlphaBits
= mode
->alpha_bits
;
3330 descr
->cDepthBits
= pf
->depth_bits
;
3331 descr
->cStencilBits
= pf
->stencil_bits
;
3332 descr
->cAuxBuffers
= pf
->aux_buffers
;
3333 descr
->iLayerType
= PFD_MAIN_PLANE
;
3337 /***********************************************************************
3338 * macdrv_wglCopyContext
3340 static BOOL
macdrv_wglCopyContext(struct wgl_context
*src
, struct wgl_context
*dst
, UINT mask
)
3344 TRACE("src %p dst %p mask %x\n", src
, dst
, mask
);
3346 err
= CGLCopyContext(src
->cglcontext
, dst
->cglcontext
, mask
);
3347 if (err
!= kCGLNoError
)
3348 WARN("CGLCopyContext() failed with err %d %s\n", err
, CGLErrorString(err
));
3349 return (err
== kCGLNoError
);
3352 /***********************************************************************
3353 * macdrv_wglCreateContext
3355 static struct wgl_context
*macdrv_wglCreateContext(HDC hdc
)
3358 struct wgl_context
*context
;
3360 TRACE("hdc %p\n", hdc
);
3362 format
= get_dc_pixel_format(hdc
);
3364 if (!is_valid_pixel_format(format
))
3366 ERR("Invalid pixel format %d, expect problems!\n", format
);
3367 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
3371 if (!(context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*context
)))) return NULL
;
3373 context
->format
= format
;
3374 if (!create_context(context
, NULL
))
3376 HeapFree(GetProcessHeap(), 0, context
);
3383 /***********************************************************************
3384 * macdrv_wglDeleteContext
3386 static void macdrv_wglDeleteContext(struct wgl_context
*context
)
3388 TRACE("deleting context %p/%p/%p\n", context
, context
->context
, context
->cglcontext
);
3389 macdrv_dispose_opengl_context(context
->context
);
3390 HeapFree(GetProcessHeap(), 0, context
);
3393 /***********************************************************************
3394 * macdrv_wglGetPixelFormat
3396 static int macdrv_wglGetPixelFormat(HDC hdc
)
3400 format
= get_dc_pixel_format(hdc
);
3402 if (!is_valid_pixel_format(format
)) /* not set yet */
3404 else if (!is_displayable_pixel_format(format
))
3406 /* Non-displayable formats can't be used with traditional WGL calls.
3407 * As has been verified on Windows GetPixelFormat doesn't fail but returns pixel format 1. */
3411 TRACE(" hdc %p -> %d\n", hdc
, format
);
3415 /***********************************************************************
3416 * macdrv_wglGetProcAddress
3418 static PROC
macdrv_wglGetProcAddress(const char *proc
)
3422 if (!strncmp(proc
, "wgl", 3)) return NULL
;
3423 ret
= wine_dlsym(opengl_handle
, proc
, NULL
, 0);
3429 if (dladdr(ret
, &info
))
3430 TRACE("%s -> %s from %s\n", proc
, info
.dli_sname
, info
.dli_fname
);
3432 TRACE("%s -> %p (no library info)\n", proc
, ret
);
3436 WARN("failed to find proc %s\n", debugstr_a(proc
));
3440 /***********************************************************************
3441 * macdrv_wglMakeCurrent
3443 static BOOL
macdrv_wglMakeCurrent(HDC hdc
, struct wgl_context
*context
)
3445 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3446 (context
? context
->cglcontext
: NULL
));
3448 return macdrv_wglMakeContextCurrentARB(hdc
, hdc
, context
);
3451 /**********************************************************************
3452 * macdrv_wglSetPixelFormat
3454 static BOOL
macdrv_wglSetPixelFormat(HDC hdc
, int fmt
, const PIXELFORMATDESCRIPTOR
*descr
)
3456 return set_pixel_format(hdc
, fmt
, FALSE
);
3459 /***********************************************************************
3460 * macdrv_wglShareLists
3462 static BOOL
macdrv_wglShareLists(struct wgl_context
*org
, struct wgl_context
*dest
)
3464 macdrv_opengl_context saved_context
;
3465 CGLContextObj saved_cglcontext
;
3467 TRACE("org %p dest %p\n", org
, dest
);
3469 /* Sharing of display lists works differently in Mac OpenGL and WGL. In Mac OpenGL it is done
3470 * at context creation time but in case of WGL it is done using wglShareLists.
3472 * The approach is to create a Mac OpenGL context in wglCreateContext / wglCreateContextAttribsARB
3473 * and when a program requests sharing we recreate the destination context if it hasn't been made
3474 * current or when it hasn't shared display lists before.
3477 if (dest
->has_been_current
)
3479 WARN("could not share display lists, the destination context has been current already\n");
3482 else if (dest
->sharing
)
3484 WARN("could not share display lists because dest has already shared lists before\n");
3488 /* Re-create the Mac context and share display lists */
3489 saved_context
= dest
->context
;
3490 saved_cglcontext
= dest
->cglcontext
;
3491 dest
->context
= NULL
;
3492 dest
->cglcontext
= NULL
;
3493 if (!create_context(dest
, org
->cglcontext
))
3495 dest
->context
= saved_context
;
3496 dest
->cglcontext
= saved_cglcontext
;
3500 /* Implicitly disposes of saved_cglcontext. */
3501 macdrv_dispose_opengl_context(saved_context
);
3503 TRACE("re-created OpenGL context %p/%p/%p sharing lists with context %p/%p/%p\n",
3504 dest
, dest
->context
, dest
->cglcontext
, org
, org
->context
, org
->cglcontext
);
3506 org
->sharing
= TRUE
;
3507 dest
->sharing
= TRUE
;
3512 /**********************************************************************
3513 * macdrv_wglSwapBuffers
3515 static BOOL
macdrv_wglSwapBuffers(HDC hdc
)
3517 struct wgl_context
*context
= NtCurrentTeb()->glContext
;
3519 TRACE("hdc %p context %p/%p/%p\n", hdc
, context
, (context
? context
->context
: NULL
),
3520 (context
? context
->cglcontext
: NULL
));
3524 SetLastError(ERROR_INVALID_HANDLE
);
3528 macdrv_flush_opengl_context(context
->context
);
3532 static struct opengl_funcs opengl_funcs
=
3535 macdrv_wglCopyContext
, /* p_wglCopyContext */
3536 macdrv_wglCreateContext
, /* p_wglCreateContext */
3537 macdrv_wglDeleteContext
, /* p_wglDeleteContext */
3538 macdrv_wglDescribePixelFormat
, /* p_wglDescribePixelFormat */
3539 macdrv_wglGetPixelFormat
, /* p_wglGetPixelFormat */
3540 macdrv_wglGetProcAddress
, /* p_wglGetProcAddress */
3541 macdrv_wglMakeCurrent
, /* p_wglMakeCurrent */
3542 macdrv_wglSetPixelFormat
, /* p_wglSetPixelFormat */
3543 macdrv_wglShareLists
, /* p_wglShareLists */
3544 macdrv_wglSwapBuffers
, /* p_wglSwapBuffers */
3548 /**********************************************************************
3549 * macdrv_wine_get_wgl_driver
3551 struct opengl_funcs
*macdrv_wine_get_wgl_driver(PHYSDEV dev
, UINT version
)
3553 if (version
!= WINE_WGL_DRIVER_VERSION
)
3555 ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version
, WINE_WGL_DRIVER_VERSION
);
3559 if (!init_opengl()) return (void *)-1;
3561 return &opengl_funcs
;